ContentProvider:在Android中实现进程间数据共享

目录

一,ContentProvider

二,Uri和UriMatcher工具类

1,Uri

2,UriMatcher

三,自定义ContentProvider

 1,准备数据源

2,创建ContentProvider子类

 3,在Manifest文件中注册ContentProvider

四,使用ContentResolver访问数据

五,获取系统中CP的数据

1,获取通话记录

2,管理多媒体内容


一,ContentProvider

        ContentProvider内容提供者,是一种实现不同应用间共享数据的标准api,当应用想要提供数据时,就提供ContentProvider,其他应用通过ContentResolver来接收数据;

        ContentProvider以Uri的形式对外提供数据,其他应用使用ContentResolver通过Uri来访问数据;

        ContentProvider是单例模式的,多个ContentResolver请求数据时,是委托给同一个CP对象来操作的;

二,Uri和UriMatcher工具类

1,Uri

Uri的结构和网站URL命名规则类似:

Uri举例:content://org.edu.provider/words

  • content://:这部分是Android固定的
  • org.edu.provider:这部分是ContentProvider中的authority,结构一般为包名.provider
  • words:资源部分,根据资源不同这部分不同

通过Uri提供的静态方法parse()来实现将字符串转换为Uri:

  • Uri uri = Uri.parse("content://org.edu.p../words") 

2,UriMatcher

帮助ContentProvider操作Uri,进行Uri判断和注册等功能;

(1)UriMatcher通过构造器构造:

UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//UriMatcher.NO_MATCH 表示不匹配任何路径的返回码(返回-1)

(2)注册Uri,只有注册过的Uri才能被访问:

//Uri的authorities
private static String AUTHORITIES = "com.example.contentprovider.ContentProvider.provider";

//Uri的标识码,用于标识唯一的资源
private static Integer BOOK_CODE = 0;

//注册Uri authorities + 资源名(表名)+ 标识码
matcher.addURI(AUTHORITIES, "tb_books", BOOK_CODE);

//最终Uri格式为"content://com.example.contentprovider.ContentProvider.provider/tb_books/0"

 (3)通过int match(Uri uri)方法来判断Uri的对应的标识符,找不到返回-1:

private String getTable(Uri uri) {
        String tableName = "";
        if(matcher.match(uri) == BOOK_CODE)tableName = "tb_books";
        return tableName;
}

三,自定义ContentProvider

  • 准备数据源:可以是文件存储,Sqlite数据库等数据源;
  • 创建ContentProvider:自定义一个类继承ContentProvider,并重写增删改查等方法;
  • Manifest文件中注册ContentProvider;

 1,准备数据源

(1)以Sqlite数据库为数据源,创建SqliteOpenHelper类:

public class SqliteHelper extends SQLiteOpenHelper {
    public SqliteHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table if not exists tb_books(" +
                "id Integer primary key autoincrement, " +
                "name varchar(20) not null" +
                ");"
        );
    }

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

    }
}

2,创建ContentProvider子类

(2)创建ContentProvider,重写增删改查等方法,使用UriMatcher注册Uri:

public class MyContentProvider extends ContentProvider {
    private SQLiteDatabase bookDB;

    private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

    private static String AUTHORITIES = "com.example.contentprovider.ContentProvider.provider";

    private static Integer BOOK_CODE = 0;

    //注册Uri
    public MyContentProvider() {
        matcher.addURI(AUTHORITIES, "tb_books", BOOK_CODE);
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    private String getTable(Uri uri) {
        String tableName = "";
        if(matcher.match(uri) == BOOK_CODE)tableName = "tb_books";
        return tableName;
    }

    @Override
    public boolean onCreate() {
        //获取Sqlite数据库
        SqliteHelper sqliteHelper = new SqliteHelper(
                getContext(),
                "bookDB.db",
                null,
                1
        );
        bookDB = sqliteHelper.getWritableDatabase();
        //插入数据
        ContentValues contentValuesBooks = new ContentValues();
        contentValuesBooks.put("name", "book1");
        bookDB.insert("tb_books", null, contentValuesBooks);
        return true;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        String table = getTable(uri);
        if(table.isEmpty()){
            return null;
        }else {
            long insert = bookDB.insert(table, null, values);
            if(insert > 0)return uri;
            else return null;
        }
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        String table = getTable(uri);
        if(table.isEmpty()){
            return -1;
        }else {
            int delete = bookDB.delete(table, selection, selectionArgs);
            return delete;
        }
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        String table = getTable(uri);
        if(table.isEmpty()){
            return null;
        }else {
            Cursor cursor = bookDB.query(table, projection, selection, selectionArgs, null, null,sortOrder);
            return cursor;
        }
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        String table = getTable(uri);
        if(table.isEmpty()){
            return -1;
        }else {
            int update = bookDB.update(table, values, selection, selectionArgs);
            return update;
        }
    }
}

