【安卓开发】内容提供器

news2024/11/18 20:01:16

内容提供器实现了不同程序之间实现数据共享的功能。

7.2 运行时权限

安卓6.0版本后引入了运行时权限
危险权限列表
每个权限都属于一个组,授权了其中一个,一个组内的权限都将会被授权。

测试代码

// AndroidManifest.xml中加入以下代码
<uses-permission android:name="android.permission.CALL_PHONE"/>

// 主函数是下列代码
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button makeCall = (Button) findViewById(R.id.make_call);
        makeCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                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(){
        try {
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        }catch (SecurityException e){
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, 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:
        }
    }
}

ContextCompat.checkSelfPermission() 方法可以怕判断用户是否已授权,第一个是context,第二个是具体参数名,然后和 PackageManager.PERMISSION_GRANTED 对比,相等说明授权了,不等相当于没授权。
授权的话直接执行打电话逻辑,没授权的话使用
requestPermissions()方法申请授权:第一个参数是Activity的实例,第二个是要申请的权限列表数组String、,第三个是请求码,唯一即可。
调用完之后都会回调到函数 onRequestPermissionsResult 中,授权的结果在 grantResults 参数中

7.3 访问其他程序中的数据

7.3.1 ContentResolver的基本用法

要想访问提供器中共享的数据,就一定要借助 ContentResolver 类,可以通过 Context 中的 getContentResolver()方法得到实例,其中提供了 update、delete、query、insert等方法用于CRUD操作。
和数据库操作不同,ContentResolver中增删改查不接收表明参数,但用Uri参数代替,这个参数被称为内容URI,由:authority和path组成。authority是用于区分不同应用程序的,一般都是报名加provider。path 是用于对同一应用程序的不同表做区分的,一般都会加在 authority 的后面,组合后的URI示例:com.example.app.provider/label1 还需要在前面加上协议:content://com.example.app.provider/label1。URI需要解析后才可以使用:
Uri uri = uri.parse("content://com.example.app.provider/label1"),下面就可以使用Uri对象来查询table表中的数据了:Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
参数解释
之后可以逐个从返回的Cursor对象中都出来了:

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

update() 方法

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

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

7.3.2 读取系统联系人

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button makeCall = (Button) findViewById(R.id.make_call);
        makeCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                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(){
        try {
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        }catch (SecurityException e){
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, 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:
        }
    }
}

布局代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/make_call"
        android:text="Make Call"/>
</LinearLayout>

还有一条权限语句:

<uses-permission android:name="android.permission.CALL_PHONE"/>

7.4 创建自己的内容提供器

7.4.1 创建内容提供器的步骤

要想自己定制,就需要实现一个java类并重载以下方法:

public class MyProvider extends ContentProvider {

    @Override
    // 创建函数,在这里通常实现数据库升级和创建操作
    public boolean onCreate(){
        return false;
    }

    @Override
    // 查询结果在Cursor对象中返回
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
        return null;
    }

    @Override
    // 添加完成后返回一个用于表示新纪录的URI
    public Uri insert(Uri uri, ContentValues values){
        return null;
    }

    @Override
    // 返回受影响的行数
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs){
        return 0;
    }

    @Override
    // 返回受影响的行数
    public int delete(Uri uri, String selection, String[] selectionArgs){
        return 0;
    }

    @Override
    // 根据传入的内容URI 返回相应的MIME类型
    public String getType(Uri uri){
        return null;
    }
}

URI后面可以加id,表示要找table1表中id为1的数据
content://com.example.app.provider/table/1
在URI中也可以使用通配符,如:
content://com.example.app.provider/*,匹配任意表,
content://com.example.app.provider/table/#,匹配table表中任意一行。

使用 UriMatcher 可以匹配内容URI,使用方法如下:

    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);
    }

    @Override
    public boolean onCreate(){
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
        switch (uriMatcher.match(uri)){
            case TABLE1_DIR:
                    // 查询table1中数据
                break;
            case TABLE1_ITEM:
                // 查询单条数据
                break;
            default:
                break;
        }
        return null;
    }

感觉主要是实现了个指令匹配的过程

