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:
- AddURI is responsible for adding URIs to UriMatcher for unified management, and can tag different URIs for easy switch
- 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
- Delete Indicates the number of deletions
- 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
- Insert Returns the Uri of the inserted element
- OnCreate is called when it is first created, is responsible for initialization, and returns true on success
- Query Returns a Cursor as a result
- 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:
- Registered uri
- Class in the oncreate method
- Override the getType method to parse the MIME corresponding to the URI
- 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