Android Application - 应用程序之间数据共享

一般来说一个应用程序只能读取自己所创建的数据库, 如果要提供给另外一个应用程序使用, 那就要使用 ContentProvide, 那另一个程序

 

就可以用 ContentResolver 来取得数据并操作.  以下以一个 book manager 的例子来说明, Content Provider 及 Content Resolver 分别是

 

建在两个不同的 packages, 而 Content Resolver 则可以 URI 来操作 Content Provider 所提供的数据.

 

 

1. Construct Custom Content Provider -

 

首先 create a new project, 使用自动生成的 Activety 即可, 我这边名名为 bookcp.java.

 

package proandroid.example.cp; import android.app.Activity; import android.os.Bundle; public class bookcp extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } 

 

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" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 

 

接下来重头戏来了, 创建一个名为 bookprovider 的類别, 使之 extends Content Provider, 且需重载:

 

update(), query(), delete(), insert(), getType()

 

其中 getType 用来判断是操作所有的数据, 或是其中一笔数据.

 

public static final String PROVIDER_NAME = "proandroid.example.provider.Books"; public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/books"); 

 

指定 provider 的路径: proandroid.example.provider.Books(而 package proandroid.exmaple.cp)

 

CONTENT_URI 的路径 content://proandroid.example.provider.Books/books, Content Resolver 就是靠着个路径来取得数据.

 

还有一点很重要的就是: 定义可查询的路径, getType 也用的到.

 

private static final UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "books", BOOKS); uriMatcher.addURI(PROVIDER_NAME, "books/#", BOOK_ID); } 

 

请参考完整的 bookprovider.java

 

package proandroid.example.cp; 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.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; public class bookprovider extends ContentProvider { public static final String PROVIDER_NAME = "proandroid.example.provider.Books"; public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/books"); public static final String _ID = "_id"; public static final String TITLE = "title"; public static final String ISBN = "isbn"; private static final int BOOKS = 1; private static final int BOOK_ID = 2; private static final UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "books", BOOKS); uriMatcher.addURI(PROVIDER_NAME, "books/#", BOOK_ID); } private SQLiteDatabase booksDB; private static final String DATABASE_NAME = "Books.db"; private static final String DATABASE_TABLE = "titles"; private static final int DATABASE_VERSION = 1; private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " (_id integer primary key autoincrement, " + "title text not null, isbn text not null);"; private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { Log.d("DatabaseHelper", "DEBUG: CP create database"); db.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w("Content Provider DB", "Upgrading database from version " + oldVersion + " to " + newVersion); Log.w("COntent Provider DB", ", which will destroy all old data"); db.execSQL("drop table if exists titles"); onCreate(db); } } @Override public int delete(Uri uri, String arg1, String[] arg2) { int count = 0; switch (uriMatcher.match(uri)) { case BOOKS: count = booksDB.delete(DATABASE_TABLE, arg1, arg2); break; case BOOK_ID: String id = uri.getPathSegments().get(1); count = booksDB.delete(DATABASE_TABLE, _ID + "=" + id + (!TextUtils.isEmpty(arg1) ? " AND (" + arg1 + ")" : ""), arg2); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case BOOKS: return "vnd.android.cursor.dir/vnd.example.books "; case BOOK_ID: return "vnd.android.cursor.item/vnd.exmaple.books "; default: throw new IllegalArgumentException("Unsupported URI:" + uri); } } @Override public Uri insert(Uri uri, ContentValues values) { long rowID = booksDB.insert(DATABASE_TABLE, "", values); if (rowID > 0) { Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID); getContext().getContentResolver().notifyChange(_uri, null); return _uri; } throw new SQLException("Failed to insert row into " + uri); } @Override public boolean onCreate() { Context context = getContext(); DatabaseHelper dbHelper = new DatabaseHelper(context); booksDB = dbHelper.getWritableDatabase(); return (booksDB == null)? false:true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder(); sqlBuilder.setTables(DATABASE_TABLE); if (uriMatcher.match(uri) == BOOK_ID) sqlBuilder.appendWhere(_ID + "=" + uri.getPathSegments().get(1)); if (sortOrder == null || sortOrder == "") sortOrder = TITLE; Cursor c = sqlBuilder.query(booksDB, projection, selection, selectionArgs, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count = 0; switch (uriMatcher.match(uri)) { case BOOKS: count = booksDB.update(DATABASE_TABLE, values, selection, selectionArgs); break; case BOOK_ID: count = booksDB.update(DATABASE_TABLE, values, _ID + "=" + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI" + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } }  

 

在 AndroidManifest.xml 声明 Provider 及其路径:

 

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="proandroid.example.cp" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".bookcp" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="bookprovider" android:authorities="proandroid.example.provider.Books" /> </application> <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission> </manifest>  

 

验证数据库生成:

 

 

Android Application - 应用程序之间数据共享_第1张图片

 

 

 

2. Using Custom Content Provider -

 

使用 Content Resolver 来取得 Content Provider 所提供的数据, 在前一篇: Display Contacts 的例子上已经说明, 唯一需要强调的是

 

Custom provider 的 URI 要如何取得: 

 

Uri uri = Uri.parse("content://proandroid.example.provider.Books/books"); 

 

bookmgr.java

 

package proandroid.ex.bookmgr; import java.util.HashMap; import java.util.List; import android.app.ListActivity; import android.net.Uri; import android.os.Bundle; import android.widget.SimpleAdapter; import android.widget.Toast; import java.util.ArrayList; import android.database.Cursor; public class bookmgr extends ListActivity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); List<HashMap<String, String>> items = fillmaps(); SimpleAdapter sa = new SimpleAdapter(this, items, R.layout.listbook, new String[] {"title", "isbn"}, new int[] {R.id.book_title, R.id.book_isbn}); setListAdapter(sa); } public List<HashMap<String, String>> fillmaps() { List<HashMap<String, String>> map = new ArrayList<HashMap<String, String>>(); Cursor cursor = null; try { Uri uri = Uri.parse("content://proandroid.example.provider.Books/books"); cursor = getContentResolver().query(uri, null, null, null, null); if (cursor.moveToFirst()) { do { String booktitle = ""; String bookisbn = ""; booktitle = cursor.getString(cursor.getColumnIndex("title")); bookisbn = cursor.getString(cursor.getColumnIndex("isbn")); Toast.makeText(this, booktitle + "," + bookisbn, Toast.LENGTH_LONG).show(); HashMap<String, String> book = new HashMap<String, String>(); book.put("title", booktitle); book.put("isbn", bookisbn); map.add(book); } while (cursor.moveToNext()); } } finally { if (cursor != null) { cursor.close(); } } return map; } } 

 

 

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" > <TextView android:layout_width="fill 

 

listbook.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"> <TextView android:id="@+id/book_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="15px" /> <TextView android:id="@+id/book_isbn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="200px" android:textSize="15px" /> </LinearLayout> 

 

 

最后 AndroidManifest.xml

 

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="proandroid.ex.bookmgr" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".bookmgr" 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="android.permission.READ_CONTACTS"></uses-permission> </manifest>  

 

新增一笔数据:

 

Android Application - 应用程序之间数据共享_第2张图片

 

3. Program running snapshot (bookmgr) -

 

 

Android Application - 应用程序之间数据共享_第3张图片

 

 

 

你可能感兴趣的:(android,String,layout,application,database,books)