当前位置: 首页 > 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.dtcms.com/a/299479.html

相关文章:

  • 7️⃣ 递归函数
  • 【AcWing 835题解】滑动窗口
  • 数据结构 双向链表
  • greenhills编译出错问题
  • C++学习之深入学习模板(进阶)
  • SAPUI5 树形表格TreeTable示例
  • Spring AI(14)——文本分块优化
  • java之23种设计模式
  • 设计模式:Memento 模式详解
  • 简单实现支付密码的页面及输入效果
  • 面条式代码(Spaghetti Code)
  • Java高级之基于Java Attach与Byte-Buddy实现SQL语句增强
  • JWT安全机制与最佳实践详解
  • Linux 系统调用详解:操作文件的常用系统调用
  • Vulnhub jangow-01-1.0.1靶机渗透攻略详解
  • 自定义定时任务功能详解
  • MySQL 表的约束
  • 【面板数据】中国A股上市公司制造业智能制造数据集(1992-2024年)
  • 基于图神经网络的星间路由与计算卸载强化学习算法设计与实现
  • java实现一个方法,isTure则程序继续往下,为false则return的链式写法
  • 零基础学习性能测试第三章:jmeter线程组组合
  • LeetCode|Day26|191. 位 1 的个数|Python刷题笔记
  • Java学习|黑马笔记|Day23】网络编程、反射、动态代理
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年7月26日第150弹
  • 在Power Automate Desktop中执行PowerShell获取SharePoint online某个文件夹的用户权限列表
  • SAP ABAP的数据通过调用泛微Restful API同步数据到OA建模表
  • 学习日志19 python
  • pytest中的rerunfailures的插件(失败重试)
  • 在 Scintilla 中为 Squirrel 语言设置语法解析器的方法
  • 【Kubernetes】使用StatefulSet进行的资源调度,扩缩容,更改配置到版本回滚,三种配置更新方式