【Android】内容提供器

一、什么是内容提供器

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

  • 核心功能

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

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

    • 支持跨进程数据交互

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

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

二、运行时权限

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

2.1在程序运行时申请权限

以CALL_PHONE权限为例

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

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中,只需要判断授权结果

java 复制代码
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button=(Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public 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对象后才能作为参数传入。

java 复制代码
Uri uri=Uri.parse("content://com.example.app.provider/tabel");

查询数据

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

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

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

添加数据

java 复制代码
ContentValues values=new ContentValues();
        values.put("column1","text");
        values.put("column2",1);
        getContentResolver().insert(uri,values);

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

更新数据

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

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

删除数据

java 复制代码
 getContentResolver().delete(uri,"column2 = ?",new String[]{"1"});

调用ContentResolver的delete方法删除数据

四、创建内容提供器

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

java 复制代码
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对象,返回的是自定义代码,通过代码判断调用方相要调用的数据

java 复制代码
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>

java 复制代码
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中注册才能使用

XML 复制代码
 <provider
            android:name=".DatabaseProvider"
            android:authorities="com.example.databasetest.provider"
            android:enabled="true"
            android:exported="true"></provider>
相关推荐
小墙程序员8 分钟前
一文了解 AGP8 的使用
android·gradle
bytebeats4 小时前
移动开发中特性开关的最佳实践
android·firebase
bytebeats5 小时前
Android 开发者的 Jetpack Compose 学习路线图
android·android jetpack
bytebeats5 小时前
Android 的未来: 为什么 `Navigation 3` 是行业变革者!
android·android jetpack
bytebeats5 小时前
如何在 Jetpack Compose 中创建逐字动画
android·android jetpack
Billy_Zuo5 小时前
Android调用python库和方法的实现
android·开发语言·python
烈焰晴天6 小时前
一款基于 ReactNative 最新发布的`Android/iOS` 新架构文档预览开源库
android·react native·ios
2501_915909066 小时前
iOS电池寿命与App能耗监测实战 构建完整性能监控系统
android·ios·小程序·https·uni-app·iphone·webview
_祝你今天愉快7 小时前
NDK-参数加密和签名校验
android
一起搞IT吧9 小时前
Camera相机人脸识别系列专题分析之十九:MTK ISP6S平台FDNode传递三方FFD到APP流程解析
android·图像处理·人工智能·数码相机·计算机视觉