android Content Provider详解二

Android深入四大组件(五)Content Provider的启动过程 Content Provider做为四大组件之一,通常情况下并没有其他的组件使用频繁,但这不能作为我们不去深入学习它的理由。关于Content Provider一篇文章是写不完的,这一篇文章先来介绍它的启动过程。 阅读详情

从Provider取得data

本节讲述了如何从provider取得数据,使用用户词典作为例子.

为了清析易懂,本节中调用ContentResolver.query()的代码片断置于"UI 线程"中.但是,在实际代码中,你应该在另一个线程执行查询动作,这样做的一种方法是使用CursorLoader 类.而,那几行示例代码仅是片断,它们不能展示一个完整的应用.

要从provider取得data,须依如下步骤:

1 请求provider的读权限.

2 定义发送请求到provider的代码.

请求读权限

要从一个provider中获取数据,你的应用需要对目标provider具有"读权限".你不能在运行时请求此权限,而只能在manifest文件中使用 <uses-permission> 元素指定你的权限需求.当你在manifest中指定此元素时,你实际上就是在为你的应用请求这个权限.当用户安装你的应用时,就表示同意了这个权限请求.

要找到你使用的provider读权限的所对应的准确名字,以及其它用于provider的权限的名字,请浏览provider的文档.

关于操作provider的权限的角色的更多信息,请见Content Provider权限一节.

用户词典Provider在它的manifest 中定义了android.permission.READ_USER_DICTIONARY 权限,所以一个想读取它内容的应用必须请求此权限.

构建请求

获取数据的下一步是构建一个请求(query).这里的第一个代码片段定义了一些用于操作用户词典Provider的变量:


// "projection" 定义了要返回的各列们
String[] mProjection =
{
    UserDictionary.Words._ID,    // Contract class constant for the _ID column name
    UserDictionary.Words.WORD,   // Contract class constant for the word column name
    UserDictionary.Words.LOCALE  // Contract class constant for the locale column name
};

// 定义一个包含"select"条款的字符串
String mSelectionClause = null;

// 初始化一个包含"select"参数的字符串
String[] mSelectionArgs = {""};

下一个代码片段演示了如何使用ContentResolver.query(),将用户词典Provider作为一个例子.一个provider客户端查询极像一个SQL查询,它包含了要返回的一坨column们,一堆筛选条件,和一个排序方式.

查询返回的column集合被称作projection (变量 mProjection).

指定返回的列的语句被分解为选择条款和选择参数两部分.选择条款是逻辑和布尔表达式,列名以及值的组合体(变量mSelection).如果你在其中指定了使用 ? 来代表一个值,查询方法就会从选择参数部分取得这个值(变量mSelectionArgs).

在下一个代码片段中,如果用户没有输入单词,选择条款就被设为null,并且查询会反回所provider中所有的单词.如果用户输入了单词,选择条款就被设置为UserDictionary.Words.Word + " = ?" 并且选择参数(数组)的第一项被设置为用户输入的单词.

/*
 * 定义一个一维的字符串数组来容纳选择参数们
 */
String[] mSelectionArgs = {""};

// 从界面中获取一个单词
mSearchString = mSearchWord.getText().toString();

// 记住要在此插插入代码检查不合法的或恶意的输入.

// 如果单词是空的,则获取所有数据
if (TextUtils.isEmpty(mSearchString)) {
    // 设置选择条款为null就会返回所有单词
    mSelectionClause = null;
    mSelectionArgs[0] = "";

} else {
    // 构造一个匹配用户输入的单词的选择条款
    mSelectionClause = " = ?";

    // 将用户输入的单词置于选择参数中
    mSelectionArgs[0] = mSearchString;

}

// 执行查询并返回游标对象
mCursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,  // The content URI of the words table
    mProjection,                       // The columns to return for each row
    mSelectionClause                   // Either null, or the word the user entered
    mSelectionArgs,                    // Either empty, or the string the user entered
    mSortOrder);                       // The sort order for the returned rows

// 有些provider在出错时返回null,有抛出异常
if (null == mCursor) {
    /*
     * 在此插入代码处理错误.记住不要使用游标! 你可能要调用
     * android.util.Log.e()把错误记录的日志
     *
     */
// 如果游标是空的,找不到匹配的provider
} else if (mCursor.getCount() < 1) {

    /*
     * 在此插入代码来通知用户,查找不成功.这也不能完全算是个错误.你可能想为用户提供插入一个新行或重新输入查询单词的选项
     */

} else {
    // 在此插入代码,利用返回的结果做想做的事

}

