2012年5月21日 星期一

Android 開發筆記 - 為自己的 app 建立 Content Provider

MyContentProvider


整個流程在 Android 官網(Create Your Content Provider)已經有很豐富的介紹,在此筆記一下 :P 加快自己往後回憶。


新增自己的 content provider 的用亦是供別人來存取自身 app 的資料(大多是 SQLite 操作),而實做流程並不難,但有一些小事要留意:



  1. 假設你的 app 的 package name 為 com.example.study,實做為 Content Provider Class 為 MyContentProvider。

  2. 首先,建立一個 app 名為 MyContentProvider,但不需要 Activity,新增完後,在新增一個 class 名為 MyContentProvider 並繼承 android.content.ContentProvider。

  3. 由於 content provider 給予外頭存取時,用到的格式為 "content://AUTHORITY/DBTable" 的型態,故決定 Content Provider 的 AUTHORITY 數值及使用的 SQLite db table name,此例定為 "com.example.study" 和 "MyTable1"、"MyTable2" 兩者。

  4. 實做 SQLiteOpenHelper,此例為 MyDBHelper,過程中建立兩張表,分別為 MyTable1 和 MyTable2 兩張表



    • CREATE TABLE MyTable1 ( _ID INTEGER PRIMARY KEY, _DATE DATETIME NULL )
      CREATE TABLE MyTable2 ( _ID INTEGER PRIMARY KEY, _DATA VARCHAR(50) NULL )




  5. 決定 content provider 所提供的 URI 服務後,使用 UriMatcher 來實做判斷方式



    • private static final UriMatcher mUriMatcher;
      private static final int URI_TYPE_TABLE1 = 1;
      private static final int URI_TYPE_TABLE2 = 2;
      static {
              mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
              mUriMatcher.addURI(AUTHORITY, MyDBHelper._DB_TABLE1, URI_TYPE_TABLE1);
              mUriMatcher.addURI(AUTHORITY, MyDBHelper._DB_TABLE2, URI_TYPE_TABLE2);
      }




  6. 實做 content provider 的相關函數,此例僅實做 String getType(Uri uri) 和 Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 兩個函數,前者用來告知 URI 所回傳的資料型態,後者則是 URI Query 時,將取得的 Cursor 操作方式(此為 SQLite 常用方式)

  7. 設定 AndroidManifest.xml,跟系統註冊使用 content provider。AndroidManifest.xml -> Application 分頁 -> Application Nodes -> Add -> Provider -> Name 欄位瀏覽 -> 選擇 MyContentProvider 後,並輸入 Authorities 欄位資訊(此例為com.example.study)

  8. 最後,實做一個 TestingActivity 來執行 content provider 的 query 動作,並從 Log.w 觀察情況。


程式碼:


MyContentProvider.java:


package com.example.study;


import android.content.ContentProvider;
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.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;


public class MyContentProvider extends ContentProvider {
        private static final String AUTHORITY = "com.example.study";
        private static final UriMatcher mUriMatcher;
        private static final int URI_TYPE_TABLE1 = 1;
        private static final int URI_TYPE_TABLE2 = 2;
        static {
                mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
                mUriMatcher.addURI(AUTHORITY, MyDBHelper._DB_TABLE1, URI_TYPE_TABLE1);
                mUriMatcher.addURI(AUTHORITY, MyDBHelper._DB_TABLE2, URI_TYPE_TABLE2);
        }
        private class MyDBHelper extends SQLiteOpenHelper {
                public static final String _DB_NAME = "MyDatabases.db";
                public static final String _DB_TABLE1 = "MyTable1";
                public static final String _DB_TABLE2 = "MyTable2";
                public static final int _DB_VERSION = 1;


                public MyDBHelper(Context context) {
                        super(context, _DB_NAME, null, _DB_VERSION);
                }


                public MyDBHelper(Context context, String name, CursorFactory factory, int version) {
                        super(context, name, factory, version);
                }