 3,在Manifest文件中注册ContentProvider

四,使用ContentResolver访问数据

(1)通过getContentResolver()方法获取ContentResolver对象:

ContentResolver contentResolver = getContentResolver();

(2)获取Uri:

Uri uri = Uri.parse("content://com.example.contentprovider.ContentProvider.provider/tb_books");

 (3)通过ContentResolver调用增删改查等方法:

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding = null;
    private ContentResolver contentResolver;
    private Uri uri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        contentResolver = getContentResolver();
        uri = Uri.parse("content://com.example.contentprovider.ContentProvider.provider/tb_books");

        binding.btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialogUtil.showDialog(
                        MainActivity.this,
                        "添加",
                        "id",
                        "书名",
                        new AlertDialogUtil.DialogClickCallback() {
                            @Override
                            public void onClick(DialogInterface dialog, int which, String input1, String input2) {
                                ContentValues contentValues = new ContentValues();
                                contentValues.put("id", Integer.valueOf(input1));
                                contentValues.put("name", input2);
                                Uri insert = contentResolver.insert(uri, contentValues);
                                if (insert != null) {
                                    Toast.makeText(MainActivity.this, "插入成功", Toast.LENGTH_SHORT).show();
                                } else
                                    Toast.makeText(MainActivity.this, "插入失败", Toast.LENGTH_SHORT).show();
                            }
                        }
                );
            }
        });

        binding.btnDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialogUtil.showDialog(
                        MainActivity.this,
                        "删除",
                        "id",
                        "书名",
                        new AlertDialogUtil.DialogClickCallback() {
                            @Override
                            public void onClick(DialogInterface dialog, int which, String input1, String input2) {
                                String selection = "id = ?";
                                String[] selectionArgs = {input1};
                                int delete = contentResolver.delete(uri, selection, selectionArgs);
                                if(delete > 0){
                                    Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show();
                                }else
                                    Toast.makeText(MainActivity.this, "删除失败", Toast.LENGTH_SHORT).show();
                            }
                        }
                );
            }
        });

        binding.btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialogUtil.showDialog(
                        MainActivity.this,
                        "修改",
                        "id",
                        "书名",
                        new AlertDialogUtil.DialogClickCallback() {
                            @Override
                            public void onClick(DialogInterface dialog, int which, String input1, String input2) {
                                ContentValues contentValues = new ContentValues();
                                contentValues.put("name", input2);
                                String selection = "id = ?";
                                String[] selectionArgs = {input1};
                                int update = contentResolver.update(uri, contentValues, selection, selectionArgs);
                                if(update > 0){
                                    Toast.makeText(MainActivity.this, "修改成功", Toast.LENGTH_SHORT).show();
                                }else
                                    Toast.makeText(MainActivity.this, "修改失败", Toast.LENGTH_SHORT).show();
                            }
                        }
                );
            }
        });

        binding.btnQuery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Cursor cursor = contentResolver.query(uri, null, null, null, null);
                StringBuffer result = new StringBuffer();
                if(cursor == null){
                    Toast.makeText(MainActivity.this, "查询失败", Toast.LENGTH_SHORT).show();
                }else{
                    while(cursor.moveToNext()){
                        int indexOfName = cursor.getColumnIndex("name");
                        int indexOfId = cursor.getColumnIndex("id");
                        int id = cursor.getInt(indexOfId);
                        String name = cursor.getString(indexOfName);
                        result.append("id: " + id + ", name: " + name + "\n");
                    }
                }
                binding.tvResult.setText(result);
            }
        });

    }
}

五,获取系统中CP的数据

        Android系统应用会采用CP(ContentProvider)的形式提供一些开放数据,只要知道相关的Uri。我们就可以直接通过ContentResolver来访问这些数据;

1,获取通话记录

通话记录的Uri为:CallLog.Calls.CONTENT_URI

获取通话记录用到的常量:

  • CallLog.Calls._ID: "_id"
  • CallLog.Calls.CACHED_NAME:”name”
  • CallLog.Calls.NUMBER:”number”
  • CallLog.Calls.TYPE:”type” CallLog.Calls.DATE:”date”
  • CallLog.Calls.DURATION:”duration”

2,管理多媒体内容

此CP支持的Uri如下:

  • MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
  • MediaStore.Audio.Media.INTERNAL_CONTENT_URI
  • MediaStore.Images.Media.EXTERNAL_CONTENT_URI
  • MediaStore.Images.Media.INTERNAL_CONTENT_URI
  • MediaStore.Video.Media.EXTERNAL_CONTENT_URI
  • MediaStore.Video.Media.INTERNAL_CONTENT_URI
  • Content://sms/outbox  发送箱短信URI
  • Content://sms/sent  收信箱短信URI
  • Content://sms/draft  草稿箱短信URI 
  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值