《第二行代码》第二版学习笔记(6)——内容提供器

news/2024/11/15 1:20:30/

文章目录

  • 一 运行时权限
    • 2.权限分类
    • 3 运行时申请权限
  • 二、内容提供器
    • 1、 ContentResolver的基本用法
    • 2、现有的内容提供器
    • 3、创建自己的内容提供器
      • 2.1 创建内容提供器的步骤
      • 2.2 跨程序数据共享

内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。

一 运行时权限

Android的权限机制,从系统的第一个版本开始就已经存在了。但其实之前Android的权限机制在保护用户安全和隐私等方面起到的作用比较有限,尤其是一些大家都离不开的常用软件,非常容易“店大欺客”。为此,Android开发团队在Android 6.0系统中引用了运行时权限这个功能,从而更好地保护了用户的安全和隐私。

2.权限分类

Android现在将所有的权限归成了三类,一类是普通权限,一类是危险权限,一类是特殊权限(不讨论)

  • 普通权限:指的是那些不会直接威胁到用户的安全和隐私的权限,对于这部分权限申请,系统会自动帮我们进行授权,而不需要用户再去手动操作了。
  • 危险权限:则表示那些可能会触及用户隐私或者对设备安全性造成影响的权限,如获取设备联系人信息、定位设备的地理位置等,对于这部分权限申请,必须要由用户手动点击授权才可以,否则程序就无法使用相应的功能。

访问:安卓完整权限列表可以查看Android系统中完整的权限列表。

3 运行时申请权限

  • 第一步就是要先判断用户是不是已经给过我们授权了。checkSelfPermission(Context,具体权限名)。
  • 没有授权的话,则需要调用ActivityCompat. requestPermissions(Activity的实例,申请的权限名,请求码)方法来向用户申请授权
public void onClick(View view) {if (ContextCompat.checkSelfPermission(MainActivity.this,android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this,new String[]{android.Manifest.permission.CALL_PHONE},1);}else {call();}
}

注:代码相对书本更新,Manifest.permission.CALL_PHONE改为android.Manifest.permission.CALL_PHONE 否则报错

  • 申请授权后不论申请成功还是失败都会回调onRequestPermissionsResult方法
    在这里插入图片描述
@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){call();}else {Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();}break;default:}}

二、内容提供器

1、 ContentResolver的基本用法

通过Context中的getContentResolver()方法获取到该类的实例。 该类提供一系列方法对数据进行CRUD操作。ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri参数代替,这个参数被称为内容URI,安卓对一些URI进行了封装。

URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authority和path

  • authority是用于对不同的应用程序做区分的,一般采用程序包名的方式来进行命名。
  • path则是用于对同一应用程序中不同的表做区分的,通常都会添加到authority的后面。
  • 一个标准的内容Uri:content://com.example.databasetest.provider/table1,表示想调用方期望访问com.example.databasetest这个应用的table1表中的数据。
  • 如果在这个Uri后面加一个id,例如content://com.example.databasetest.provider/table1/1,期望访问table1表中id为1的数据
	Uri newUri = getContentResolver().insert(uri, values);getContentResolver().delete(uri,null,null);getContentResolver().update(uri,values,null,null);Cursor cursor = getContentResolver().query(uri, null, null,null, null);

2、现有的内容提供器

读取和操作相应程序中的数据。如读取系统联系人,系统中有联系人列表的提供器。

  • 申请运行时权限,参照1.3部分。

  • 查询联系人数据,如下列代码所示,第一个参数为URI对象(系统对这个对象做了封装)

  • 在清单文件中声明读取系统联系人的权限

    <uses-permission android:name="android.permission.CALL_PHONE"/>
    
  • 效果图
    在这里插入图片描述

3、创建自己的内容提供器

给我们程序的数据提供外部访问接口。

