Android开发实践 ContentProvider和ContentResolver

1.关于ContentProvider和ContentResolver

(1)ContentProvider(内容提供者)

ContentProvider是不同应用程序之间进行数据交换的标准API,只提供数据的访问接口。

ContentProvider以某种Uri形式对外提供数据,允许其他应用访问或修改数据,其他应用程序通过ContentResolver根据Uri去访问操作指定数据。

将一个字符串转换成Uri:

Uri uri = Uri.parse("content://com.gc.contentprovider/test/100");

ContentProvider只有一个onCreate()生命周期方法且只会被调用一次,当其他应用通过ContentResolver第一次访问该ContentProvider时,onCreate()方法将会被回调。

(2)ContentResolver(内容观察者)

Content提供了如下方法来获取ContentResolver:

getContentResolver();

2.ContentProvider、ContentResolver、Uri三者之间的关系

3.开发ContentProvider

开发ContentProvider需要两步:

第1步:继承ContentProvider,实现query()、insert()、update()、delete()等方法(这些方法是给其他应用调用的);

第2步:在AndroidManifest.xml注册该ContentProvider,指定android:authorities属性(指定ContentProvider对应的Uri)和android:exported属性(设置android:exported:true表示允许其他应用程序调用)。

接下来实际开发一个ContentProvider:

(1)创建MyProvider,继承ContentProvider

public class MyProvider extends ContentProvider {
    // 第一次创建调用
    @Override
    public boolean onCreate() {
        System.out.println("onCreate");
        return true;
    }
    // 返回值表示该ContentProvider所提供数据的MIME类型
    @Override
    public String getType(Uri uri) {
        System.out.println("getType");
        return null;
    }
    // 查询方法,返回查询得到的Cursor
    @Override
    public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs, String sortOrder) {
        System.out.println(uri + "-query");
        System.out.println("where参数:" + where);
        return null;
    }
    // 插入方法,返回新插入记录的Uri
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        System.out.println(uri + "-insert");
        System.out.println("values参数:" + values);
        return null;
    }
    // 删除方法,返回被删除的记录条数
    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        System.out.println(uri + "-delete");
        System.out.println("where参数:" + where);
        return 0;
    }
    // 删除方法,返回被更新的记录条数
    @Override
    public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
        System.out.println(uri + "-update");
        System.out.println("where参数:" + where + ",values参数:" + values);
        return 0;
    }
}

(2)配置ContentProvider

在AndroidManifest.xml中application元素下添加如下子元素即可

<!-- 注册一个ContentProvider -->
<!-- exported:指定是否允许其他应用调用,true允许 -->
<!-- name:指定ContentProvider实现类的类名 -->
<!-- authorities:指定ContentProvider对应的Uri -->
<provider
    android:exported="true"
    android:name=".MyProvider"
    android:authorities="com.gc.contentprovider.myprovider">
</provider>

(3)使用ContentResolver调用方法(其他应用程序内)

public class MyResolver extends Activity {
    ContentResolver resolver;
    Uri uri = Uri.parse("content://com.gc.contentprovider.myprovider/");

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 获取系统的ContentResolver对象
        resolver = getContentResolver();
    }

    public void query(View source) {
        // 调用ContentResolver的query()方法,实际返回的是该Uri对应的ContentProvider的query()的返回值
        Cursor c = resolver.query(uri, null, "query_where", null, null);
        System.out.println("远程ContentProvider返回的Cursor:" + c);
    }

    public void insert(View source) {
        ContentValues values = new ContentValues();
        values.put("name", "android");
        // 调用ContentResolver的insert()方法,实际返回的是该Uri对应的ContentProvider的insert()的返回值
        Uri newUri = resolver.insert(uri, values);
        System.out.println("远程ContentProvider新插入记录的Uri:" + newUri);
    }

    public void update(View source) {
        ContentValues values = new ContentValues();
        values.put("name", "android");
        // 调用ContentResolver的update()方法,实际返回的是该Uri对应的ContentProvider的update()的返回值
        int count = resolver.update(uri, values, "update_where", null);
        System.out.println("远程ContentProvider更新记录数:" + count);
    }

    public void delete(View source) {
        // 调用ContentResolver的delete()方法,实际返回的是该Uri对应的ContentProvider的delete()的返回值
        int count = resolver.delete(uri, "delete_where", null);
        System.out.println("远程ContentProvider删除记录数:" + count);
    }
}

4.操作系统的ContentProvider

使用ContentResolver操作系统ContentProvider数据的步骤依然是两步:

第1步:调用Activity的getContentResolver()方法获取ContentResolver对象;

第2步:根据需要调用ContentProvider的query()、insert()、update()、delete()方法操作数据即可。

注意:需要提前了解该ContentProvider的Uri以及该ContentProvider所操作的数据列的列名,这些可通过查阅官方文档来获取。

时间: 2024-10-17 08:10:25

Android开发实践 ContentProvider和ContentResolver的相关文章

Android开发实践:Android交叉编译工具链的使用