查询与下面的SQL语句等价:

SELECT _ID, word, frequency, locale FROM words WHERE word = <userinput> ORDER BY word ASC;

在此SQL 语句中,以实际的列名代替了内置的类别常量.

防止恶意输入

如果被content provider管理的数据是一个SQL 数据库,在原始的SQL语句中包含不可信的数据会导致SQL注入.

思考以下选择条款:

// 通过连接用户输入到列名来构造一个选择条款
String mSelectionClause =  "var = " + mUserInput;

如果你这样做,你就允许用户连接恶意的SQL语句到你的SQL语句中.例如,用户可以输入"nothing; DROP TABLE *;" ,这将在选择条款中变为 var = nothing; DROP TABLE *;..既然选择条款被作为SQL语句,这就可能导致provider删除SQLite数据库中的所有的表(除非provider被设置成捕获SQL injection 阴谋).

要避免此问题,应使用一个运用?作为可替换参数的选择条款和一个作为选择参数的数组.当你这样做时,用户输入被直接绑定到查询而不是被解释为SQL语句的一部分.因为它不被认为是SQL,于是用户输入就不能注入恶意SQL.使用以下选择条款来代替连接用户输入的那个:

// 构造一个带有占位符的选择条款
String mSelectionClause =  "var = ?";

像这样建立起选择参数数组:

// 定义一个数组来容纳选择参数
String[] selectionArgs = {""};

像这样把一个值置入选择参数数组中:

// Sets the selection argument to the user's input
selectionArgs[0] = mUserInput;

一个使用?作为占位符的选择条款+一个选择参数数组是指定一个选择器的最佳方式,即使provider不是基于SQL数据库的.

显示查询结果

客户端方法ContentResolver.query() 总是返回一个包含所查询的列们的Cursor .一个Cursor 对象提供了随机的读取它所包含的行和列的能力.使用Cursor 的方法们,你可以迭代结果中的行,决定每列的数据类型,从列获得数据,以及检测结果的其它属性.一些Cursor 的实现会在provider的数据改变时自动更新,或在Cursor 改变时触发监听者的方法,或者两者都支持.

注: 一个provider可能跟据构建查询的对象的性质限制对某些列的操作.例如,联系人Provider会禁止同步适配器操作某些列,所以它不会把它们返回给一个activity或service.

如果没有符合选择条件的行,provider返回一个Cursor 对象,其Cursor.getCount() 为0 (一个空cursor).

如果一个内部错误发生,查询结果会因provider的不同而不同.它可能返回null,也可能抛出一个Exception.

既然一个Cursor 是行组成的"列表",那么一个和显示Cursor 内容的好方法就是把它链接到一个ListView 上,通过SimpleCursorAdapter.

下面的代码片段是衔接前面的代码来的.它创建一个SimpleCursorAdapter 对象,包含有查询返回的Cursor ,然后设置这个对象为ListView的适配器.

// 定义要从Cursor取出的并要加载到view中的列们
String[] mWordListColumns =
{
    UserDictionary.Words.WORD,   // Contract class constant containing the word column name
    UserDictionary.Words.LOCALE  // Contract class constant containing the locale column name
};

// 定义一个View ID组成的列表,它们将接收每行的Cursor列的值
int[] mWordListItems = { R.id.dictWord, R.id.locale};

// Creates a new SimpleCursorAdapter
mCursorAdapter = new SimpleCursorAdapter(
    getApplicationContext(),               // The application's Context object
    R.layout.wordlistrow,                  // ListView的一行的layout
    mCursor,                               // The result from the query
    mWordListColumns,                      // A string array of column names in the cursor
    mWordListItems,                        // An integer array of view IDs in the row layout
    0);                                    // Flags (usually none are needed)

// 将适配器设置给ListView
mWordList.setAdapter(mCursorAdapter);

注:要使Cursor支持ListView,cursor必须包含一个叫做_ID的列,因此,上面所示的查询从"单词"表中取出了_ID ,当然ListView 可以不显示它.这条限制同时也解释了为毛大多数provider在它们的表中都具有一个_ID 列.

从查询结果中获取数据