getType函数的 MIME 类型需要介绍下,一个URI对应的MIME字符串主要有三部分:

  • 必须以vnd开头
  • 如果内容URI以路径结尾,则后跟 android.cursor.dir/ , 如果以id结尾,则跟 android.cursor.item/ 。
  • 最后接上 vnd.<authority>.<path>

content://com.example.app.provider/tabel这个内容 URI 对应的 MIME 可以写成
vnd.android.cursor.dir/vnd.com.example.app.provider.table
content://com.example.app.provider/tabel1/1对应于vnd.android.cursor.item/vnd.com.example.app.provider.table1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/371598.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

魔改hustoj源码使其支持显示队名和队员及女队标志

0. 起因&需求 本文涉及到的开源项目Github地址&#xff1a;https://github.com/zhblue/hustoj 事件的起因是&#xff0c;计算机学院要举办一个院级的ACM比赛&#xff0c;然后捏… 老师给我提了一个需求&#xff0c;就是能不能把比赛排行榜显示的队名下标注对应的队员&…

光栅化Triangles(笔记)

field of view (可见区域) 该角度越大,需要透视投影的角度越大,成像显示的内容越多 有Y值,则可得出成像范围 屏幕: 典型的光栅处理设备所有像素都被表示为x,y坐标轴形式 3D方块成像步骤: 先将其所在平面化为 与屏幕等长等宽的形式: 如何将一个三角形拆成像素&#xff1f;采样…

C++学习笔记-2

C学习笔记-2输入/输出控制----I/O流命名空间的定义及使用string类型函数改进域解析符::扩大全局变量的作用域形式参数可带有默认值函数重载引用的定义与应用引用的概念及使用引用作为形式参数引用与指针的比较引用作为返回值动态内存空间用new申请动态内存空间用delete释放动态…

unicloud的aggregate聚合查询时间戳转日期

我特么不知道看了这个帖子几百遍才看明白到-----》unicloud数据库中&#xff0c;聚合操作如何操作时间戳&#xff1f; - DCloud问答 自己淋过雨老想着为别人撑伞&#xff0c;可怜我这35岁的老人家&#xff0c;给我去点关注&#xff01;&#xff01;&#xff01;&#xff01;&a…

centos上cliskhouse的安装记录

clickhouse是由俄罗斯Yandex公司开发的列式存储数据库&#xff0c;于2016年开源&#xff0c;clickhouse的定位是快速的数据分析&#xff0c;对于处理海量数据的情况性能非常好&#xff0c;在网上也有很多测试的案例&#xff0c;在大数据的情况下性能远超过其他数据库&#xff0…

ThreadLocal原理、结构、源码解析

文章目录一、Thread简介1.什么是ThreadLocal2.为什么要是用ThreadLocal2.1Synchronized、Lock保证线程安全2.2ThreadLocal保证线程安全3.ThreadLocal和Synchronized的区别二、ThreadLocal原理1.Thread抽象内部结构2.ThreadLocal源码2.1Thread、ThreadLocal、ThreadLocalMap、En…

行业观察 | 内存接口芯片和CXL协议

本文对内存接口芯片的概念和CXL协议进行不完全总结。 更新&#xff1a;2022 / 02 / 25 行业观察 | 内存接口芯片背景内存接口芯片概念趋势CXL 协议背景 DRAM 内存基本被国外巨头 三星、美光 等内存模组制造商垄断&#xff0c;合计市场占有率超过 90%。 内存接口芯片 概念 什…

【Android】Android开发笔记(一)

【Android】Android开发笔记&#xff08;一&#xff09; 在Android Studio中import module和delete moduleimport moduledelete moduleAndroid Studio中App&#xff08;Module&#xff09;无法正常运行在实机上测试App一些基本概念App的工程结构结语在Android Studio中import m…

Leetcode Solutions - Part 2

1. Two Sum 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按…

7-vue-1

谈谈你对MVVM的理解 为什么要有这些模式&#xff0c;目的&#xff1a;职责划分、分层&#xff08;将Model层、View层进行分类&#xff09;借鉴后端思想&#xff0c;对于前端而已&#xff0c;就是如何将数据同步到页面上 MVC模式 代表&#xff1a;Backbone underscore jquer…

【DIY Arduino基于RC气垫船】

