A Preliminary Study of Android's ContentProvider

Introduction to this section:

This section brings you the last of the four major components of Android - ContentProvider (content provider). Some readers may have questions, "Doesn't Android have five major components? Is there an Intent?" Yes , Intent is also very important, but he just maintains the link between these components! Intent we will explain in the next chapter! Speaking of this ContentProvider, when will we use him? There are two types:

  • 1. We want to access other applications in our own application, or some data exposed to us by ContentProvider, such as mobile phone contacts, text messages, etc.! We want to read or modify these data, which requires the use of ContentProvider!
  • 2. For our own application, we want to expose some of our own data for other applications to read or operate. We can also use ContentProvider. In addition, we can choose the data to be exposed, which avoids the loss of our private data. Give way!

It seems to be cheating, but it is actually very simple to use. Let’s learn about ContentProvider~  Official document : ContentProvider  In this section, we will explain the concept of ContentProvider, and write some examples of commonly used system ContentProvider for you, as well as your own Define ContentProvider!


1. ContentProvider concept explanation:


2. Use the ContentProvider provided by the system

In fact, many times we use ContentProvider not to expose our own data, but more often to  read information from other applications through ContentResolver . The most commonly used one is to read system APP, information, contacts, multimedia information, etc.! If you want to call these ContentProviders, you need to check the relevant API information yourself! In addition, different versions may correspond to different URLs! Here is how to get the URL and the corresponding database table fields. Here we take the most commonly used contacts as an example. Others can be googled by yourself~ ① Go
to the system source code file: all-src.rar -> TeleponeProvider -> AndroidManifest.xml to find the corresponding API
②Open the file explorer/data/data/com.android.providers.contacts/databases/contact2.db of the emulator and use the SQLite graphics tool to view after exporting, three core tables: raw_contact table , data table , mimetypes table !
Here are some basic operation examples:


1) Simply read the inbox information:

Core code:

private void getMsgs(){
    Uri uri = Uri.parse("content://sms/");
    ContentResolver resolver = getContentResolver();
    //获取的是哪些列的信息
    Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null);
    while(cursor.moveToNext())
    {
        String address = cursor.getString(0);
        String date = cursor.getString(1);
        String type = cursor.getString(2);
        String body = cursor.getString(3);
        System.out.println("地址:" + address);
        System.out.println("时间:" + date);
        System.out.println("类型:" + type);
        System.out.println("Content:" + body);
        System.out.println("======================");
    }
    cursor.close();
}

Don't forget to add permission to read the inbox to AndroidManifest.xml:

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

operation result:

Some running results are as follows:


2) Simply insert a message into the inbox

Core code:

private void insertMsg() {
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://sms/");
    ContentValues conValues = new ContentValues();
    conValues.put("address", "123456789");
    conValues.put("type", 1);
    conValues.put("date", System.currentTimeMillis());
    conValues.put("body", "no zuo no die why you try!");
    resolver.insert(uri, conValues);
    Log.e("HeHe", "短信插入完毕~");
}

operation result:

Precautions:

The above code can realize the function of writing text messages below 4.4, but it cannot be written on 5.0. The reason is: starting from 5.0, software other than the default SMS application cannot send text messages in the form of writing to the text message database!


3) Simply read phone contacts

Core code:

private void getContacts(){ 
    //①Query the raw_contacts table to obtain the id of the contact 
    ContentResolver resolver = getContentResolver(); 
    Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; 
    //Query the contact data 
    cursor = resolver.query(uri, null , null, null, null); 
    while(cursor.moveToNext()) 
    { 
        //Get contact name, phone number 
        String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); 
        String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
        System.out.println("Name:" + cName); 
        System.out.println("Number:" + cNum); 
        System.out.println("======================"); 
    } 
    cursor.close (); 
}

Don't forget to add permission to read contacts:

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

operation result:

Some running results are as follows:


4) Query the contact information of the specified phone

Core code:

private void queryContact(String number){
        Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number);
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null);
        if (cursor.moveToFirst()) {
            String name = cursor.getString(0);
            System.out.println(number + "对应的联系人名称:" + name);
        }
    cursor.close();
}

operation result:


5) Add a new contact

Core code:

private void AddContact() throws RemoteException, OperationApplicationException { 
    //Use transaction to add contact 
    Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); 
    Uri dataUri = Uri.parse("content:/ /com.android.contacts/data"); 

    ContentResolver resolver = getContentResolver(); 
    ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); 
    ContentProviderOperation op1 = ContentProviderOperation.newInsert(uri) 
            .withValue("account_name", n ull) 
            .build(); 
    operations.add(op1); 

    //name, number, zip code in sequence 
    ContentProviderOperation op2 = ContentProviderOperation.newInsert(dataUri)
            .withValueBackReference("raw_contact_id", 0)
            .withValue("mimetype", "vnd.android.cursor.item/name")
            .withValue("data2", "Coder-pig")
            .build();
    operations.add(op2);

    ContentProviderOperation op3 = ContentProviderOperation.newInsert(dataUri)
            .withValueBackReference("raw_contact_id", 0)
            .withValue("mimetype", "vnd.android.cursor.item/phone_v2")
            .withValue("data1", "13798988888")
            .withValue("data2", "2")
            .build();
    operations.add(op3);

    ContentProviderOperation op4 = ContentProviderOperation.newInsert(dataUri)
            .withValueBackReference("raw_contact_id", 0) 
            .withValue("mimetype", "vnd.android.cursor.item/email_v2") 
            .withValue("data1", "[email protected]") 
            .withValue("data2", "2") 
            .build(); 
    operations.add(op4); 
    //Add the above content to the phone contacts~ 
    resolver.applyBatch("com.android.contacts", operations); 
    Toast.makeText(getApplicationContext() , "Added successfully", Toast.LENGTH_SHORT).show(); 
}

operation result:

Don't forget about permissions:

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

3. Custom Content Provider

We rarely define ContentProvider by ourselves, because we often don’t want the data of our application to be exposed to other applications. Even so, it is still necessary to learn how to use ContentProvider. There is one more way of data transmission, right~ this is
before Draw a flowchart:

Next, let's implement it step by step:

Before we start, we need to create a database creation class (database content will be discussed later~):

DBOpenHelper.java

public class DBOpenHelper extends SQLiteOpenHelper {

    final String CREATE_SQL = "CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREMENT,name)";
    
    public DBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, name, null, 1);
    }

    
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_SQL);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub

    }

}

Step 1 : Customize the ContentProvider class, implement onCreate(), getType(), and rewrite the corresponding addition, deletion, modification and query methods according to requirements:

NameContentProvider.java

public class NameContentProvider extends ContentProvider { 

    //Initialize some constants 
     private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);         
     private DBOpenHelper dbOpenHelper; 
    
    //For the convenience of using UriMatcher directly, here addURI, then call Matcher to match 
     
     static{   
         matcher.addURI ("com.jay.example.providers.myprovider", "test", 1); 
     }   
     
    @Override 
    public boolean onCreate() { 
        dbOpenHelper = new DBOpenHelper(this.getContext(), "test.db", null, 1) ; 
        return true; 
    } 

    @Override 
    public Cursor query(Uri uri, String[] projection, String selection, 
            String[] selectionArgs, String sortOrder) {
        return null; 
    } 

    @Override 
    public String getType(Uri uri) { 
        return null; 
    } 

    @Override 
    public Uri insert(Uri uri, ContentValues ​​values) { 
        
        switch(matcher.match(uri)) 
        { 
        //Open the database and put it inside Want to prove that the uri match is complete 
        case 1: 
            SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); 
            long rowId = db.insert("test", null, values); 
            if(rowId > 0) 
            { 
                //Append after the existing Uri ID 
                Uri nameUri = ContentUris.withAppendedId(uri, rowId); 
                //Notification data has changed
                getContext().getContentResolver().notifyChange(nameUri, null);
                return nameUri;
            }
        }
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        return 0;
    }

}

Step 2 : Register ContentProvider in AndroidManifest.xml:

<!--The attributes are: fully qualified class name, URI for matching, whether to share data--> 
<provider android:name="com.jay.example.bean.NameContentProvider" 
            android:authorities="com.jay .example.providers.myprovider" 
            android:exported="true" />

Ok, the ContentProvider part is done!


Next, create a new project, let's implement the ContentResolver part, we insert a piece of data directly by clicking the button:

MainActivity.java

public class MainActivity extends Activity {

    private Button btninsert;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        btninsert = (Button) findViewById(R.id.btninsert);
        
        //读取contentprovider 数据  
        final ContentResolver resolver = this.getContentResolver();
        
        
        btninsert.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                 ContentValues values = new ContentValues();
                 values.put("name", "测试");
                 Uri uri = Uri.parse("content://com.jay.example.providers.myprovider/test");
                resolver.insert(uri, values);
                Toast.makeText(getApplicationContext(), "数据插入成功", Toast.LENGTH_SHORT).show();
                
            }
        });
       
    }
}

how to use?  Well, the code is quite simple, first run the project as ContentProvider, and then run the project of ContentResolver, click the button to insert a piece of data, then open the file explorer to take out the db database of ContentProvider, and use the graphic viewing tool to view the inserted data , due to time constraints, the results will not be demonstrated~


4. Monitor the data changes of ContentProvider through ContentObserver

Usage guide :

After running the program, let it hang aside. After receiving the text message, you can see the content of the message on the logcat. You can change Activtiy to Service according to your own needs, and do this kind of thing in the background~

Guess you like

Origin blog.csdn.net/leyang0910/article/details/131332444