Content provider

Content provider

1. Introduction to content provider

Content provider is mainly used to realize the function of data sharing between different applications. It provides a complete mechanism to allow one program to access the data in another program, and the ring can ensure the security of the accessed data

2. Runtime permissions

1. Detailed explanation of Android permission mechanism

AndroidManifest.xml file

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

On the one hand, if the user installs the program on a device lower than 6.0, a reminder of the required permissions will pop up
On the one hand, users can view the permission of any program at any time in the application management interface
The runtime permission function is added to the 6.0 system Users do not need to authorize all permissions at one time when installing the software, but can authorize a permission application during the use of the software

2. Apply for permission when the program is running

Mobile phones lower than Android 6.0 system can work normally

<Button
        android:id="@+id/make_call"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Make Call"/>
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button makeCall=(Button) findViewById(R.id.make_call);
        makeCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    Intent intent=new Intent(Intent.ACTION_CALL);
                    intent.setData(Uri.parse("tel:10086"));
                    startActivity(intent);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

Modify androidmanifest xml

<uses-permission android:name="android.permission.CALL_PHONE"/>

Above 6.0

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button makeCall = (Button) findViewById(R.id.make_call);
        makeCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            //Judge whether the user has been authorized Parameter 1: Context, parameter 2: specific permission name
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                //Apply for permission from the user. Parameter 1: Activity instance, parameter 2: String array, requested permission name, parameter 3: request code
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 1);
                } else {
                    call();
                }
            }
        });
    }
    private void call(){
        try {
            Intent intent=new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case 1:
                if (grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    call();
                }else{
                    Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
}

3. Access data in other programs

1. Basic usage of contentresolver

query

if(cursor!=null){
	while(cursor.moveToNext()){
		String column1=cursor.getString(cursor.getColumnIndex("column1"));
		int column2=cursor.getInt(cursor.getColumnIndex("column2"));
	}
	cursor.close();
}

increase

ContentValues values=new ContentValues();
values.put("column1","text");
values.put("column2",1);
getContentResolver().insert(uri,values);

modify

ContentValues values=new ContentValues();
values.put("column1","");
getContentResolver()..update(uri,values,"column1=? and column2=?",new String[]{"text","1"});

delete

getContentResolver().delete(uri,"column2=?",new String[]{"1"});

2. Read system contact

activity_main.xml

 <ListView
       android:id="@+id/contacts_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
public class MainActivity extends AppCompatActivity {
    ArrayAdapter<String> adapter;
    List<String> contactsList=new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView contactsView=(ListView) findViewById(R.id.contacts_view);
        adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,contactsList);
        contactsView.setAdapter(adapter);
        if(ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
        }else{
        readContacts();
    }
    }
    //ContactsContract. CommonDataKinds. The phone () method parses a content URI string and provides an encapsulated constant content_ URL, that is, use URI The parse () method parses the result
    private void readContacts(){
        Cursor cursor=null;
        try {
            //Query contact data
            cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
            if(cursor!=null){
                while (cursor.moveToNext()){
                    //Get contact name
                    @SuppressLint("Range") String displayName=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    //Get contact phone number
                    @SuppressLint("Range") String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contactsList.add(displayName+"\n"+number);
                }
                adapter.notifyDataSetChanged();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(cursor!=null){
                cursor.close();
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch(requestCode){
            case 1:
                if (grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    readContacts();
                }else{
                    Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
}

AndroidManifest.xml

<uses-permission android:name="android.permission.READ_CONTACTS"/>

4. Create your own content provider

1. Steps

public class MyProvider extends ContentProvider {
//Initialize the content provider The database creation and upgrade operations are usually completed here. A return of true indicates that the initialization of the content provider is successful, and a return of false indicates failure
    @Override
    public boolean onCreate() {
        return false;
    }
//Query data from the content provider The uri parameter is used to determine the table, the projection parameter is used to determine which columns to query, the selection and selectionArgs parameters are used to constrain which rows to query, the sortOrder parameter is used to sort the results, and the query results are stored and returned in the Cursor object
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        return null;
    }
//The corresponding MIME type is returned according to the incoming content URL    
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }
//Add a piece of data to the content provider The url parameter is used to determine the data in the table to be updated. The new data is saved in the values parameter. The selection and selectionArgs parameters are used to restrict the rows to be updated. The number of affected rows will be used as the return value
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        return null;
    }
//Delete data from the content provider The uri parameter is used to determine the data in a table. The selection and selectionArgs parameters are used to restrict the deletion of those rows. The number of deleted rows is returned as the return value
    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }
//Update existing data in the content provider The uri parameter is used to determine the data in the table to be updated. The new data is saved in the values parameter. The selection and selectionArgs parameters are used to restrict the rows to be updated. The number of affected rows will be returned as the return value
    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }
}

A standard Uri writing method
content"//com.example.app.provider/table1 indicates that the caller expects to access the data in the table1 table of com.example.app
content"//com.example.app.provider/table1/1: indicates that the caller expects to access the data with id 1 in the table1 table of com.example.app
*: represents any string that matches any length
#: indicates a number that matches any length
A content URL format that can match any table:
content"//com.example.app.provider/*
A content URL format that can match any row of data in the table:
content"//com.example.app.provider/table/#
modify

public class MyProvider extends ContentProvider {
public static final int TABLE1_DIR=0;
public static final int TABLE1_ITEM=1;
public static final int TABLE2_DIR=2;
public static final int TABLE2_ITEM=3;
public static UriMatcher uriMatcher;
static {
    uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI("com.example.app.provider","table1",TABLE1_DIR);
    uriMatcher.addURI("com.example.app.provider","table1/#",TABLE1_ITEM);
    uriMatcher.addURI("com.example.app.provider","table2",TABLE2_DIR);
    uriMatcher.addURI("com.example.app.provider","table2/#",TABLE2_ITEM);
}
...
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        switch (uriMatcher.match(uri)){
            case TABLE1_DIR:
                //Query all data in table1 table
                break;
            case  TABLE1_ITEM:
                //Query single data in table1 table
                break;
            case TABLE2_DIR:
                //Query all data in table2 table
                break;
            case TABLE2_ITEM:
                //Query a single piece of data in table2 table
                break;
            default:
                break;
        }
        ...
    }
    ...
}

