天天看點

Android ContentProvider(内容提供者)的使用

ContentProvider簡介

ContentProvider(内容提供者)是Android的四大元件之一,可以實作不同程序間的資料共享。在Android 源碼系統中,像設定,聯系人,多媒體等都使用到了ContentProvider。其實ContentProvider最終也是操作Sqlite資料庫,實作資料的增删改查。接下來我們看看怎麼使用。

使用步驟:

一、建立一個UserContentProvider類繼承ContentProvider,并在AndroidManifest.xml中添加授權:

android:authorities="com.psp.user.provider"

<provider
    android:name=".UserContentProvider"
    android:authorities="com.psp.user.provider"
    android:enabled="true"
    android:exported="true"/>
           
  1. name:ContentProvider的類名 
  2. authorities:唯一辨別了一個ContentProvider,外部應用通過該屬性值來通路ContentProvider。是以該屬性值必須唯一 
  3. exported:表明是否允許其他應用調用ContentProvider,true表示支援,false表示不支援     

二、建立資料庫操作類如下:首先聲明資料庫的名稱,表名,以及版本号,并建立一張使用者表。

public class DBOpenHelper extends SQLiteOpenHelper {
    //資料庫名
    private static final String DB_NAME = "user.db";
    //表名
    public static final String DB_TABLE_NAME = "user";
    //資料可版本号
    private static final int DB_VERSION = 1;

    public DBOpenHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //建立一張使用者表
        String sql_create_user = "CREATE TABLE IF NOT EXISTS "+DB_TABLE_NAME+"(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,age TEXT)";
        db.execSQL(sql_create_user);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}
           

三、實作UserContentProvider類,在onCreate()方法中向資料庫中插入一條資料。實作query和insert方法,其他方法不做探究。

public class UserContentProvider extends ContentProvider {

    //授權,和AndroidManifest.xml中的保持一緻
    public static final String AUTHORITY = "com.psp.user.provider";
    //比對Uri的類
    private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    //設定ContentProvider的唯一辨別,用于比對不同的Uri
    private static final int USER_INFO = 1;

    private SQLiteDatabase mDb;

    //初始化
    static {
        //若URI資源路徑 = content://com.psp.user.provider/user ,則傳回注冊碼USER_INFO
        uriMatcher.addURI(AUTHORITY, "user", USER_INFO);
    }

    private Context mContext;

    public UserContentProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public String getType(Uri uri) {
        // at the given URI.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int uri_code = uriMatcher.match(uri);
        switch (uri_code) {
            case USER_INFO:
                mDb.insert(DBOpenHelper.DB_TABLE_NAME, null, values);
                break;
            default:
                throw new RuntimeException("出錯了!!");
                // 向該表添加資料
        }
        // 當該URI的ContentProvider資料發生變化時,通知外界(即通路該ContentProvider資料的通路者)
        mContext.getContentResolver().notifyChange(uri, null);

        return uri;
    }

    @Override
    public boolean onCreate() {
        mContext = getContext();
        mDb = new DBOpenHelper(getContext()).getReadableDatabase();
        //初始化一條資料
        ContentValues initialValues = new ContentValues();
        initialValues.put("name","zhang san");
        initialValues.put("age",18);

        mDb.insert(DBOpenHelper.DB_TABLE_NAME,null,initialValues);

        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        int result = uriMatcher.match(uri);
        //查詢資料
        switch (result){
            case USER_INFO:
                return mDb.query(DBOpenHelper.DB_TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder, null);
            default:
                    throw new RuntimeException("出錯了!!");

        }
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
           

三、在其他應用中查詢或者插入資料,這邊以在本應用中操作為例。其他應用中方法一樣。

在MainActivity的布局檔案中添加兩個按鈕,一個實作查詢,一個實作插入。布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.psp.contentproviderdemo.MainActivity">

    <Button
        android:id="@+id/bt_querry_user_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="query user"
        android:textAllCaps="false"
        />

    <Button
        android:id="@+id/bt_insert_user_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="insert user"
        android:textAllCaps="false"
        />

</LinearLayout>
           

MainActivity的代碼實作如下:

public class MainActivity extends AppCompatActivity {

    //比對uri和UserContentProvider中的保持一緻
    public static final Uri USER_CONTENT_URI = Uri.parse("content://com.psp.user.provider/user");

    Button query_user;
    Button insert_user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        query_user = findViewById(R.id.bt_querry_user_info);
        insert_user = findViewById(R.id.bt_insert_user_info);

        query_user.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                queryProviderData(MainActivity.this);
            }
        });

        insert_user.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                insertProviderData(MainActivity.this,"li si",22);
            }
        });

    }

    //查詢資料庫
    public static String queryProviderData(Context context) {
        try {
            Cursor cursor = context.getContentResolver().query(USER_CONTENT_URI,
                    new String[]{"_id", "name","age"}, null, null, null);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    Log.d("psp_log","_id= "+cursor.getInt(0)+"\n"+
                            "name="+cursor.getString(1)+"\n"+"age="+cursor.getInt(2));
                    Toast.makeText(context,"name="+cursor.getString(1)+"\n"+"age="+cursor.getInt(2),Toast.LENGTH_SHORT).show();
                }
                cursor.close();
            }else {
                Log.d("psp_log","snCursor = null" );
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    //向資料庫中插入資料
    public static void insertProviderData(Context context,String name,int age) {
            ContentValues userValues = new ContentValues();
            userValues.put("name", name);
            userValues.put("age", age);
            context.getContentResolver().insert(USER_CONTENT_URI, userValues);
    }
}
           

四、結果驗證

啟動應用,點選查詢按鈕,看是否有一條初始化的“zhang san”的使用者,列印結果:

01-05 10:00:45.610 28827-28827/com.psp.contentproviderdemo D/psp_log: _id= 1
                                                                      name=zhang san
                                                                      age=18
           

我們在點選插入按鈕,再點選查詢按鈕,看看“li si”是否插入成功,列印結果:

01-05 10:29:48.343 29993-29993/com.psp.contentproviderdemo D/psp_log: _id= 1
                                                                      name=zhang san
                                                                      age=18
01-05 10:29:48.354 29993-29993/com.psp.contentproviderdemo D/psp_log: _id= 2
                                                                      name=li si
                                                                      age=22
           

列印結果說明資料操作是成功的。

源碼位址:

GitHub位址:pshiping2014/ContentProviderDemo