你可以使用查询结果做更多是事情,而不是仅简单地显示它们.比如,你可以从用户词典中获取拼法然后在其它provider中查找它们.要这样做,你需在Cursor中迭代所有的行.


// 获取叫做"word"的列的序号
int index = mCursor.getColumnIndex(UserDictionary.Words.WORD);

/*
 * 仅在cursor有效时执行下面语句.如果发生内部错误,用户词典Provider返回null.
 * 其它provider可能抛出一个异常而不是返回null.
 */

if (mCursor != null) {
    /*
     * 移到cursor中的下一行.在第一次移动之前,
     * "行指针" 为-1,并且,如果你想获取那个位置的数据,你将得到一个异常
     */
    while (mCursor.moveToNext()) {

        // 从列中获取值.
        newWord = mCursor.getString(index);

        // 在此插入代码处理获取到的单词

        ...

        // 循环结束
    }
} else {

    // 如果cursor为null或前面抛出了异常,在处插入代码报告错误.
}

Cursor 的实现包含了多个"get" 方法,用于从对象中获取不同类型的数据.例如,前面的代码片段使用getString().它们也具有一个getType() 方法,用它可以返回的值代表了数据的类型.

Android语言基础教程(207)Android自定义Content Provider之声明Content Provider:Android自定义Content Provider:让你的应用数据成为 想在Android应用间安全共享数据?Content Provider是你的不二之选!本文深度解析如何通过声明和实现自定义Content Provider,让你的应用数据"走出去"。从基本概念到完整示例,从权限控制到安全实践,带你一步步掌握这一核心组件,成为Android数据共享的"外交达人"。 阅读详情

相关推荐

Android 四大组件之Content Provider,外部应用访问不到,原因就是如此简单

如果你遇到了Content Provider 外部应用不能访问的情况,content provider 可以帮助应用管理对自身存储或由其他应用存储的数据的访问,并提供与其他应用共享数据的方法。它们封装数据,并提供用于定义数据安全性的机制。content provider 是将一个进程中的数据与另一个进程中运行的代码连接的标准接口。实现 content provider 有诸多优势。最重要的是,您可以配置 content provider,让其他应用安全地访问和修改您的应用数据。是Android四大组件之一。

qq_38999743的博客 1865

Android第一行代码-内容提供器(ContextProvider、ContextResolver)

跨程序共享数据–探究内容提供器 内容提供器简介(Android实现跨程序共享数据的标准方式) 内容提供器主要用于在不同的应用程序之间实现数据共享的功能,允许一个程序访问另一个程序的数据,同时可保证被访数据的安全性。 运行时权限 Android6.0系统中引用了运行时权限这个功能,从而更好的保护了用户的安全和隐私。 Android权限机制详解 用户设备的安全性主要在以下两个方面得到了保护: 如果用户在低于6.0系统的设备上安装该程序,会在安装界面给出提醒,这样用户就可以清楚地知晓该程序一共申请了哪些权限。

weixin_38367817的博客 1138

Android中的Content Provider是什么以及它有哪些用途

Content Provider封装了数据源,并提供了一套标准的接口,允许其他应用以一种统一的方式访问和操作这些数据。它通常用于访问SQLite数据库、文件、网络等数据源,是Android四大组件之一(其他三个是Activity、Service和BroadcastReceiver)。

2402_84885073的博客 1305

Android 四大组件 ————ContenProvider(内容提供者)