在本教程中,我们将学习如何构建基于 Arduino 的 RC 气垫船。我将向您展示构建它的整个过程,从设计和3D打印气垫船部件(包括螺旋桨)开始,到连接电子元件和对Arduino进行编程。 您可以观看以下视频或阅读下面的书面教程。 视频地址:https://www.youtube.com/watch?v=2XIG…

二叉平衡树(C++)

背景&#xff1a; 二叉平衡树&#xff0c;就是根据二叉搜索树进行优化&#xff0c;让其速度更加的快&#xff0c;如果读者没有学过二叉搜索树&#xff0c;可以前往以下链接查看资料&#xff1a;http://t.csdn.cn/cCDQDhttp://t.csdn.cn/cCDQD 二叉搜索树的缺陷&#xff1a; 在…

【Spark分布式内存计算框架——Spark Streaming】1. Streaming 概述(上)Streaming 应用场景、Lambda 架构

前言 在很多实时数据处理的场景中&#xff0c;都需要用到流式处理&#xff08;Stream Process&#xff09;框架&#xff0c;Spark也包含了两个完整的流式处理框架Spark Streaming和Structured Streaming&#xff08;Spark 2.0出现&#xff09;&#xff0c;先阐述流式处理框架&…

Linux--TCP编程--0216 17

观前提示&#xff1a;本篇博文的一些接口需要前几篇博文实现的 线程池的实现Liunx--线程池的实现--0208 09_Gosolo&#xff01;的博客-CSDN博客 线程池的单例模式Linux--线程安全的单例模式--自旋锁--0211_Gosolo&#xff01;的博客-CSDN博客 1.TCP编程需要用的接口 创建 sock…

【数据挖掘】EDA——以2022雪浪算力开发者大赛数据为例

作者简介&#xff1a;重庆大学22级研一&#xff0c;研究方向&#xff1a;时空数据挖掘、图神经网络。目前正在学习大数据、数据挖掘等相关知识&#xff0c;希望毕业后能找到数据相关岗位。 前言 之前写了一个比赛复盘&#xff08;【竞赛复盘】2022雪浪算力开发者大赛——阀体异…

Python脚本之准备测试环境的用户数据

本文为博主原创&#xff0c;未经授权&#xff0c;严禁转载及使用。 本文链接&#xff1a;https://blog.csdn.net/zyooooxie/article/details/127645678 这期是讲述下 我准备测试环境用户数据的经历。 【实际这篇博客推迟发布N个月】 个人博客&#xff1a;https://blog.csdn.…

【读书笔记】《深入浅出数据分析》第三章 寻找最大值

目录 一&#xff0c;Excel却是最基础、最高频、最有机会展示的一款数据分析工具二&#xff0c;作为数据工作者&#xff0c;实际工作中&#xff0c;不管用不用的上&#xff0c;至少到达会的水准1&#xff0c;常用函数2&#xff0c;透视表3&#xff0c;可视化4&#xff0c;数据分…

【RabbitMQ笔记04】消息队列RabbitMQ七种模式之发布订阅模式(Publish/Subscribe)

这篇文章&#xff0c;主要介绍消息队列RabbitMQ七种模式之发布订阅模式&#xff08;Publish/Subscribe&#xff09;。 目录 一、发布订阅模式 1.1、Exchange交换机 &#xff08;1&#xff09;什么是Exchange交换机呢&#xff1f;&#xff1f;&#xff1f; &#xff08;2&am…

数据结构与算法----问答2023

1、什么是哈希表&#xff1f;如何解决碰撞&#xff1f; 哈希表&#xff08;Hash Table&#xff09;&#xff0c;也称为散列表&#xff0c;是一种用于实现字典&#xff08;键值对&#xff09;数据结构的数据结构。它将键映射到哈希表中的一个索引&#xff08;桶&#xff09;来保…

从零开始学习iftop流量监控(找出服务器耗费流量最多的ip和端口)

一、iftop是什么iftop是类似于top的实时流量监控工具。作用&#xff1a;监控网卡的实时流量&#xff08;可以指定网段&#xff09;、反向解析IP、显示端口信息等官网&#xff1a;http://www.ex-parrot.com/~pdw/iftop/二、界面说明>代表发送数据&#xff0c;< 代表接收数…