廢話不多說, 情境就是如果Android的process間要共享資源, 通常會實做ContentProvider+SQLite, 再export出適合的uri
如果想要對ContentProvider設定讀/寫的權限, 要從Manifest.xml下手, 以下範例:
ContentProvider(提供讀/寫的權限)
<manifest ...> <application ...> <provider android:name="{PROVIDER_CLASS}" android:authorities="{AUTHORITY}" android:multiprocess="true" android:readPermission="{CONTENTPROVIDER_PACKAGE}.{READ_PERMISSION}" android:writePermission="{CONTENTPROVIDER_PACKAGE}.{WRITE_PERMISSION}> </provider> <activity ...></activity> </application> </manifest>
ContentResolver(設定為只有讀的權限)
<manifest ...> <application ...> <activity ...></activity> </application> <uses-permission android:name="{CONTENTPROVIDER_PACKAGE}.{READ_PERMISSION}" /> <permission-tree android:name="{CONTENTPROVIDER_PACKAGE}.{READ_PERMISSION}" /> <permission android:protectionLevel="dangerous" android:name="{CONTENTPROVIDER_PACKAGE}.{READ_PERMISSION}" /> </manifest>
實例說明:
ContentProvider.apk
/src/demo/content/provider/myObj.java /src/demo/content/provider/myObjProvider.java /src/demo/content/provider/myContentProvider.java /res/main.xml AndroidManifest.xml
myObj.java
package demo.content.provider; import android.net.Uri; import android.provider.BaseColumns; public class myObj implements BaseColumns { public static final String AUTHORITY = "demo.content.provider"; public static final String PATH_SINGLE = "obj/"; public static final String PATH_MULTIPLE = "objs"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH_MULTIPLE); public static final String NAME = "name"; }
myObjProvider.java
package demo.content.provider; import java.util.HashMap; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.provider.BaseColumns; public class myObjProvider extends ContentProvider { private static final int OBJS = 1; private static final int OBJ = 2; public static final String DATABASE_NAME = "ContentProvider.db"; public static final String TABLE_NAME = "obj"; public static final int DATABASE_VERSION = 1; private static UriMatcher URI_MATCHER = null; private static HashMap<String, String> PROJECTION_MAP; private static SQLiteDatabase db; static { URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); URI_MATCHER.addURI(myObj.AUTHORITY, myObj.PATH_MULTIPLE, OBJS); URI_MATCHER.addURI(myObj.AUTHORITY, myObj.PATH_SINGLE, OBJ); PROJECTION_MAP = new HashMap<String, String>(); PROJECTION_MAP.put(BaseColumns._ID, "_id"); PROJECTION_MAP.put(myObj.NAME, "name"); } @Override public boolean onCreate() { DbHelper mDbHelper = new DbHelper(getContext()); return (db = mDbHelper.getWritableDatabase()) != null ? true : false; } // // DbHelper // private static class DbHelper extends SQLiteOpenHelper { private static final String DATABASE_CREATE = "CREATE TABLE " + myObjProvider.TABLE_NAME + "(_id INTEGER PRIMARY KEY, " + "name TEXT UNIQUE NOT NULL)"; public DbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DbHelper.DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } @Override public void onOpen(SQLiteDatabase db) { super.onOpen(db); } } // // implement abstract methods // public int delete(Uri uri, String selection, String[] selectionArgs) { int count = 0; switch (myObjProvider.URI_MATCHER.match(uri)) { case OBJS: count = db.delete(TABLE_NAME, selection, selectionArgs); break; case OBJ: String segment = uri.getPathSegments().get(1); String where = ""; if (selection.length() != 0) { where = " AND (" + selection + ");"; } count = db.delete(TABLE_NAME, "_id=" + segment + where, selectionArgs); break; default: } return count; } public String getType(Uri uri) { return null; } public Uri insert(Uri uri, ContentValues values) { long rowId = 0L; ContentValues cv = null; if (values != null) { cv = new ContentValues(values); } else { cv = new ContentValues(); } rowId = db.insert(TABLE_NAME, null, cv); Uri result = ContentUris.withAppendedId(uri, rowId); return result; } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); String orderBy = null; switch (myObjProvider.URI_MATCHER.match(uri)) { case OBJS: queryBuilder.setTables(myObjProvider.TABLE_NAME); queryBuilder.setProjectionMap(myObjProvider.PROJECTION_MAP); break; case OBJ: queryBuilder.setTables(myObjProvider.TABLE_NAME); queryBuilder.appendWhere("_id=" + uri.getPathSegments().get(1)); break; default: } Cursor c = queryBuilder.query(db, projection, selection, selectionArgs, null, null, orderBy); c.setNotificationUri(this.getContext().getContentResolver(), uri); return c; } public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { /* int count = 0; switch (myObjProvider.URI_MATCHER.match(uri)) { case OBJ: count = db.update(myObjProvider.TABLE_NAME, values, selection, selectionArgs); break; case OBJS: String segment = uri.getPathSegments().get(1); String where = ""; if (!TextUtils.isEmpty(selection)) { where = " AND (" + selection + ")"; } count = db.update(myObjProvider.TABLE_NAME, values, "_id=" + segment + where, selectionArgs); break; default: } return count; */ return 0; } }
myContentProvider.java
package demo.content.provider; import android.app.ListActivity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.SimpleCursorAdapter; public class myContentProvider extends ListActivity { private EditText addName; private Button addButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); addName = (EditText) findViewById(R.id.add_name); addButton = (Button) findViewById(R.id.add_button); addButton.setOnClickListener(new OnClickListener() { public void onClick(View v){ add(); fillAdapter(); } }); } @Override public void onStart() { super.onStart(); fillAdapter(); } private void fillAdapter() { String[] projection = new String[]{myObj._ID, myObj.NAME}; ContentResolver resolver = this.getContentResolver(); Cursor mCursor = resolver.query(myObj.CONTENT_URI, projection, null, null, null); startManagingCursor(mCursor); String[] from = new String[]{myObj.NAME}; int[] to = new int[]{android.R.id.text1}; SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, mCursor, from, to); setListAdapter(adapter); } private void add() { ContentValues cv = new ContentValues(); cv.put(myObj.NAME, addName.getText().toString()); getContentResolver().insert(myObj.CONTENT_URI, cv); } }
main.xml
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:scrollbars="none"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10px" android:layout_marginBottom="5px" android:text="-Add NEW Item-" /> <EditText android:id="@+id/add_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="10px" android:layout_marginBottom="5px" android:text="" /> <Button android:id="@+id/add_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10px" android:layout_marginBottom="15px" android:text="Add" /> <ListView android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="demo.content.provider" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <provider android:name="myObjProvider" android:authorities="demo.content.provider" android:multiprocess="true" android:readPermission="demo.content.provider.PERMISSION.READ" android:writePermission="demo.content.provider.PERMISSION.WRITE"> </provider> <activity android:name=".myContentProvider" 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>
ContentResolver.apk(設定為有讀/寫的權限)
package demo.content.resolver; import android.app.ListActivity; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.content.ContentResolver; import android.content.ContentValues; import android.widget.SimpleCursorAdapter; public class myContentResolver extends ListActivity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String[] projection = new String[]{"_id", "name"}; Uri uri = Uri.parse("content://demo.content.provider/objs"); ContentResolver resolver = this.getContentResolver(); // // insert // ContentValues cv = new ContentValues(); cv.put("name", "insert_value_by_content_resolver"); resolver.insert(uri, cv); // // query // Cursor mCursor = resolver.query(uri, projection, null, null, null); startManagingCursor(mCursor); String[] from = new String[]{"name"}; int[] to = new int[]{android.R.id.text1}; SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, mCursor, from, to); setListAdapter(adapter); } }
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ListView android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="demo.content.resolver" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".myContentResolver" 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> <uses-permission android:name="demo.content.provider.PERMISSION.READ"></uses-permission> <uses-permission android:name="demo.content.provider.PERMISSION.WRITE"></uses-permission> <permission-tree android:name="demo.content.provider.PERMISSION.READ"></permission-tree> <permission-tree android:name="demo.content.provider.PERMISSION.WRITE"></permission-tree> <permission android:protectionLevel="dangerous" android:name="demo.content.provider.PERMISSION.READ"></permission> <permission android:protectionLevel="dangerous" android:name="demo.content.provider.PERMISSION.WRITE"></permission> </manifest>
* myContentProvider.apk here
* myContentResolver.apk here
沒有留言:
張貼留言