1,介绍:     内容提供者(Content Provider) 主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序的数据,同时还能保证被访数据的安全性。 2,简单原理图 3,进程间访问对方数据库: 【1】在A进程中创建数据库 public class MyOpenHelper extends SQLiteOpenHelper { ...

Cricket_7的博客 542

Android ContenProvider 机制完整剖析

请支持原创~~~ 相关博文: android 中的 ContentObserver (一) android 中的 ContentObserver (二) Android基础总结之八:ContentProvider 基于版本:Android R 0. 前言 很早以前分析过service(Android 中service 详解) 和broadcast receiver(android 中的 Broadcast 机制详解) 的机制,最近在回顾的时候发现少了ContentPro...

私房菜 1958

[车联网安全自学篇] Android安全之Content Provider攻防

"Content Provider 攻防"按照Google为Android设计的安全模型,应用的数据属于私有数据,故默认情况下,应用无法访问其他应用的私有数据。但当应用需要与其他应用共享数据时,Content Provider就扮演着应用间数据共享桥梁的角色。

橙留香Park的博客 5639

Android 第5讲:内容提供者ContentProvider

Android内容提供者

weixin_47323733的博客 2939

Android Content Provider 示例项目

Content Provider作为Android系统中用于数据共享的核心组件,它允许应用在遵循Android安全模型的基础上,对外开放其私有数据或者使用其他应用共享的数据。Content Provider通过一系列标准的接口提供数据的查询、插入、更新和删除操作,这使得不同应用之间可以便捷地共享数据,而无需直接访问其他应用的数据存储。理解Content Provider的工作机制对于构建模块化、数据驱动的Android应用至关重要。

weixin_35871529的博客 904

Android之内容提供器Content Provider详解(二)

上一篇 Android之内容提供器Content Provider详解(一)讲解了Content Provider之访问其他程序中的数据,本篇继续讲解创如何建自己的内容提供器本博文是《第一行代码 Android》的读书笔记/摘录。三、创建自己的内容提供器在上一篇中,我们学习了如何在自己的程序中访问其他应用程序的数据。总体来说思路还是非常简单的,只需要获取到该应用程序的内容URI,然后借助Conten

wei_zhi的博客 1289

光耦继电器电路分析

光耦电路的分析笔记

MingYue_SSS的博客 6875

树莓派4在Bookworm Raspbian系统下无法进入桌面模式(启动后出现彩色画面,然后一直黑屏,但是可以正常启动和ssh)

本文记录了这段比较坎坷的探索之路,由于你的问题不一定是我最终解决方案的,可能是前面探索路上试过的,所以建议按顺序看排除前置问题。 双十一又买了个树莓派 4B,插上之前树莓派 4B 的 TF 卡直接就能使用(毕竟是一样规格的)。但是由于用来连接硬盘的 USB 线是坏的,我以为是系统问题就进行了重装(所以坏掉的线还是直接扔了好)。 重新安装系统就装了最新的 2023-10-10 版本的 64 位的 Raspberry Pi OS,但是出现了一个问题: 启动后出现彩色画面,然后一直黑屏。

ZhongUncle的博客 3735

Android Content Provider

使用 Content Provider | Android使用 Content Provider如果你要公开你的数据,你可以创建或者使用一个Content Provider。它是一个能使所以应用程度都能存储和检索数据的对象。它是唯一在包和包之间分享数据的方法;因为不存在那种供所有的包来共享的一般存储空间。Android自带了一些Content Provider,它们用于一些一般的数

dywe_ddm的专栏 2302

VNC Viewer建立多个图形界面,来远程访问同一个服务器(Ubuntu)

如题。目前已经有了一个VNC viewer连接,那么如果再开一个图形界面呢? 思路主要是:新建一个用户,从这个用户新建一个vnc连接,然后访问图形界面。

the Blog of 等不到天亮丶等时光 5900

3-6安卓中的Content Provider组件

​继承与重写方法​需继承ContentProvider类并实现以下核心方法:java@Overridepublic boolean onCreate() { /* 初始化数据库等操作/ }@Override查询逻辑 */ }// 重写insert、update、delete、getType方法getType():返回MIME类型(如vnd.android.cursor.dir/user表示多行数据)。​注册Provider​。

weixin_45530192的博客 1438

永不消逝的电波 -GSM空口信号的接收与解码

一开始接触软件无线电应该是从很早之前对RFID洗衣卡的解密开始的,后来接触人员定位,慢慢的打开了这样一扇大门。。。。 翻到之前做的GSM信号的接收解码,今天就对其过程做一个记录,也不是什么新颖的内容,权当是记录和回忆了。 对于GSM网络的相关内容,不是非常的熟悉,如有不正确的,欢迎批评指正。

Jack.Xu 专栏 1万+

Cesium创建无人机视锥,同步视锥与鹰眼地图视角,实现视锥键盘控制。解决视锥初始化位置不准确问题等

本文描述了一个基于Cesium的3D视锥体可视化系统开发过程。系统实现了主视图与鹰眼视图的双屏联动,支持通过键盘控制视锥体的空间移动(WASD前后左右,Q/E旋转,C/Z升降),并实时同步更新两个视图。关键技术包括:1)基于主视图Scene创建Camera实现视锥体精确绘制;2)通过PerspectiveFrustum设置视锥参数;3)建立双视图的相机位置及视角同步机制。目前暂未实现视锥体far/near边界在鹰眼视图中的可视化,该系统可应用于无人机视角监控等三维场景交互需求。