                @Override
                public void onCreate(SQLiteDatabase db) {
                        db.execSQL( "CREATE TABLE "+_DB_TABLE1+" ( _ID INTEGER PRIMARY KEY, _DATE DATETIME NULL )" );
                        db.execSQL( "CREATE TABLE "+_DB_TABLE2+" ( _ID INTEGER PRIMARY KEY, _DATA VARCHAR(50) NULL )" );
                }


                @Override
                public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                        db.execSQL("DROP TABLE IF EXISTS "+_DB_TABLE1);
                        db.execSQL("DROP TABLE IF EXISTS "+_DB_TABLE2);
                }
        }
        MyDBHelper mHelper = null;


        private void genTesting() {
                SQLiteDatabase mDB = mHelper.getWritableDatabase();

                // MyDBHelper._DB_TABLE1
                mDB.execSQL("INSERT INTO "+MyDBHelper._DB_TABLE1+" (_DATE) VALUES (datetime('now'))");


                // MyDBHelper._DB_TABLE2
                ContentValues values = new ContentValues();
                values.put("_DATA", "Hello World!");
                mDB.insertOrThrow(MyDBHelper._DB_TABLE2, null, values);


                mDB.close();
        }

        @Override
        public boolean onCreate() {
                // TODO Auto-generated method stub
                mHelper = new MyDBHelper(getContext());
                return true;
        }


        @Override
        public String getType(Uri uri) {
                // TODO Auto-generated method stub
                switch(mUriMatcher.match(uri)) {
                        case URI_TYPE_TABLE1:
                                return "vnd.android.cursor.item/vnd."+AUTHORITY+"."+MyDBHelper._DB_TABLE1; // one row
                        case URI_TYPE_TABLE2:
                                return "vnd.android.cursor.dir/vnd."+AUTHORITY+"."+MyDBHelper._DB_TABLE2; // multiple rows
                        default:
                                throw new IllegalArgumentException("Unknown URI " + uri);
                }
        }


        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
                // TODO Auto-generated method stub
                genTesting();
                Cursor out = null;
                SQLiteDatabase mDB = null;
                switch(mUriMatcher.match(uri)) {
                        case URI_TYPE_TABLE1:
                                mDB = mHelper.getWritableDatabase();
                                out = mDB.rawQuery("SELECT * FROM "+MyDBHelper._DB_TABLE1+" ORDER BY _ID DESC LIMIT 1", null);
                                out.moveToFirst();
                                break;
                        case URI_TYPE_TABLE2:
                                mDB = mHelper.getWritableDatabase();
                                out = mDB.rawQuery("SELECT * FROM "+MyDBHelper._DB_TABLE2, null);
                                out.moveToFirst();
                                break;
                        default:
                                throw new IllegalArgumentException("Unknown URI " + uri);
                }
                return out;
        }


        @Override
        public Uri insert(Uri uri, ContentValues values) {
                // TODO Auto-generated method stub
                return null;
        }


        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
                // TODO Auto-generated method stub
                return 0;
        }

        @Override
        public int delete(Uri arg0, String arg1, String[] arg2) {
                // TODO Auto-generated method stub
                return 0;
        }
}


MyContentProviderTestingActivity.java:


package com.example.study.test;


import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;


public class MyContentProviderTestingActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);

                Cursor c = getContentResolver().query(
                        Uri.parse("content://com.example.study/MyTable1"),
                        null,null,null,null ); // get all
                if( c != null ) {
                        c.moveToFirst();
                        while(c.isAfterLast()==false) {
                                Log.e("CP","MyTalbe1 field1:"+c.getString(0)+", field2:"+c.getString(1));
                                c.moveToNext();
                        }
                        c.close();

                        c = getContentResolver().query(
                                Uri.parse("content://com.example.study/MyTable2"),
                                null,null,null,null ); // get all
                        c.moveToFirst();
                        while(c.isAfterLast()==false) {
                                Log.e("CP","MyTalbe2 field1:"+c.getString(0)+", field2:"+c.getString(1));
                                c.moveToNext();
                        }
                        c.close();

                }
        }
}


沒有留言:

張貼留言