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~