Android进程间通信之ContentProvider(内容提供者)

一、简介
  • ContentProvider主要用于在不同的应用程序间实现数据共享的功能,允许一个程序访问另外一个程序中的数据,还能保证数据访问的安全性。

  • 是Android跨进程实现数据共享的标准方式。
    在这里插入图片描述

  • ContentProvider相当于进程间的搬运工,对数据一系列的操作(CRUD)

  • 数据源可以是数据库(SQLite等)、文件、xml、网络等等。

在了解ContentProvider之前,需要对URI和运行时权限进行回顾下,在ContentProvider中涉及到这两个知识点

二、统一资源标识符(URI)

URI:是给ContentProvider中的数据提供唯一的标识符。

URI分为自定义和系统内置两种类型,系统内置比如通讯录、日程表、相册等等。

1、自定义URI

自定义URI的标准命名:
在这里插入图片描述

  • 主题名(Schema):ContentProvider的URI前缀,系统规定的。
  • 授权信息(Authority):ContentProvider的唯一标识符。
  • 表名(Path):ContentProvider指向数据库中的某个表名。
  • 记录(ID):表中的某个记录,如果无指定,默认返回的是全部记录。

注意:

自定义URI格式末尾一般有两种结束方式

  • 一种是以表名(Path)即路径为结束点,该方式表示访问表中所有的数据 如:content://com.hzw.progress/Book
  • 另外一种是记录(ID)为结束点,则表示只访问有相应ID属性的数据 如:content://com.hzw.progress/Book/1

此外某些时候我们希望访问任意一张表中所有数据或者某张表的任意一行数据,此时可以使用通配符的方式。

//  *  匹配任意长度的任何有效字符的字符串 
// 表示能访问com.gwz.progress下所有表数据
content://com.gwz.progress/*

//  #  匹配任意长度的数字字符的字符串
//表示能访问com.gwz.progress下的表名为Book中任意一行数据
content://com.gwz.progress/Book/#

自定义的URI的使用方法:

//通过Uri解析指定的Uri字符串得到URi对象
Uri uri = Uri.parse("content://com.hzw.progress/Book/1");
2、系统内置URI

在使用内置URI时,需注意在Mainfest文件中声明相应的权限,否则会访问失败甚至程序崩溃现象。具体的所需权限可以搜索log日志的“Permission Denial”得知。

运行时权限

在Android6.0开始系统加入运行时权限机制,就是在应用安装使用中需要用户同意一些系统权限,若拒绝授权,则无法使用该功能。通常这些权限是涉及到用户的安全和隐私,为此称之为危险权限,一些常用的危险:

在这里插入图片描述
下面通过调起手机系统拨号为例,说明权限授权的流程
在未手动授权的情况:

  public void onClick(View view) {
   
        switch (view.getId()){
   
            case R.id.but_call:
                call();
                break;
        }
    }

private void call() {
   
        try {
   
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        }catch (SecurityException e){
   
            e.printStackTrace();
        }
    }

//在Mainfest中声明打电话权限
<uses-permission android:name="android.permission.CALL_PHONE"/>

在Android5.0之前只要在Mainfest声明权限就可以访问成功,然而在Android6.0及以上环境,点击后会发现程序没有任何反应,说明调起拨号界面失败,我们可以通过日志发现具体错误信息:
在这里插入图片描述
通过Permission Denial搜索日志也可得知具体所需权限
在这里插入图片描述

接下来修复处理这个运行时权限问题,实现调起拨号界面。
基本步骤:

  1. 获取所需权限的授权许可值,通过checkSelfPermission可得。具体返回值有两种:
    (1)PERMISSION_GRANTED:表示已经得到相关权限
    (2)PERMISSION_DENIED:未得到权限许可
  2. 通过授权许可值,检查是否有授权(与PackageManager.PERMISSION_GRANTED进行比较)
    (1)未授权:则申请授权,可用requestPermissions申请
    (2)已有授权:直接调用业务方法。
  3. 重写onRequestPermissionsResult方法,在其根据grantResults数组的元素值和请求code判断是否授权成功。
    (1)授权成功:可直接调用业务方法
    (2)授权失败或拒绝授权:下次再次申请授权时需前往应用信息界面手动打开需求
  private static final int CALL_CODE=100;

    public void onClick(View view) {
   
        switch (view.getId()){
   
            case R.id.but_call:
                //获取CALL_PHONE权限许可值
                int selfPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
                //检查是否授权  
                if (selfPermission !=PackageManager.PERMISSION_GRANTED){
   
                      //没有授权情况下,则申请CALL_CODE权限
                    ActivityCompat.requestPermissions(this,new String[]{
   Manifest.permission.CALL_PHONE},CALL_CODE);
                }else {
   
                     //授权成功的情况下,直接调用call方法
                    call();
                }
                break;

    }


   @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
   
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //根据grantResults数组的元素值和请求code判断是否授权成功
        if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
   
            switch (requestCode){
   
                case CALL_CODE:
                    call();
                    break;
            }

        }else {
   

            Log.i(TAG, "onRequestPermissionsResult: "+"权限授权失败,需要前往应用信息页面设置");
            showPermissionFailureDialog();
        }

    }
    //授权失败显示的dialog
    private void showPermissionFailureDialog(){
   
        new AlertDialog.Builder(this)
                .setMessage("您已拒绝了相关权限,将无法使用该功能,是否前往应用信息页面手动打开该权限")
                .setNegativeButton(android.R.string.no,null)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
   
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
   
                        Intent intent=getAppDetailSettingIntent(ContentProviderActivity.this);
                        startActivity(intent);
                    }
                }).create().show();
    }

 /**
     * 获取应用详情页面intent
     *
     * @return
     */
    public static Intent getAppDetailSettingIntent(Context context) {
   
        Intent localIntent = new Intent();
        localIntent.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值