Android之ContentProvider跨程序共享数据入门(笔记二)

第二篇来看看ContentProvider,就是把我们的内容提供给别人,让别人来使用。那么我们这里就需要两个项目,一个是包含数据库用来提供数据的,一个是用来调用查看的。首先看下提供数据的工程:

创建数据库的代码:

public class MyDatabaseHelper extends SQLiteOpenHelper {
    public static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement,"
            + "author text,"
            + "price real,"
            + "pages integer,"
            + "name text )";
    public static final String CREATE_CATEGORY = "create table Category (" +
            "id integer primary key autoincrement," +
            "category_name text," +
            "category_code integer)";

    private Context mContext;


    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        this.mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(CREATE_BOOK);
        sqLiteDatabase.execSQL(CREATE_CATEGORY);
//        Toast.makeText(mContext , "创建成功" , Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        sqLiteDatabase.execSQL("drop table if exists Book");
        sqLiteDatabase.execSQL("drop table if exists Category");
        onCreate(sqLiteDatabase);
    }
}


MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button bt_create_database;
    private MyDatabaseHelper myDatabaseHelper;
    private Button bt_insert_data;
    private Button bt_update_data;
    private Button bt_delete_data;
    private Button bt_query_data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        bt_create_database = (Button) findViewById(R.id.bt_create_database);

        bt_create_database.setOnClickListener(this);

        myDatabaseHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        bt_insert_data = (Button) findViewById(R.id.bt_insert_data);
        bt_insert_data.setOnClickListener(this);
        bt_update_data = (Button) findViewById(R.id.bt_update_data);
        bt_update_data.setOnClickListener(this);
        bt_delete_data = (Button) findViewById(R.id.bt_delete_data);
        bt_delete_data.setOnClickListener(this);
        bt_query_data = (Button) findViewById(R.id.bt_query_data);
        bt_query_data.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_create_database:
                myDatabaseHelper.getWritableDatabase();
                break;
            case R.id.bt_insert_data:
                insertData();
                break;
            case R.id.bt_update_data:
                updateData();
                break;
            case R.id.bt_delete_data:
                deleteData();
                break;
            case R.id.bt_query_data:
                queryData();
                break;
        }
    }

    private void queryData() {
        SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
        Cursor cursor = db.query("Book" , null , null , null , null , null , null);
        while (cursor.moveToNext()){
            Log.d("MainActivity" , cursor.getString(cursor.getColumnIndex("name")));
        }
        cursor.close();
    }

    private void deleteData() {
        SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
        db.delete("Book", "author = ?", new String[]{"鲁迅"});
        Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();
    }

    private void updateData() {
        SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", "The Da Vinci Code");
        db.update("Book", contentValues, "name = ?", new String[]{"达芬奇密码"});
        Toast.makeText(this, "更新成功", Toast.LENGTH_SHORT).show();

    }

    private void insertData() {
        SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", "达芬奇密码");
        contentValues.put("pages", "454");
        contentValues.put("author", "丹布朗");
        contentValues.put("price", "50");
        db.insert("Book", null, contentValues);
        contentValues.clear();


        contentValues.put("name", "百草书屋");
        contentValues.put("pages", "300");
        contentValues.put("author", "鲁迅");
        contentValues.put("price", "100");
        db.insert("Book", null, contentValues);
        contentValues.clear();
        Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();

    }
}

我们先通过上面运行起来,创建数据库,然后添加一些数据上去。(这上面其实是《第一行代码》里讲数据库的内容,为了方便,作者在讲ContentProvider的时候就在这基础上进行修改)

接下来才是跟我们主题相关的内容:

新建一个类继承自ContentProvider:

public class DatabaseProvider extends ContentProvider {
    public static final int BOOK_DIR = 0;
    public static final int BOOK_ITEM = 1;
    public static final int CATEGORY_DIR = 2;
    public static final int CATEGORY_ITEM = 3;
    public static final String AUTHORITY = "com.example.jdnew.databasetest.provider";
    private static UriMatcher uriMatcher;
    private MyDatabaseHelper databaseHelper;


    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY , "book" , BOOK_DIR);
        uriMatcher.addURI(AUTHORITY , "book/#" , BOOK_ITEM);
        uriMatcher.addURI(AUTHORITY , "category" , CATEGORY_DIR);
        uriMatcher.addURI(AUTHORITY , "category/#" , CATEGORY_ITEM);
    }

    @Override
    public boolean onCreate() {
        databaseHelper = new MyDatabaseHelper(getContext() , "BookStore.db" , null , 2);
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, 
                        @Nullable String selection, @Nullable String[] selectionArgs, 
                        @Nullable String sortOrder) {
        SQLiteDatabase sqLiteDatabase = databaseHelper.getReadableDatabase();
        Cursor cursor = null;
        switch (uriMatcher.match(uri)){
            case BOOK_DIR:
                cursor = sqLiteDatabase.query("Book" , projection , selection , 
                        selectionArgs , null , null ,sortOrder);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                cursor = sqLiteDatabase.query("Book" , projection , "id = ?" , 
                        new String[]{bookId} , null , null , sortOrder);
                break;
            case CATEGORY_DIR:
                cursor = sqLiteDatabase.query("Category" , projection , selection , 
                        selectionArgs , null , null , sortOrder);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                cursor = sqLiteDatabase.query("Category" , projection , "id = ?" , 
                        new String[]{categoryId} , null , null , sortOrder);
                break;
        }
        
        return cursor;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        switch (uriMatcher.match(uri)){
            case BOOK_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.jdnew.databasetest.provider.book";
            case BOOK_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.jdnew.databasetest.provider.book";
            case CATEGORY_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.jdnew.databasetest.provider.category";
            case CATEGORY_ITEM:
                return "vnd.android.cursor.dir/vnd.com.example.jdnew.databasetest.provider.category";
        }

        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        SQLiteDatabase sqLiteDatabase = databaseHelper.getWritableDatabase();
        Uri uriReturn = null;
        switch (uriMatcher.match(uri)){
            case BOOK_DIR:
            case BOOK_ITEM:
                long newBookId = sqLiteDatabase.insert("Book" , null , contentValues);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
                break;
            case CATEGORY_DIR:
            case CATEGORY_ITEM:
                long newCategoryId = sqLiteDatabase.insert("Category" , null , contentValues);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
                break;
        }
        return uriReturn;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, 
                      @Nullable String[] selectionArgs) {
      SQLiteDatabase sqLiteDatabase = databaseHelper.getWritableDatabase();
        int deletedRows = 0;
        switch (uriMatcher.match(uri)){
            case BOOK_DIR:
                deletedRows = sqLiteDatabase.delete("Book" , selection , selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                deletedRows = sqLiteDatabase.delete("Book" , "id = ?" , new String[]{bookId});
                break;
            case CATEGORY_DIR:
                deletedRows = sqLiteDatabase.delete("Category" , selection , selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                deletedRows = sqLiteDatabase.delete("Category" , "id = ?" , 
                        new String[]{categoryId});
                break;
        }
        return deletedRows;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, 
                      @Nullable String selection, @Nullable String[] selectionArgs) {
        SQLiteDatabase sqLiteDatabase = databaseHelper.getWritableDatabase();
        int updatedRows = 0;
        switch (uriMatcher.match(uri)){
            case BOOK_DIR:
                updatedRows = sqLiteDatabase.update("Book" , contentValues , selection ,
                        selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                updatedRows = sqLiteDatabase.update("Book" , contentValues , "id = ?" , 
                        new String[]{bookId});
                break;
            case CATEGORY_DIR:
                updatedRows = sqLiteDatabase.update("Category" , contentValues , selection , 
                        selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                updatedRows = sqLiteDatabase.update("Category" , contentValues , "id = ?" , 
                        new String[]{categoryId});
                break;
        }
        
        return updatedRows;
    }
}


分析一下,继承该类后我们需要重写几个方法:

onCreate()

一般在这里做数据库的创建和升级的操作等,只有当有ContentResolver来访问这里的数据的时候,内容提供器才会被初始化。(注:这是个返回boolean值的方法,因此创建成功后要返回true)


query(@NonNull Uri uri, @Nullable String[] projection,
                        @Nullable String selection, @Nullable String[] selectionArgs,
                        @Nullable String sortOrder)

使用uri来确定查询的表,projection表示哪些列,selection和selectionArgs用来约束查询哪些行,sortOrder表示排序。(注:这里将查询的结果以curosr返回)


insert(@NonNull Uri uri, @Nullable ContentValues contentValues)

uri表示插入的表,contentValue则是插入的数据。(注:返回用于标识插入该条数据的uri)


delete(@NonNull Uri uri, @Nullable String selection,
                      @Nullable String[] selectionArgs)

uri表示删除的表,selection和selectionArgs用来约束删除哪些行。(注,返回的是删除的行数int)


update(@NonNull Uri uri, @Nullable ContentValues contentValues,
                      @Nullable String selection, @Nullable String[] selectionArgs)

uri代表更新的表,contentValue用于存储更新的数据,selection和selectionArgs用来约束更新哪些行。(注:同样返回的是受影响的行数int)


getType(@NonNull Uri uri)

根据传入的内容URI来返回相应的MIME类型。(注:返回的是MIME类型的字符串String)


------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

(插入:

那么什么是MIME类型呢?

MIME全程是Multipurpose Internet Mail Extensions,多用途互联网邮件扩展。通过查阅资料后我所了解到的是这种类型是起初用在浏览器里的,因为我们的浏览器要处理很多种数据,文字,音频,图像,视频等等,那么就需要这么一种格式规范类型来表示这么多不同的数据,让浏览器能更好地识别。)


那么在android里的ContentProvider里,这里也有自己的一套格式规范,它对这个MIME类型字符串的构成由三部分组成:

1.必须以vnd开头

2.如果URI以路径结尾,那么后接android.cursor.dir/ ; 如果以id结尾,那么后接android.cursor.item/

3.最后接上vnd . <authority> . <path>

回想一下上一篇所讲的,我们要去解析的时候需要一个uri,这个uri是由权限和路径组成的,也就是上方第三条的authority和path这两个。

权限默认是包名,路径就是我们的表名,或是表名下的某条数据,就是这样:com.example.app.provider + table1 = com.example.app.provider/table1。然后再加上规范的写法,那么它就是content://com.example.app.provider/table1。

ok,那我们现在撇开规范,只要权限和路径,以上方这条uri:com.example.app.provider/table1为例,它得出来的MIME类型字符串为:

vnd  .  android.cursor.dir/  vnd  . com.example.app.provider  .  table1

如果在com.example.app.provider/table1后面加上个id:com.example.app.provider/table1/1

那么MIME类型字符串就变成vnd  .  android.cursor.item/ vnd . com.example.app.provider . table1

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

哦,再说下UriMatcher,这个类是用来匹配我们的Uri的,像一开始我们对它进行了初始化,然后把我们要的Uri给添加进去:

  uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY , "book" , BOOK_DIR);
        uriMatcher.addURI(AUTHORITY , "book/#" , BOOK_ITEM);
        uriMatcher.addURI(AUTHORITY , "category" , CATEGORY_DIR);
        uriMatcher.addURI(AUTHORITY , "category/#" , CATEGORY_ITEM);


然后接下来就是进行匹配,一旦匹配成功了就返回一个匹配码,而这个匹配码就是我们addURI的时候里面的第三个参数(如BOOK_DIR),所以这里才是我们为什么能用BOOK_DIR来做case的值的原因。

 switch (uriMatcher.match(uri)){
            case BOOK_DIR:
                updatedRows = sqLiteDatabase.update("Book" , contentValues , selection ,
                        selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                updatedRows = sqLiteDatabase.update("Book" , contentValues , "id = ?" , 
                        new String[]{bookId});
                break;
            case CATEGORY_DIR:
                updatedRows = sqLiteDatabase.update("Category" , contentValues , selection , 
                        selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                updatedRows = sqLiteDatabase.update("Category" , contentValues , "id = ?" , 
                        new String[]{categoryId});
                break;
        }

然后最后的一步就是再Manifest文件里进行注册:

<provider
            android:authorities="com.example.jdnew.databasetest.provider"
            android:name="com.example.jdnew.databasetest.DatabaseProvider"
            android:exported="true"/>
authorities就是我们一直在说的权限,然后name就是这个类的全名,然后exported设为true,表示可以被其它应用访问。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


那么上方的那个项目我们已经准备好了内容提供了,接下来就来试试看,我们的另外一个app是否能够去获取到上面这个app里的内容:

public class ProviderTestActivity extends AppCompatActivity implements View.OnClickListener {
    private Button bt_insert_data;
    private Button bt_update_data;
    private Button bt_delete_data;
    private Button bt_query_data;
    private String newId;
    private final String TAG = "ProviderTestActivity";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_provider_test);
        initView();
    }

    private void initView() {
        bt_insert_data = (Button) findViewById(R.id.bt_insert_data);
        bt_update_data = (Button) findViewById(R.id.bt_update_data);
        bt_delete_data = (Button) findViewById(R.id.bt_delete_data);
        bt_query_data = (Button) findViewById(R.id.bt_query_data);

        bt_insert_data.setOnClickListener(this);
        bt_update_data.setOnClickListener(this);
        bt_delete_data.setOnClickListener(this);
        bt_query_data.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_insert_data:
                insertData();
                break;
            case R.id.bt_update_data:
                updateData();
                break;
            case R.id.bt_delete_data:
                deleteData();
                break;
            case R.id.bt_query_data:
                queryData();
                break;
        }
    }

    private void queryData() {
        Uri uri = Uri.parse("content://com.example.jdnew.databasetest.provider/book");
        Cursor cursor = getContentResolver().query(uri , null , null ,null ,null);
        if (cursor!=null) {
            while (cursor.moveToNext()) {
                String name = cursor.getString(cursor.getColumnIndex("name"));
                String author = cursor.getString(cursor.getColumnIndex("author"));
                int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                double price = cursor.getDouble(cursor.getColumnIndex("price"));
                Log.d(TAG , "name is" + name);
                Log.d(TAG , "author is " + author);
                Log.d(TAG , "pages are " + pages);
                Log.d(TAG , "price is " + price);
            }
            cursor.close();
        }
    }

    private void deleteData() {
        Uri uri = Uri.parse("content://com.example.jdnew.databasetest.provider/book/" + newId);
        getContentResolver().delete(uri , null , null);
    }

    private void updateData() {
        Uri uri = Uri.parse("content://com.example.jdnew.databasetest.provider/book/" + newId);
        ContentValues contentValues = new ContentValues();
        contentValues.put("name" , "A Storm of Swords");
        contentValues.put("pages", 1216);
        contentValues.put("price" , 25.2);
        getContentResolver().update(uri , contentValues , null , null);
    }

    private void insertData() {
        Uri uri = Uri.parse("content://com.example.jdnew.databasetest.provider/book");
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", "百年孤独");
        contentValues.put("author", "马尔克斯");
        contentValues.put("pages", 300);
        contentValues.put("price", 22.5);
        Uri newUri = getContentResolver().insert(uri, contentValues);

        newId = newUri.getPathSegments().get(1);
    }
}








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值