Introduction to the

ContentProvider Is a standard API for exchanging data between different apps. For example, if this is a Notepad APP, other applications that want to access your APP’s data (within reason) can use ContentProvider.

A ContentProvider provides the content of a web site, then has a URI to access it, and the user has a browser, the ContentResolver, to fetch the data.

The basic use

Note the authorities attribute (discussed later). Then we can see that there are many ways to do this. We will override the INSERT method first:


  @Override
public Uri insert(Uri uri, ContentValues values) {
System.out.println("-------insert-------");
return null;
}

Copy the code

Create a ContentResolver in another APP for “browsing data”


mContentResolver = getContentResolver();
mContentResolver.insert(Uri.parse("content://hao.win/"), contentValues);

Copy the code

Insert in the first APP is called:

This is the basic usage, and we see that the ContentResolver insert call is essentially a call to the insert method of the first APP

Uri

Common Uri: content: / / haotianyi. Win/word / 1 / name, to explore the meaning of each part below:

ContentProvider: // Similar to the Internet protocol in urls, ContentProvider default protocol is content

Haotianyi. win is equivalent to a domain name

Word stands for resources

1 represents the record whose ID is 1 under the Word resource

Name represents the name field of the record whose ID is 1

Note that # stands for wildcard, which can represent any field

To manipulate URIs, there is a URI class to manipulate strings: uri.parse

There is also a ContentUris class for manipulating URIs:

ContentUris. WithAppendedId (uri, rowID) add ID to uri ContentUris. ParseId (uri) parsing out the ID from the uriCopy the code

Specific operation

When a Uri can carry information, there should be a class that handles that information. UriMatcher manages the Uri and has only two methods:

  1. AddURI is responsible for adding URIs to UriMatcher for unified management, and can tag different URIs for easy switch
  2. Determines the identifier based on the previously registered Uri, returns -1 if there is no match

Using the instance

UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); matcher.addURI("hao.win","word",0); matcher.addURI("hao.win","word/1",1); Parse ("content://hao.win/word/")); / / the return value 1 the matcher. Match (Uri. Parse (" content: / / hao. Win/word / 1 / "));Copy the code

Notice that the full name is written in uri. parse

ContentProvider,

Common methods

When inheriting from the ContentProvider class, the system automatically generates the following methods:

Constructor does not say

  1. Delete Indicates the number of deletions
  2. GetType determines the MIME type of the Uri, that is, the number of elements corresponding to the Uri. One element starts with vnd.android.cursor.item and multiple elements start with vnd.android.cursor.dir
  3. Insert Returns the Uri of the inserted element
  4. OnCreate is called when it is first created, is responsible for initialization, and returns true on success
  5. Query Returns a Cursor as a result
  6. Update: Returns the number of update records

Instance – Shared data

Create two apps, one for generating data and providing ContentProvider, and the other for calling:

Create a constant

Public static Final String AUTHORITY = "hao.win"; // Define a static inner class, Public static Final Class Word{// Define three columns allowed by Content. Public static final String _ID = "_id"; public static final String WORD = "word"; public static final String DETAIL = "detail"; Public static final Uri HAO_CONTENTS = uri.parse (" Content ://"+AUTHORITY+"/"+"/words"); public static final Uri HAO_CONTENT = Uri.parse("content://"+AUTHORITY+"/"+"/word"); }}Copy the code

Notice how this puts a related variable in a separate inner class

Create MyDatabaseHelper


public class MyDatabaseHelper extends SQLiteOpenHelper {
 
public MyDatabaseHelper(Context context) {
super(context, "test.db", null, 1);
}
 
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
 
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table main(_id integer primary key autoincrement,word,detail)");
}
 
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
 
}
}
Copy the code

Notice the first constructor, which is much simpler

Perfect MyContentProvider

This is interesting:

  1. Registered uri
  2. Class in the oncreate method
  3. Override the getType method to parse the MIME corresponding to the URI
  4. Override the corresponding method

Registered Uri


private static UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
private static final int WORDS = 1;
private static final int WORD = 2;
 
static {
sMatcher.addURI(Conf.AUTHORITY, "words", WORDS);
sMatcher.addURI(Conf.AUTHORITY, "word/#", WORD);
}

Copy the code

This is a static block of code

Class in the onCreate method


  @Override
public boolean onCreate() {
mDatabaseHelper = new MyDatabaseHelper(this.getContext());
return true;
}
Copy the code

Notice that return true

Rewrite the getType

@Override public String getType(Uri uri) { switch (sMatcher.match(uri)) { case WORD: return "vdn.android.cursor.item/hao.win"; case WORDS: return "vdn.android.cursor.dir/hao.win"; Default: throw new IllegalArgumentException(" unknown uri1"); }}Copy the code

Binding a URI to an int in this process has obvious benefits, especially when using swith

Override the corresponding method


 @Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase database = mDatabaseHelper.getWritableDatabase();
switch (sMatcher.match(uri)){
case WORDS:
long rowID = database.insert("main", Conf.Word._ID, values);
if (rowID>0){
Uri withAppendedId = ContentUris.withAppendedId(uri, rowID);
 
getContext().getContentResolver().notifyChange(withAppendedId,null);
System.out.println("------insert-------");
return withAppendedId;
}
break;
}
return null;
}

Copy the code

Note: getContext().getContentResolver().notifyChange(withAppendedId,null) notifies data of changes, where observer mode can be used

Called in ContentResolver


 ContentValues contentValues = new ContentValues();
contentValues.put("word","nihao");
mContentResolver.insert(Uri.parse("content://hao.win/words"), contentValues);