MIME string format corresponding to a content URL:
1. Must start with vnd
2. If the content URL ends with a path, it is followed by Android cursor. Dir /, followed by Android if the content URL ends with id cursor. item/.
3. Finally connect vnd< authority>,<path>
The corresponding MIME type of content"//com.example.app.provider/table1 can be written as
vnd.android.cursor.dir/vnd.com.example.app.provider.table1
The corresponding MIME type of content"//com.example.app.provider/table1/1 can be written as
vnd.android.cursor.item/vnd.com.example.app.provider.table1

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        switch (uriMatcher.match(uri)) {
            case TABLE1_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
            case TABLE1_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
            case TABLE2_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2";
            case TABLE2_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table2";
            default:
                break;
        }
        return null;
    }

2. Realize cross program data sharing

public class DatabaseProvider extends ContentProvider {
    public static final int BOOK_DIR = 0;
    public static final int BOOK_ITEM = 1;
    public static final int CATEGORY_DIR = 2;
    public static final int CATEGORY_ITEM = 3;
    public static final String AUTHORITY = "com.example.databasetest.provider";
    private static UriMatcher uriMatcher;
    private MyDatabaseHelper dbHelper;

    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
        uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
        uriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
        uriMatcher.addURI(AUTHORITY, "category/#", CATEGORY_ITEM);
    }

    @Override
    public boolean onCreate() {
        dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        // Query data
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = null;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                cursor = db.query("Book", projection, "id = ?", new String[] { bookId }, null, null, sortOrder);
                break;
            case CATEGORY_DIR:
                cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                cursor = db.query("Category", projection, "id = ?", new String[] { categoryId }, null, null, sortOrder);
                break;
            default:
                break;
        }
        return cursor;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // Add data
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        Uri uriReturn = null;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
            case BOOK_ITEM:
                long newBookId = db.insert("Book", null, values);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
                break;
            case CATEGORY_DIR:
            case CATEGORY_ITEM:
                long newCategoryId = db.insert("Category", null, values);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
                break;
            default:
                break;
        }
        return uriReturn;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        // Update data
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int updatedRows = 0;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                updatedRows = db.update("Book", values, selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                updatedRows = db.update("Book", values, "id = ?", new String[] { bookId });
                break;
            case CATEGORY_DIR:
                updatedRows = db.update("Category", values, selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                updatedRows = db.update("Category", values, "id = ?", new String[] { categoryId });
                break;
            default:
                break;
        }
        return updatedRows;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Delete data
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int deletedRows = 0;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                deletedRows = db.delete("Book", selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                deletedRows = db.delete("Book", "id = ?", new String[] { bookId });
                break;
            case CATEGORY_DIR:
                deletedRows = db.delete("Category", selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                deletedRows = db.delete("Category", "id = ?", new String[] { categoryId });
                break;
            default:
                break;
        }
        return deletedRows;
    }

    @Override
    public String getType(Uri uri) {
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.databasetest. provider.book";
            case BOOK_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.databasetest. provider.book";
            case CATEGORY_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.databasetest. provider.category";
            case CATEGORY_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.databasetest. provider.category";
        }
        return null;
    }

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add To Book"
        android:id="@+id/add_data"
        tools:ignore="MissingConstraints" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update Book"
        android:id="@+id/update_data"
        tools:ignore="MissingConstraints" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Delete From Book"
        android:id="@+id/delete_data"
        tools:ignore="MissingConstraints" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Query From Book"
        android:id="@+id/query_data"
        tools:ignore="MissingConstraints" />
</LinearLayout>
public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });
        Button addData = (Button) findViewById(R.id.add_data);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                // Start assembling the first data
                values.put("name", "The Da Vinci Code");
                values.put("author", "Dan Brown");
                values.put("pages", 454);
                values.put("price", 16.96);
                db.insert("Book", null, values); // Insert first data
                values.clear();
                // Start assembling the second data
                values.put("name", "The Lost Symbol");
                values.put("author", "Dan Brown");
                values.put("pages", 510);
                values.put("price", 19.95);
                db.insert("Book", null, values); // Insert second data
            }
        });
        Button updateData = (Button) findViewById(R.id.update_data);
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("price", 10.99);
                db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" });
            }
        });
        Button deleteButton = (Button) findViewById(R.id.delete_data);
        deleteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.delete("Book", "pages > ?", new String[] { "500" });
            }
        });
        Button queryButton = (Button) findViewById(R.id.query_data);
        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                // Query all data in the Book table
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        // Traverse the Cursor object, take out the data and print
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        String author = cursor.getString(cursor.getColumnIndex("author"));
                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                        double price = cursor.getDouble(cursor.getColumnIndex("price"));
                        Log.d("MainActivity", "book name is " + name);
                        Log.d("MainActivity", "book author is " + author);
                        Log.d("MainActivity", "book pages is " + pages);
                        Log.d("MainActivity", "book price is " + price);
                    } while (cursor.moveToNext());
                }
                cursor.close();
            }
        });
    }

}

Keywords: Java Android Android Studio

Added by dbomb101 on Sat, 22 Jan 2022 03:09:03 +0200