ContentProvider
ContentProvider <--> Activity
com.example.cp01 <--> com.example.cp02
ContentProvider Application (com.example.cp01)
manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.cp01"> <application android:allowBackup="true" android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:theme="@style/AppTheme"> <provider android:authorities="com.example.cp01" android:name=".MyContentProvider" android:exported="true"/> <!-- not secure --> </application> </manifest>
ContentProvider
package com.example.cp01; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentValues; import android.database.CharArrayBuffer; import android.database.ContentObserver; import android.database.Cursor; import android.database.DataSetObserver; import android.net.Uri; import android.os.Bundle; import android.util.Log; public class MyContentProvider extends ContentProvider { @Override public boolean onCreate() { Log.i("XXX", "onCreate"); return false; } @Override public String getType(Uri uri) { Log.i("XXX" , "getType:" + uri); return null; } @Override public Uri insert(Uri uri, ContentValues contentValues) { Log.i("XXX" , "insert:" + uri + ", cv:" + contentValues); return Uri.parse("insert"); } @Override public int delete(Uri uri, String s, String[] strings) { Log.i("XXX" , "delete:" + uri); return 1; } @Override public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { Log.i("XXX" , "update:" + uri+ ", cv:" + contentValues); return 2; } @Override public Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) { Log.i("XXX" , "query:" + uri); Cursor c = new Cursor() { @Override public int getCount() { return 0; } @Override public int getPosition() { return 0; } @Override public boolean move(int i) { return false; } @Override public boolean moveToPosition(int i) { return false; } @Override public boolean moveToFirst() { return false; } @Override public boolean moveToLast() { return false; } @Override public boolean moveToNext() { return false; } @Override public boolean moveToPrevious() { return false; } @Override public boolean isFirst() { return false; } @Override public boolean isLast() { return false; } @Override public boolean isBeforeFirst() { return false; } @Override public boolean isAfterLast() { return false; } @Override public int getColumnIndex(String s) { return 0; } @Override public int getColumnIndexOrThrow(String s) throws IllegalArgumentException { return 0; } @Override public String getColumnName(int i) { return null; } @Override public String[] getColumnNames() { return new String[0]; } @Override public int getColumnCount() { return 0; } @Override public byte[] getBlob(int i) { return new byte[0]; } @Override public String getString(int i) { return null; } @Override public void copyStringToBuffer(int i, CharArrayBuffer charArrayBuffer) { } @Override public short getShort(int i) { return 0; } @Override public int getInt(int i) { return 0; } @Override public long getLong(int i) { return 0; } @Override public float getFloat(int i) { return 0; } @Override public double getDouble(int i) { return 0; } @Override public int getType(int i) { return 0; } @Override public boolean isNull(int i) { return false; } @Override public void deactivate() { } @Override public boolean requery() { return false; } @Override public void close() { Log.i("XXX", "close !"); } @Override public boolean isClosed() { return false; } @Override public void registerContentObserver(ContentObserver contentObserver) { } @Override public void unregisterContentObserver(ContentObserver contentObserver) { } @Override public void registerDataSetObserver(DataSetObserver dataSetObserver) { } @Override public void unregisterDataSetObserver(DataSetObserver dataSetObserver) { } @Override public void setNotificationUri(ContentResolver contentResolver, Uri uri) { } @Override public Uri getNotificationUri() { return null; } @Override public boolean getWantsAllOnMoveCalls() { return false; } @Override public Bundle getExtras() { return null; } @Override public Bundle respond(Bundle bundle) { return null; } }; return c; } }
Activity Application (com.example.cp02)
manifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.cp02" > <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Activity
package com.example.cp02; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Uri uri = Uri.parse("content://com.example.cp01"); ContentValues values = new ContentValues(); values.put("key-a", "val-a"); values.put("key-b", "val-b"); values.put("key-c", "val-c"); values.put("key-d", "val-d"); ContentResolver cr = getContentResolver(); Cursor c = cr.query(uri, null, null, null, null); Log.i("caller", "query:" + c); c.close(); Uri i = cr.insert(uri, values); Log.i("caller", "insert:" + i); int u = cr.update(uri, values, null, null); Log.i("caller", "update:" + u); int d = cr.delete(uri, null, null); Log.i("caller", "delete:" + d); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
Exception
@Override public int delete(Uri uri, String s, String[] strings) { Log.i("XXX" , "delete:" + uri); throw new RuntimeException("exception !"); //return 1; }
Activity log
10335-10335/com.example.cp02 I/caller﹕ query:android.content.ContentResolver$CursorWrapperInner@41d97740 10335-10335/com.example.cp02 I/caller﹕ insert:insert 10335-10335/com.example.cp02 I/caller﹕ update:2 10335-10335/com.example.cp02 I/caller﹕ delete:0 <---- ******
ContentProvider log
10349-10349/com.example.cp01 I/ActivityThread﹕ Pub com.example.cp01: com.example.cp01.MyContentProvider 10349-10349/com.example.cp01 I/XXX﹕ onCreate 10349-10361/com.example.cp01 I/XXX﹕ query:content://com.example.cp01 10349-10360/com.example.cp01 I/XXX﹕ close ! 10349-10361/com.example.cp01 I/XXX﹕ insert:content://com.example.cp01, cv:key-c=val-c key-b=val-b key-a=val-a key-d=val-d 10349-10360/com.example.cp01 I/XXX﹕ update:content://com.example.cp01, cv:key-c=val-c key-b=val-b key-a=val-a key-d=val-d 10349-10361/com.example.cp01 I/XXX﹕ delete:content://com.example.cp01 10349-10361/com.example.cp01 E/JavaBinder﹕ *** Uncaught remote exception! (Exceptions are not yet supported across processes.) <---- ****** java.lang.RuntimeException: exception ! at com.example.cp01.MyContentProvider.delete(MyContentProvider.java:37) at android.content.ContentProvider$Transport.delete(ContentProvider.java:228) at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:188) at android.os.Binder.execTransact(Binder.java:351) at dalvik.system.NativeStart.run(Native Method)