coder_bin的博客 1590

Android四大组件基础学习之Content Provider

Android四大组件基础学习之Content Provider

Y3036359510的博客 1175

NCBI Datasets CLI优化:解决基因组数据下载报错与速度问题

基因组数据下载是生物信息学分析的关键环节,其稳定性和效率直接影响研究进度。NCBI Datasets CLI作为官方命令行工具,常面临连接中断和下载速度慢两大痛点,这主要源于服务器连接限制和网络传输问题。通过自动重试机制和校验修复流程可提升稳定性,而连接复用与CDN加速等技术能显著提高下载效率。在植物基因组等大规模数据场景中,结合脱水模式和增量更新策略可减少70%传输量。本文以艾草基因组项目为例,展示如何通过并行下载和API优化将100个基因组的下载时间从18小时缩短至2小时,为生物信息学研究提供可靠的数据

weixin_29051245的博客 243

Android四大组件——Content Provider

例如,用户只需知道有一个insert方法可以插入数据,并且向该方法传递待插入的数据即可,其并不关心数据是如何插入的,也不关心数据的具体组织形式。但是,程序不能直接操作Content Provider,而是借助名为Content Resolver的类,如下图所示。Content Provider 使用基于数据库模型的简单表格来提供需要共享的数据,在该表格中,每一行表示一条记录,而每一列代表特定类型和含义的数据,并且其中每一条数据记录都包含一个名为“_ID”的字段类标识每条数据。但是该过程是主动地读取数据。

2301_79188932的博客 1079

X线DR医学图像 --- DR医用滤线栅及摩尔纹详解 (二) 摩尔纹的产生机理

1,横向摩尔纹的表现 2,纵向摩尔纹的表现 3,摩尔纹在pitch = 143μm(注:pitch为采样间隔/周期)的FPD上的表现。 4,摩尔纹的危害(严重的影响了临床诊断) 5,摩尔纹对胸片肺部肺纹理的破坏 6,滤线栅的频率(滤线栅生产厂家的产品参数)。判断摩尔纹产生的重要依据之一 7,DR平板探测器的采样频率/空间极限分辨率 l.........

松下J27录放机 4981

2024年电气工程师最新面试题及答案

1. **基本电气工程原理**:包括电流、电压、电阻、功率等基本概念。2. **欧姆定律**:V = IR,描述电压、电流和电阻之间的关系。42. **风力发电系统组成**:包括风力涡轮机、发电机、控制系统等。44. **智能电网技术**:包括自动化控制、通信技术、数据分析等。10. **减少EMI**:使用屏蔽、滤波、合理布线等方法。40. **光伏系统组成**:包括光伏板、逆变器、控制器等。48. **能量存储技术**:包括电池、超级电容器、飞轮等。

guo162308的博客 6561

Android开发指导文档(译)--content provider(二)

创建一个Content Provider<br />要创建一个content provider你应该:建立一个存储数据的系统。多数的content provider用Android的文件存储方法或SQlite数据库来存储数据,但是你可以用任何你想用的方法存储。Android提供了SQLiteOpenHelper类来帮助你创建一个数据库以及SQLiteDatabase来管理它。 继承ContentProvider类来提供对数据的访问在manifest文件(AndroidManifest.xml)中为你的应

Tjxin_xd的专栏 1870

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

android Content Provider详解三

Content Provider 的权限 一个具有provider的应用可以指定其它要操作自己的数据所应具有的权限.这些权限保证了用户能了解一个应用将要操作那个数据.其它应用需基于provider的需求请求相应的权限.用户在安装应用时会看到它们所请求的权限. 如果一个provider的应用没有指定任务权限,那么其它应用就不能操作provider的数据.然而,provider所在的应用的组件们却

daizheng521的专栏 996

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

content provider 的使用

android有一个独特之处就是,数据库只能被它的创建者所使用,其他的应用是不能访问到的,所以如果你想实现不同应用之间的数据共享,就不得不用content provider了。    在Android中,content provider是一个特殊的存储数据的类型,它提供了一套标准的接口用来获取以及操作数据。并且,android自身也提供了几个现成的content provider:Contact

jiasudu1的专栏 691
上一篇: 内容提供者-Content Provider
下一篇: android Content Provider详解三
天涯狂人
博客等级 码龄19年 9粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值