Copy the code

Notice that the keyword in the put method of ContentValues is the column of the data table (the column you want to insert)

When this method is called:

Field – Read contacts

The first constants and classes related to system ContenProvider are in the Android. provider package:

Clear the uri

ContactsContract. Contacts. _ID is used to obtain the contact id

String conatctID = cursor. Get String (cursor. GetColumnIndex (ContactsContract. Contacts. _ID)) to obtain the contact idCopy the code

ContactsContract. Contacts. CONTENT_URI management contact uri

Cursor Cursor = mContentResolver. Query (ContactsContract. Contacts. CONTENT_URI, null, null, null, null) query to get all of the ContactsCopy the code

ContactsContract. Contacts. DISPLAY_NAME contact’s name



String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

Copy the code

ContactsContract.Com monDataKinds. Phone. NUMBER/Phone NUMBER

/ / get the Phone number String number = phones. Get String (phones. GetColumnIndex (ContactsContract.Com monDataKinds. Phone. Number));Copy the code

ContactsContract.Com monDataKinds. Email. Email address DATA

String emailAdress = emails. Get String (emails. GetColumnIndex (ContactsContract.Com monDataKinds. Email. DATA)) to obtain the contact Email addressCopy the code

All the code

public class MainActivity extends AppCompatActivity { private ContentResolver mContentResolver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContentResolver = getContentResolver(); } public void start(View view) { Cursor cursor = mContentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); while (cursor.moveToNext()) { String conatctID = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));  String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); / / according to the id telephone contact Cursor Cursor phones = getContentResolver () query (ContactsContract.Com monDataKinds. Phone. CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + conatctID, null, null); // Since there may be multiple phone numbers, use a list ArrayList<String> numbers = new ArrayList<>(); While (phone.movetonext ()) {// Get the phone number String number = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); numbers.add(number); } phones.close(); // Use the contact id as above, Get Email cursor cursor emails = getContentResolver () query (ContactsContract.Com monDataKinds. Email. CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=" + conatctID, null, null); List ArrayList<String> emaiList = new ArrayList<>(); while (emails.moveToNext()) { String emailAdress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); emaiList.add(emailAdress); } AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); Builder.settitle (" contact ").setMessage(name + "----" + printList(emaiList) + "-- "+ printList(numbers)).show(); Private string printList(list list) {private String printList(list list) {private String printList(list list) {private String printList(list list) {private String printList(list list) {private String printList(list list) {private String printList(list list) {StringBuilder Builder = new StringBuilder(); for (int i = 0; i < list.size(); i++) { String o = (String) list.get(i); builder.append(o); } return builder.toString(); }}Copy the code

Note permissions:

Field – Insert contacts

Train of thought

Get the ID of the contact you want to add (by inserting an empty piece of data), then insert the name, phone number, and Email

code

Public void insert(View View) {public void insert(View View) {ContentValues values = new ContentValues(); / / insert a null uri uri to get the latest contacts rawUri = getContentResolver (), insert (ContactsContract. RawContacts. CONTENT_URI, values). long rawID = ContentUris.parseId(rawUri); / * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- name -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * / / / set the contact id values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawID); / / set the content type is name values. The put (ContactsContract. RawContacts. Data. The MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); / / set the name values. The put (ContactsContract.Com monDataKinds. StructuredName. GIVEN_NAME, "huang"); / / the real insert Data getContentResolver () insert (ContactsContract. Data. CONTENT_URI, values). // Set values. Clear (); / * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the first telephone number -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * / / / set specific insert id values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawID); / / set type values. The put (ContactsContract. RawContacts. Data. The MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "1234567890"); /*values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "1000000000"); Add unlock so this value overrides the previous value, Does not have two values * / / / set to mobile Phone values. The put (ContactsContract.Com monDataKinds. Phone. The TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values); values.clear(); / / want to the same contact cat as long as the two telephone number on copy of this code is ok / * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the second telephone number -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * / / / set specific insert id values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawID); / / set type values. The put (ContactsContract. RawContacts. Data. The MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "1000000000"); /*values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "1000000000"); Add unlock so this value overrides the previous value, Does not have two values * / / / set to mobile Phone values. The put (ContactsContract.Com monDataKinds. Phone. The TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values); values.clear(); /*--------------------email------------------------*/ values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawID); values.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE); values.put(ContactsContract.CommonDataKinds.Email.DATA, "[email protected]"); getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values); }Copy the code

Practice – Managing multimedia

Get all the pictures

ArrayList<String> names = new ArrayList<>(); ArrayList<String> descs = new ArrayList<>(); / / get all pictures the uri of the Cursor media = getContentResolver () query (MediaStore. Images. Media. EXTERNAL_CONTENT_URI, null, null, null, null); While (media.movetonext ()) {// Get the name of the image String name = media.getString(media.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)); names.add(name); / / get the picture DESCRIPTION String desc = media. Get String (media. GetColumnIndex (MediaStore. Images. Media. The DESCRIPTION)); descs.add(desc); } AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); Builder.settitle (" image ").setMessage(printList(names) + "-- "+ printList(descs)).show();Copy the code

Add images

Add an image from drawable to the picture of the system:

ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "hty"); ContentValues. Put (MediaStore. Images. Media. The DESCRIPTION, "hao providence"); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/png"); // Only the contentProvider registered to the system but still no insert = Uri for the file getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.hty); OutputStream = getContentResolver(). OpenOutputStream (insert); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); outputStream.close(); } catch (Exception e) { e.printStackTrace(); }Copy the code

Note that the URIs are in Images:

Observer model

To be continued