当前位置: 首页 > news >正文

【Android】内容提供器

一、什么是内容提供器

  • 定义:Android 四大组件之一,用于管理应用数据的跨应用共享

  • 核心功能

    • 提供统一的接口访问数据(SQLite、文件、网络等)

    • 控制数据的安全访问权限

    • 支持跨进程数据交互

主要用于在不同的应用程序之间实现数据共享的功能,允许程序访问另一个程序的数据并保证被访问数据的安全性。

内容提供器可选择对哪一部分数据进行共享。

二、运行时权限

危险权限需要在运行时处理,普通权限需要在AndroidManifest.xml文件中添加权限声明

2.1在程序运行时申请权限

以CALL_PHONE权限为例

1.修改AndroidManifest.xml文件,声明权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><uses-permission android:name="android.permission.CALL_PHONE"/>

2.修改主活动,先判断用户是否已经授权,借用ContextCompat.checkSelfPermission方法,接收两个参数,Context和具体权限名,使用返回值和PackageManager.PERMISSION_GRANTED比较,相等表示已授权,直接执行逻辑。

没有授权,调用 ActivityCompat.requestPermissions向用户申请授权,接收三个参数,Activity实例,含有要申请权限名的String数组和请求码,之后系统自动回调onRequestPermissionResult方法,授权结果封装在grantResults中,只需要判断授权结果

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button=(Button) findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 1);} else {call();}}});}private void call(){Intent intent=new Intent(Intent.ACTION_CALL);intent.setData(Uri.parse("tel:10086"));startActivity(intent);}public void onRequestPermissionResult(int requestCode,String[] permissions,int[] grantResults){switch (requestCode){case 1:if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){call();}else{Toast.makeText(this,"permission",Toast.LENGTH_SHORT).show();}break;default:}}

 用户之后在手机设置中中可以对程序危险权限进行关闭

三、访问其他程序中的数据

3.1ContentResolver的基本用法

想要访问内容提供器中共享的数据,要借助ContentResolver类,可以通过Context中的getContentResolver()方法获取到该类的实例。

ContentResolver中的CRUD操作接收Uri参数,这个参数被称为内容URI,内容URI为内容提供器中的数据建立了唯一标识符,主要由authority和path两部分组成。

  • authority:对不同应用程序进行区分,采用程序包名进行命名

  • path:对同一应用程序中的不同表区分,一般添加在authority后

得到内容URI后通过Uri.parse得到Uri对象后才能作为参数传入。

Uri uri=Uri.parse("content://com.example.app.provider/tabel");

 查询数据

Cursor cursor=getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);
  •  uri:指定查询某个应用程序下的某一张表
  • projection:指定查询的列名
  • selection:指定where的约束条件
  • selectionArgs:为where中的占位符提供具体的值
  • sortOrder:指定查询结果的排序方式

 查询完成后返回Cursor对象,可以将数据从Cursor中逐个读取出来

 if(cursor!=null){while (cursor.moveToNext()){String column1=cursor.getString(cursor.getColumnIndex("column1"));int column2=cursor.getInt(cursor.getColumnIndex("column2"));}cursor.close();}

 添加数据

ContentValues values=new ContentValues();values.put("column1","text");values.put("column2",1);getContentResolver().insert(uri,values);

将待添加的数据组装到ContentValues中,然后调用ContentResolver的insert方法,传入参数uri和values

更新数据

ContentValues values=new ContentValues();values.put("column1","");getContentResolver().update(uri,values,"column1 = ? and column2 = ?",new String[]{"text","1"});

 上述代码使用了selection和selectionArgs参数对想要更新的数据进行约束

删除数据

 getContentResolver().delete(uri,"column2 = ?",new String[]{"1"});

 调用ContentResolver的delete方法删除数据

四、创建内容提供器

1.新建一个类继承ContentProvider,需要全部重写6个抽象方法

public class MyProvider extends ContentProvider {public boolean onCreate(){return false;}public Cursor query(Uri uri, String[] projection,String selection,String[] selectionArgs,String sortOrder){return null;}public Uri insert(Uri uri, ContentValues values){return null;}public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){return 0;}public int delete(Uri uri,String selection,String[] selectionArgs){return 0;}public String getType(Uri uri){return null;}
}

 onCreate:初始化内容提供器时调用,完成对数据库的创建和升级

query:从内容提供器中查询数据,查询结果存放在Cursor对象中返回