前面2篇文章分别介绍了Android NDK编译的命令行参数,以及如何在任意目录使用Android.mk来编译本地c/c++代码,Andriod.mk和ndk-build只不过是Android官方提供了一套封装过的Android交叉编译环境而已,其实,你可以不用它,而直接通过传统的Makefile文件来编译你的c/c++代码的,本文即介绍如何直接通过传统的Makefile文件来编译可用于Android平台的库文件. 经常搞嵌入式开发的朋友对于交叉编译环境应该并不陌生,说白了,就是一组运行在x86

Android开发实践:利用ProGuard进行代码混淆

由于Android的代码大都是Java代码,所以挺容易被反编译的,好在Android ADT为我们集成了混淆代码的工具,一来可以混淆我们的代码,让程序被反编译后基本看不懂,另外还能起到代码优化的作用.发布项目前,建议打开Android的代码混淆功能. Android ADT主要通过ProGuard工具来提供代码混淆,网上也有挺多博客文章讲这个的,但感觉很多都介绍得太过于复杂,这里我就以问答的方式来更加简洁地介绍下ProGuard吧. 1. ProGuard是什么 ProGuard是一个工具,用来

Android开发实践:WIFI连接功能的封装

在上一篇文章<Android开发实践:WIFI扫描功能的封装>介绍了如何利用Andriod的API实现WIFI的扫描,本文则重点讲述一下如何连接WIFI吧,在此,也给出一个封装WIFI连接过程的类,提供简单的接口以供在各个代码工程中复用. 与WIFI扫描类似,WIFI的连接同样是一个耗时的过程,所以需要放到线程中执行,通过回调来通知调用者连接结果.该回调接口的定义如下: public interface WifiConnectListener { public void OnWifiConne

Android开发实践:由new Handler()说开去

最近面试一些Android开发的应聘者,除了基本的Activity生命周期等基础问题以外,我一般还会问如下两个问题: (1) Service与Thread有什么区别? (2) 在Activity里new Handler()和在自己创建的Thread中new Handler()有什么区别? 第一个问题其实是一个伪命令,因为Service是Android四大组件之一,而Thread只是Java提供的一个封装了线程管理的工具类,无论是Activity还是Service,都可以通过Thread来创建一个

Android开发实践:为什么要继承onMeasure()

Android开发中偶尔会用到自定义View,一般情况下,自定义View都需要继承View类的onMeasure方法,那么,为什么要继承onMeasure()函数呢?什么情况下要继承onMeasure()?系统默认的onMeasure()函数行为是怎样的 ?本文就探究探究这些问题. 首先,我们写一个自定义View,直接调用系统默认的onMeasure函数,看看会是怎样的现象: package com.titcktick.customview; import android.content.Con

Android开发实践:Java层与Jni层的数组传递

Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的Socket代码发送出去,当然,Jni层也需要把从Socket接收到的数据流返回给Java层.我简单地总结了一下,从Java层到Jni层,从Jni层到JAVA层,各有3种传递方式,下面用代码示例简单地介绍一下. 示例代码的主要文件有两个,一个是Native.java,是Java层的类:另一个是Native.c,是JNI层的文件,关键的地

Android开发实践:以“专业”的态度处理多线程

刚开始学一门编程语言的时候,我总是会有一种困惑,怎样让自己的代码看起来更"专业"?很多时候,我们可以照着教材实现一些基本的功能,比如用Socket发送/接收几个字符,写一个线程完成某个异步任务,但是在实际的项目中,往往不那么简单,比如需要设计Socket通信协议,需要处理Socket的连接异常断开,需要考虑在线程阻塞的情况下如何正常退出和释放资源等等,关于这些"实战经验",前面的文章也有所涉及,以后有空准备再开个专题跟大家分享探讨一下,今天先简单地说说怎样更&quo

Android开发实践:自己动手编写图片剪裁应用(1)

最近利用一周左右的业余时间,终于完成了一个Android图片剪裁库,核心功能是根据自己的理解实现的,部分代码参考了Android源码的图片剪裁应用.现在将该代码开源在Github上以供大家学习和使用,地址:https://github.com/Jhuster/ImageCropper,效果如下所示: 我的大致计划是首先介绍一下这个库的用法,然后再写几篇文章介绍一下其中的一些原理和关键技术,希望对Android开发新手有所帮助. [特性] 支持通过手势移动和缩放剪裁窗口 支持固定剪裁窗口大小.固定

Android开发实践:多线程编程小结

我们知道,Android系统为了提高程序的实时响应能力,不允许在UI线程中进行耗时的操作,否则会出现ANR异常,因此必须将耗时的任务放到非UI线程中执行.Android/Java提供了很多类来帮助大家完成异步操作,比如:Thread类,Timer类,AsyncTask类,HandlerThread类,以及Executor接口.这些类都分别在什么场合下使用呢? 本文简单地总结一下Android开发中常见的多线程类型和解决方案,并比较和分析了各个方案的区别,以便更好地理解和应用这些API接口. 1.