2.1 创建内容提供器的步骤

  • 在com.example.databasetest包下新建MyProvider继承ContentProvider,并重写6个抽象类方法(alt+shift+enter)。

  • 在静态代码块中创建UriMatcher的实例

     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);}
    
  • 写CRUD方法

  • 写getType方法,必须以vnd开头。Uri以路径结尾,vnd后接.android.cursor.dir,Uri以id结尾,vnd后接.android.cursor.item。

    @Overridepublic String getType(Uri uri) {// TODO: Implement this to handle requests for the MIME type of the data// at the given URI.
//        throw new UnsupportedOperationException("Not yet implemented");switch (uriMatcher.match(uri)){case BOOK_DIR:return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.book";case BOOK_ITEM:return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.book";case CATEGORY_DIR:return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.category";case CATEGORY_ITEM:return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.category";}return null;}
  • 在清单文件中注册该provider
   <providerandroid:name=".DatabaseProvider"android:authorities="com.example.databasetest.provider"android:enabled="true"android:exported="true"></provider>

使用下列方式生成的provider,会在清单文件中自动注册。
在这里插入图片描述

2.2 跨程序数据共享

新建ProviderTets 项目,在该项目下访问DatabaseTest中数据库的数据。

代码更新:按照书上的执行报错,解决办法
在ProviderTets 的清单文件中添加如下声明:第一行是内容提供器所在的包名,第二行是内容提供器的authority。

    <queries android:name="com.example.databasetest"/><queries><provider android:authorities="com.example.databasetest.provider"/></queries>

http://www.ppmy.cn/news/1438923.html

相关文章

海外市场稳步推进,俄罗斯客户莅临湖南创远洽谈合作

4月18日&#xff0c;来自俄罗斯的意向合作客户到访湖南创远参观考察&#xff0c;并就双方今后合作进行了深入沟通。王毅董事长代表公司热情接待了远道而来的客人&#xff0c;对他们的到来表示热烈的欢迎。 客户在参观公司生产车间时&#xff0c;对公司天井钻机产品进行了详细了…

vue 关键字变红

1.html <div v-html"replaceKeywordColor(item.title)" ></div> 2.js //value为搜索框内绑定的值 replaceKeywordColor(val) {if (val?.includes(this.value) && this.value ! ) {return val.replace(this.value,<font color"red&…

SVM原理:怎么实现维度映射的

目录 SVM原理:怎么实现维度映射的 忽略异常点​ 软间隔:忽略部分异常值

泛微E9开发 如何自定义流程标题

1、功能背景 主表中有“选择类别”下拉框字段&#xff0c;用户可以根据需求来选择申请类别&#xff0c;一般多个相似流程的申请可以合并成一个&#xff0c;但是为了区分&#xff0c;我们可以通过将标题修改的方式来使整个显示页面更明确。 2、展示效果 3、实现方法 注意&…

Kafka学习笔记(二、linux和docker安装及使用demo)

1.安装启动 1.1.下载解压 官网下载地址将下载的tar包上传到服务器一个目录&#xff0c;然后解压$ tar -xzf kafka_2.13-3.7.0.tgz $ cd kafka_2.13-3.7.01.2. 启动环境 需安装Jdk8&#xff0c;Kafka可以使用ZooKeeper或KRaft启动。 ZooKeeper启动 运行如下命令&#xff0c;…

wstunnel (websocket模式ssh)

接上一篇 修改客户端运行参数 ssh -o ProxyCommand"./wstunnel client -L stdio://%h:%p ws://192.168.254.131:8080" 127.0.0.1 其中127.0.0.1为服务端的本地ssh访问&#xff0c;可以修改为通过服务端访问其他设备的ssh服务。例如&#xff1a; ssh -o ProxyComma…

去雾笔记-知识蒸馏

知识蒸馏&#xff08;Knowledge distillation&#xff09;是一种模型压缩技术&#xff0c;旨在将一个复杂的模型&#xff08;通常称为“教师模型”&#xff09;的知识转移给一个较简单的模型&#xff08;通常称为“学生模型”&#xff09;&#xff0c;以降低模型的计算复杂度和…

C# - 反射获取字段/属性/方法

using System; using System.Reflection;public class MyClass {public int MyField;public int MyProperty { get; set; }public void MyMethod() { } }class Program {static void Main(){Type type typeof(MyClass);// 获取字段FieldInfo fieldInfo type.GetField("M…