insert:向内容提供器中添加一条数据,返回一个用于表示这条新记录的URI

update:更新已有数据,返回受影响的行数

delete:删除数据,返回被删除的行数

getType:返回相应的MIME类型

URI以路径结尾表示访问该表中的所有数据,以id结尾表示访问该表中有相应id的数据

可以使用通配符的方式分别匹配这两种格式的内容URI

*:表示匹配任意长度的任意字符
#:表示匹配任意长度的数字

2.借助UriMatcher类可以实现匹配内容的URI功能

UriMatcher中提供了addURI方法,接收三个参数,authority,path和自定义代码

调用UriMatcher的match方法时,传入一个Uri对象,返回的是自定义代码,通过代码判断调用方相要调用的数据

public class MyProvider extends ContentProvider {public static final int TABLE1_DIR=0;public static final int TABLE1_ITEM=1;public static final int TABLE2_DIR=2;public static final int TABLE2_ITEM=3;private static UriMatcher uriMatcher;static {uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI("com.example.app.provider","table1",TABLE1_DIR);uriMatcher.addURI("com.example.app.provider","table1/#",TABLE1_ITEM);uriMatcher.addURI("com.example.app.provider","table2",TABLE2_DIR);uriMatcher.addURI("com.example.app.provider","table2/#",TABLE2_ITEM);}public boolean onCreate(){return false;}public Cursor query(Uri uri, String[] projection,String selection,String[] selectionArgs,String sortOrder){switch (uriMatcher.match(uri)){case TABLE1_DIR:break;case TABLE1_ITEM:break;case TABLE2_DIR:break;case TABLE2_ITEM:break;default:break;}return null;}public Uri insert(Uri uri, ContentValues values){return null;}public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){return 0;}public int delete(Uri uri,String selection,String[] selectionArgs){return 0;}public String getType(Uri uri){return null;}
}

 getType是所有内容提供器必须提供的一个方法,用于获取Uri对象的MIME类型,由三部分组成:

  • 必须以vnd开头

  • 如果以路径结尾,则后接android.cursor.dir/,如果以id结尾,后接android.cursor.item/

  • 最后接vnd.<authority>.<path>

public String getType(Uri uri){switch (uriMatcher.match(uri)){case TABLE1_DIR:return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";case TABLE1_ITEM:return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";case TABLE2_DIR:return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2";case TABLE2_ITEM:return "vnd.android.cursor.item/vnd.com.example.app.provider.table2";default:break;}return null;}

 内容提供器要在AndroidManifest.xml中注册才能使用

 <providerandroid:name=".DatabaseProvider"android:authorities="com.example.databasetest.provider"android:enabled="true"android:exported="true"></provider>

http://www.lryc.cn/news/600922.html

相关文章:

  • Kubernetes 与 Docker的爱恨情仇
  • 1.安装anaconda详细步骤(含安装截图)
  • C++20 协程
  • ​机器学习从入门到实践:算法、特征工程与模型评估详解
  • 是德科技 | AI上车后,这条“高速公路”如何畅通?
  • 聚类-一种无监督分类算法
  • 聚类里面的一些相关概念介绍阐述
  • Digit Queries
  • OpenFeign-远程调用
  • 数据结构 二叉树(2)---二叉树的实现
  • excel删除重复项场景
  • HarmonyOS中的PX、 VP、 FP 、LPX、Percentage、Resource 详细区别是什么
  • 商汤InternLM发布最先进的开源多模态推理模型——Intern-S1
  • CUDA杂记--FP16与FP32用途
  • P2392 kkksc03考前临时抱佛脚
  • Linux——线程互斥
  • 【RHCSA 问答题】第 13 章 访问 Linux 文件系统
  • PYTHON从入门到实践-16数据视图化展示
  • 卫星通信终端天线对星之:参考星对星
  • DOM元素添加技巧全解析
  • 单片机CPU内部的定时器——滴答定时器
  • Linux DNS 服务器正反向解析
  • Mybatis学习之配置文件(三)
  • Linux随记(二十一)
  • 变频器实习DAY15
  • Linux内核设计与实现 - 第13章 虚拟文件系统(VFS)
  • Linux shuf命令随机打乱行顺序
  • 差模干扰 共模干扰
  • 利用RAII与析构函数避免C++资源泄漏
  • kafka的部署和jmeter连接kafka