天天看点

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