第10章ContentProvider(4学时)
ContentProvider

ContentProdiver内容提供者ContentProvider为Android组件之一,主要用来应用程序之间的数据共享,也就是说一个应用程序用ContentProvider将自己的数据暴露出来,其他应用程序通过ContentResolver来对其暴露出来的数据进行增删改查。
ContenProvider与ContentResolver之间的对话同过Uri(通用资源标识符),一个不恰当的比喻就好像浏览器要显示一个网页要有一个东西发送请求,这相当于ContentResolver,你要拿东西就要知道去哪里拿,你就得知道服务器的域名或网址,而这个网址就相当于Uri,当到达服务器的时候服务器要有个东西来处理,这就相当于ContenProvider。
在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。
但是一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,例如我们需要操作系统里的媒体库、通讯录等,这时我们就可以通过ContentProvider来满足我们的需求了。
Content Provider基本概念(1)ContentProvider为存储和获取数据提供了统一的接口。
ContentProvide 对数据进行封装,不用关心数据存储的细节。
使用表的形式来组织数据(2)使用ContentProvider可以在不同的应用程序之间共享数据。
(3) Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。
(4)ContentProvider所提供的函数:query(),insert(),update(),delete(),getType(),onCreate()等A程序通过ContenProvider来暴露数据的基本步骤:(1)实现一个ContenProvider的子类,并重写query,insert,update,delete等这几个方法,(2)在androidmanifest.xml中注册ContenProvider,指定的android:authorities属性B程序通过ContentResolver来操作A程序暴露出来的数据的基本步骤(1)通过content的getContentResolver()来获取ContentResolver对象(2)通过ContentResolver对象来query,insert,update,delete来进行操作在实现query,insert,update,delete时有一个重要的参数Uri类,Uri一个重要的方法Uri.parse(String str)用来解析str字符串,而str字符串格式一般都有A 程序提供给B程序,B程序按照指定的格式去请求。
《Android移动应用开发》访问系统ContentProvider

参数说明 uri 用于查询ContentProvider的Uri。 projection 用于标识 uri 中有哪些列需要包含在返回的 Cursor 对象中。 selection 作为查询的过滤参数,类似于 SQL 中 Where 语句之后的条件选择。 selectionArgs 查询条件参数,配合 selection 参数使用。 sortOrder 查询结果的排序方式。
2 使用ContentProvider
访问系统ContentProvider
方法
Activity中调用getContentResolver()获取ContentResolver对象 ContentResolver对象具有调用ContentProvider 中同名方法的方法,可提供持续存储的基本 “CRUD”(创建、检索、更新和删除)功能。
Content Resolver
Data
SQLite
XML
Remote Store
1 认识ContentProvider
系统ContentProvider
多媒体提供者 日历提供者 联系人提供者 文档提供者
2 使用ContentProvider
访问系统ContentProvider
基本步骤
1)为应用程序添加ContentProvider的访问权限。 2)通过getContentResolver()方法得到ContentResolver对象。 3)调用ContentResolver类的query()方法查询数据,该方法会返回一个Cursor对象。 4)对得到的Cursor对象进行分析,得到需要的数据。 5)调用Cursor类的close()方法将Cursor对象关闭。
内容提供者ContentProvider的使用详解

内容提供者ContentProvider的使用详解1.什么是ContentProvider首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少。
ContentProvider为不同的软件之间数据共享,提供统一的接口。
也就是说,如果我们想让其他的应用使用我们自己程序内的数据,就可以使用ContentProvider定义一个对外开放的接口,从而使得其他的应用可以使用咱们应用的文件、数据库内存储的信息。
当然,自己开发的应用需要给其他应用共享信息的需求可能比较少见,但是在Android系统中,很多系统自带应用,比如联系人信息,图片库,音频库等应用,为了对其他应用暴露数据,所以就使用了ContentProvider机制。
所以,我们还是要学习ContentProvider的基本使用,在遇到获取联系人信息,图片库,音频库等需求的时候,才能更好的实现功能2.如何定义一个ContentProviderAndroid系统为了让我们更好的对外暴露数据,提供了统一的接口,所以定义了抽象类ContentProvider,因此,如果我们想对外提供数据,我们需要继承ContentProvider,并且实现下面的这几个方法:onCreate()当我们的provider初始化时被调用,我们应该在这个方法里面完成部分初始化操作query() 查询方法,用于给调用者返回数据insert() 插入操作,用于让外部应用插入数据到内容提供者中update() 更新操作,用于更新内容提供者的数据delete() 用于删除数据getType 返回内容提供者的MIME Type上面这些方法,当我们继承自ContentProvider的时候,eclipse 会自动的给我们添加,但是这并不代表我们每个方法都需要自定义实现。
如果我们只希望给其他应用提供数据,而不允许其他应用修改我们的数据,那么我们只需要实现onCreate(),getType()和query()这三个方法就可以了,其他的三个方法我们可以根据业务需求,实现或者是不实现。
android开发contentprovider教学课堂PPT

String sortOrder)
Ø 方法返回一个Cursor对象。
uri: ContentProvider的uri
联系人的uri:
ContactsContract.Contacts.CONTENT_URI
projection:要查询的列名。
selection:查询的条件
selectionArgs:查询条件中通配符对应的值
创建适配器
SimpleCursorAdapter useradapter =
new SimpleCursorAdapter(
用户ID的uri
this, erlistitem, usercursor,
new String[]{ContactsContract.Contacts._ID,
lstshow.setAdapter(adapter);
}
}
18
Ø读取联系人姓名和电话 Ø使用ListView显示查询的数据。
其他应用中可根据需要访问单词本应用保存在数据库中 的数据。
如:某娱乐软件的界面下端可随机出现一些记录的生词 ,帮助用户在不经意中加强对单词的记忆。
13
Ø步骤:
制作开放数据的单词本应用
Android 软件工程师系列课程
开发单词本应用,设计数据库。
添加ContentProvider子类,开放数据库数据。
Cursor cursor=null;
if(matcher.match(uri)==1){
cursor = db.rawQuery("select * from wordstudy",null);
}
return cursor;
} ………………………..
10_Android-ContentProvider

使用内容供应商共享数据如果直接访问磁盘文件(SDCard|File|SQLite数据库|首选项),需要很多底层的交互细节,但该种方式,只使用url即可对应用程序进行访问,并统一了数据访问方式。
public class PersonContentProvider extends ContentProvider{//在该生命周期中才能正确得到Content对象。
public boolean onCreate(){//...}public Uri insert(Uri uri,ContentValues values);....}<application android:icon="@drawable/icon"Android:label="@string/app_name"><!--注册供应商--><provider android:name=".PersonContentProvider"Android:authorities="cn.itcast.providers.personprovider"/></application>URI:Content://cn.itcast.provider.personprovider/person/10Scheme 主机名或authority 路径Scheme:android规定,必须是content://Authority:唯一标识该供应商。
path:代表操纵的数据。
将字符串转换成Uri对象Uri uri = Uri.parse("content://xxxx/person/10");UriMatcher:使用该类,可以判断Uri如何哪一种模式//若不匹配,返回UriMather.NO_MA TCHUriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);//一次添加匹配的模式串,以及匹配后返回的数值//${authority} ${path}sMatcher.addURI("cn.itcast.contentprovider","person",1);sMatcher.addURI("cn.itcast.contentprovider","person/#",2);switch(sMatcher.match(Uri)){case 1:case 2:.....//获取uri后边ID部分的话,可以通过Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person");Uri resultUri = ContentUris.withAppendedId(uri,10); //...person/10Uri.parse("content://cn.itcast.provider.personprovider/person/10")Long personid = ContentUris.parseId(uri);XxxContentProvider extends ContentProvider{....//该方法用于返回当前Url所代表数据的MIME类型,如果操作的数据属于集合类型,//那么MIME类型字符串应该以vnd.android.cursor.dir/开头//如:''vnd.android.cursor.dir/person"//如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以//vnd.android.cursor.item/开头//如:vnd.android.cursor.item/personpublic String getType(Uri uri){..};}使用内容解析器(ContentResolver):ContentResolver resolver = getContentResolver();Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person");ContentV alues values = new ContentV alues();values.put("name", "itcast");values.put("age", 25);//插入resolver.insert(uri, values);//查询resolver.query(uri, null, null, null, "personid desc");//更新resolver.update(updateIdUri, updateV alues, null, null);//删除resolver.delete(deleteIdUri, null, null);监听contentprovider的数据变化//供应商中的crud方法完成后需要发出数据变更的通知,以通知那些感兴趣的监听者XxxContentProvider extends ContentProvider{public long insert(){...getContext().getContentResolver().notifyChange(uri,null);}内容解析器如若要对数据变更,需要使用ContentObserver对uri进行监听,收到通知后,回调处理方法onChange();context.getContentResolver().registerContentObserver(uri,true,new MyContentObserver(new Handler()));class MyContentObServer extends ContentObserer{public MyContentObServer(Handler handler){super(handler);}public void onChange(){...}}监听用户发送(接收)的短信系统自带的短信程序发送(或接收)短信时,会通过ContentProvider把短信保存进数据库,并且发出一个变更通知(notifyChange).使用ContentObserver对数据变化进行监听,在用户发送短信时,就会被ContentObserver窃听到短信.//系统Context.getContentResolver().notifyChange("content://sms",null);//客户端:Context.getContentResolver().registerObserver(uri,false,newContentObserver(new Handler()){});// content://sms/outbox// content://sms/outbox// content://sms/outboxCursor cursor =getContentResolver().query(Uri.parse("content://sms/outbox"),null,cursor.getInt(cursor.getColumnIndex("_id")));cursor.getString(cursor.getColumnIndex("address")));cursor.getString(cursor.getColumnIndex("body")));cursor.getLong(cursor.getColumnIndex("date")));注:<uses-permission android:name="android.permission.READ_SMS" />。
ContentProvider详解

ContentProvider详解⼏个概念:Cursor、 Content provider 、 Uri 、contentresolver1、Cursor :个⼈理解为数据库中的⼀⾏数据,它是每⾏数据的集合。
它是⼀个类。
通过它的⼀系列⽅法,我们可以对数据库中的每⾏进⾏定位,我们还可以知道每⼀列的信息。
⽐如:cursor(游标).moveToFirst(),表⽰定位到第⼀⾏,然后我们通过其他⽅法可以知道每列的名称,每列的数据类型等。
2、Content Provider :内容提供者,我们⼀个application中的其他类假如想操作数据库中的数据的话,就可以直接对此进⾏操作,⽽避免了对数据库进⾏直接操作,再说了,数据库这些个东西有权限要求的,我们不可能把数据库直接暴露出来,所以,通常采⽤这种形式。
其实他就是⼀个提供数据访问的⽹站,我们要访问它的话,就得知道他的域名。
android:authorities . 在minifest.xml中配置如下:(包含两个部分,name 与 anthorities)<provider android:name=".PersonProvider" android:authorities="com.sharpandroid.providers.personprovider"/>当某个应⽤,可能是外部的,可以通过这两个属性来找到这个Content Provider了。
Content Provider ⽀持在多个应⽤中存储和读取数据。
这也是跨应⽤共享数据的唯⼀⽅式。
在android系统中,没有⼀个公共的内存区域,供多个应⽤共享存储数据。
3、Uri:这个东西就是提供者提供数据的详细地址,到底是哪些数据,⽤此来对数据进⾏过滤操作。
假如说,Content Provider是⼀个DNS,域名的话。
那么Uri可以认为是IP地址,我们通过此IP地址找到我们所需要的数据。
Android四大组件 之ContentProvider
获得系统的CP 的数据
• Android系统中会给应用提供一些开放的系统数据,当然 它是采用CP的这种形式。 • 通过ContentResolver访问系统CP的步骤: – 调用Activity的ContentResolver获取CR对象 – 调用CR中的insert,delete,update,query方法获得系 统CP提供的数据
URI
例如以下是系统的一些 URI: content://media/internal/images (该 URI 返回设备上存储的所有图片)
content://contacts/people/5 (联系人信息中 ID 为 5 的联系人记录)
content://contacts/people (该 URI 返回设备上的所有联系人信息)
• 注意:
– 要获得系统CP提供的数据,必须要了解该CP的Uri。
使用CP 管理联系人
• Android系统中Contacts应用来管理联系人,而且暴露相 应CP。 • 此CP支持的Uri如下: – ContactsContract.Contacts.CONTENT_URI :管理联系 人的Uri – monDataKinds.Phone.CONTENT_ URI:管理联系人的电话的Uri – monDataKinds.Email.CONTENT_ URI:管理联系人的Email的Uri
2)、parseId(uri)//用于从指定uri中解析出所包含的id的值
Uri uri = Uri.parse("content://com.yfz.Lesson/people/10") long personid = ContentUris.parseId(uri); 最后personid 为 :10
Android学习之基础知识十—内容提供器(ContentProvider)
Android学习之基础知识⼗—内容提供器(ContentProvider)⼀、跨程序共享数据——内容提供器简介 内容提供器(Content Provider)主要⽤于在不同的应⽤程序之间实现数据共享的功能,它提供了⼀套完整的机制,允许⼀个程序访问另⼀个程序中的数据,同时还能保证被访数据的安全性,⽬前,使⽤内容提供器是Android实现跨程序共享数据的标准⽅式。
不同于⽂件存储和SharedPreferences存储中的两种全局可读写操作模式,内容提供器可以选择只对哪⼀部分数据进⾏共享,从⽽保证我们程序中的隐私数据不会有泄漏的风险。
在正式学习内容提供器之前,我们还需要先掌握另外⼀个⾮常重要的知识——Android运⾏时权限,因为待会⼉的内容提供器⽰例中会使⽤到运⾏时权限的功能。
不光是内容提供器,开发过程中经常会⽤到运⾏时权限,因此必须牢牢掌握。
⼆、运⾏时权限 Android开发团队在Android6.0系统中引⽤了运⾏时权限这个功能,⽐之前的Android权限机制能更好的保护⽤户的安全和隐私。
2.1、Android权限机制详解 Android现在将所有的权限归成了两类:⼀类是普通权限,⼀类是危险权限。
普通权限是指那些不会直接威胁到⽤户的安全和隐私的权限,对于这部分权限申请,系统会⾃动帮我们进⾏授权,⽽不需要⽤户再去⼿动操作了,⽐如查看⽹络连接,开机⾃启等权限;危险权限则表⽰那些可能会触及⽤户隐私,或者对设备安全性造成影响的权限,如获取设备联系⼈信息、定位设备的地理位置等,对于这部分权限申请,必须要有⽤户⼿动点击授权才可以,否则程序就⽆法使⽤相应的功能。
虽然Android中⼀共有上百种权限,但是危险权限⼀共就只有9组24个,其他剩下的就都是普通权限。
下⾯是危险权限的列表:注意:表格中每个危险权限都是属于⼀个权限组,我们在进⾏运⾏时权限处理时使⽤的是权限名,但是⽤户⼀旦同意授权了,那么该权限所对应的权限组中所有的其他权限也会同时被授权。
Android实验10ContentProvider
实验十ContentProvider一、实验目的及任务1、ContentProvider的使用2、ContentResolver的使用二、实验环境1、Jdk2、Eclipse3、Android SDK三、实验步骤自定义一个ContentProvider,完成下面界面。
底层使用SQLite数据库,支持数据的添加、删除、更新和查询等基本操作。
四、实验代码布局<RelativeLayoutxmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity"><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="姓名"/><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignRight="@+id/textView1"android:layout_below="@+id/textView1"android:layout_marginTop="31dp"android:text="年龄"/><TextViewandroid:id="@+id/textView3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/textView2"android:layout_below="@+id/textView2"android:layout_marginTop="47dp"android:text="身高"/><EditTextandroid:id="@+id/editText1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_alignTop="@+id/textView1"android:ems="10"/><EditTextandroid:id="@+id/editText2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/editText1"android:layout_alignTop="@+id/textView2"android:ems="10"/><EditTextandroid:id="@+id/editText3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/textView3"android:layout_alignBottom="@+id/textView3"android:layout_alignLeft="@+id/editText2"android:ems="10"><requestFocus/></EditText><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_alignBottom="@+id/button1"android:layout_alignLeft="@+id/editText3"android:textSize="10px"android:text="全部显示"/><TextViewandroid:id="@+id/textView4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_below="@+id/button1"android:layout_marginTop="18dp"android:text="ID"/><TextViewandroid:id="@+id/textView5"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_below="@+id/button5"android:layout_marginTop="41dp"android:layout_toLeftOf="@+id/button5"android:text="TextView"/><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/textView4"android:layout_below="@+id/editText3"android:layout_marginTop="14dp"android:text="添加数据"android:textSize="10px"/><Buttonandroid:id="@+id/button4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/button3"android:layout_alignBottom="@+id/button3"android:layout_alignParentRight="true"android:text="全部删除"android:textSize="10px"/><Buttonandroid:id="@+id/button6"android:layout_height="wrap_content"android:layout_alignTop="@+id/textView4"android:layout_toLeftOf="@+id/button7"android:text="ID查询"android:textSize="10px"/><Buttonandroid:id="@+id/button7"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/button6"android:layout_alignBottom="@+id/button6"android:layout_alignParentRight="true"android:text="ID更新"android:textSize="10px"/><Buttonandroid:id="@+id/button5"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/button6"android:layout_alignBottom="@+id/button6"android:layout_alignLeft="@+id/button2"android:text="ID删除"android:textSize="10px"/><Buttonandroid:id="@+id/button3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_above="@+id/textView4"android:layout_toLeftOf="@+id/button4"android:text="清楚显示"android:textSize="10px"/><EditTextandroid:id="@+id/editText4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBottom="@+id/button5"android:layout_alignLeft="@+id/textView4"android:layout_toLeftOf="@+id/button5"android:ems="10"/></RelativeLayout>JAVA代码============================================================================== package .xwp.android.contentprovider;import android.content.UriMatcher;import .Uri;import android.provider.BaseColumns;public class ContentData {public static final String AUTHORITY = "hb.android.contentProvider";public static final String DATABASE_NAME = "teacher.db";public static final int DATABASE_VERSION = 4;public static final String USERS_TABLE_NAME = "teacher";public static final class UserTableData implements BaseColumns {public static final String TABLE_NAME = "teacher";public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY + "/teacher");Public.static.final.String.CONTENT_TYPE.= ."vnd.android.cursor.dir/hb.android.teachers";public.static.final.String.CONTENT_TYPE_ITME.= ."vnd.android.cursor.item/hb.android.teach er";public static final int TEACHERS = 1;public static final int TEACHER = 2;public static final String TITLE = "name";public static final String NAME = "age";public static final String DATE_ADDED = "high";public static final String DEFAULT_SORT_ORDER = "_id desc";public static final UriMatcher uriMatcher;static {uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI(ContentData.AUTHORITY, "teacher", TEACHERS);uriMatcher.addURI(ContentData.AUTHORITY, "teacher/#", TEACHER);}}}==============================================================================import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;public class DBOpenHelper extends SQLiteOpenHelper {public DBOpenHelper(Context context, String name, CursorFactory factory,int version) {super(context, name, factory, version);}public DBOpenHelper(Context context, String name, int version) {this(context, name, null, version);}@Overridepublic void onCreate(SQLiteDatabase db) {System.out.println("create table");db.execSQL("create table " + erTableData.TABLE_NAME+ "(" + erTableData._ID+ " INTEGER PRIMARY KEY autoincrement,"+ + " varchar(20),"+ erTableData.TITLE + " varchar(20),"+ erTableData.DATE_ADDED + " varchar(20),"+ ";");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}}=============================================================================== package xwp.android.contentprovider;import erTableData;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import .Uri;import android.text.TextUtils;public class TeacherContentProvider extends ContentProvider {private DBOpenHelper dbOpenHelper = null;@Overridepublic boolean onCreate() {dbOpenHelper = new DBOpenHelper(this.getContext(), ContentData.DATABASE_NAME, ContentData.DATABASE_VERSION);return true;}@Overridepublic Uri insert(Uri uri, ContentValues values){SQLiteDatabase db = dbOpenHelper.getWritableDatabase();long id = 0;switch ( UserTableData.uriMatcher.match(uri)) {case UserTableData.TEACHERS:id = db.insert("teacher", null, values);return ContentUris.withAppendedId(uri, id);case UserTableData.TEACHER:id = db.insert("teacher", null, values);String path = uri.toString();return Uri.parse(path.substring(0, stIndexOf("/"))+id);default:throw new IllegalArgumentException("Unknown URI " + uri);}}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();int count = 0;switch ( UserTableData.uriMatcher.match(uri)) {case UserTableData.TEACHERS:count = db.delete("teacher", selection, selectionArgs);break;case UserTableData.TEACHER:content://hb.android.teacherProvider/teacher/10long personid = ContentUris.parseId(uri);String where = "_ID=" + personid;where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : ""; count = db.delete("teacher", where, selectionArgs);break;default:throw new IllegalArgumentException("Unknown URI " + uri);}db.close();return count;}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();int count = 0;switch ( UserTableData.uriMatcher.match(uri)) {case UserTableData.TEACHERS:count = db.update("teacher", values, selection, selectionArgs);break;case UserTableData.TEACHER:content://com.ljq.provider.personprovider/person/10long personid = ContentUris.parseId(uri);String where = "_ID=" + personid;where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : ""; count = db.update("teacher", values, where, selectionArgs);break;default:throw new IllegalArgumentException("Unknown URI " + uri);}db.close();return count;}@Overridepublic String getType(Uri uri) {switch ( UserTableData.uriMatcher.match(uri)) {case UserTableData.TEACHERS:return UserTableData.CONTENT_TYPE;case UserTableData.TEACHER:return UserTableData.CONTENT_TYPE_ITME;default:throw new IllegalArgumentException("Unknown URI " + uri);}}@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {SQLiteDatabase db = dbOpenHelper.getReadableDatabase();switch ( UserTableData.uriMatcher.match(uri)) {case UserTableData.TEACHERS:return db.query("teacher", projection, selection, selectionArgs, null, null, sortOrder);case UserTableData.TEACHER:long personid = ContentUris.parseId(uri);String where = "_ID=" + personid;where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";return db.query("teacher", projection, where, selectionArgs, null, null, sortOrder);default:throw new IllegalArgumentException("Unknown URI " + uri);}}五、实验结果截图。
03课件-BTC-Android-01-第10章 Android-基本组件(4)-ContentProvider
新建立的类继承ContentProvider后,Eclipse会提示程序开发人员需 要重载部分代码,并自动生成需要重载的代码框架 下面的代码是Eclipse自动生成的代码框架
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. import android.content.*; import android.database.Cursor; import .Uri;
public class PeopleProvider extends ContentProvider{ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; }
13
© 2012 Inspur Group
Inspur Education
ContentProvider的开发步骤
创建数据提供者
12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
ri uri) { // TODO Auto-generated method stub return null; }
如果URI是单条数据,则返回的MIME数据类型应以 vnd.android.cursor.item开头 如果URI是多条数据,则返回的MIME数据类型应以 vnd.android.cursor.dir/开头
12
© 2012 Inspur Group
Inspur Education
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
移动平台软件设计
ContentResolver方法介绍
query(Uri uri, String[] projection, String selection, String[] selectionAr gs,String sortOrder):通过Uri进行查询,返回一个Cursor。 insert(Uri url, ContentValues values):将一组数据插入到Uri 指定的 地方,返回最新添加那个记录的Uri。
10.2 ContentResolver
应用程序使用 ContentResolver 对象,利用URI,才能访问 ContentProvider提供的数据集。
一个ContentProvider可以提供多个数据集 可以为多个ContentResolver服务
移动平台软件设计
ContentProvider数据集
update(Uri uri, ContentValues values, String where, String[] selectio nArgs):更新Uri指定位置的数据,返回更新的行数。
delete(Uri url, String where, String[] selectionArgs):删除指定Uri并 且符合一定条件的数据,返回删除的行数。
移动平台软件设计
导出contacts2.db并查看
3个重点表: raw_contact表 data表 contacts表
移动平台软件设计
(1)raw_contacts表
主要存储了联系人的名称、名称的字母索引和帐户类型信息( 区别是本机号码还是SIM卡号码) 主要字段:
_id :主键,表的ID
?为占位符
功能描述:在联系人数据集 (ContactsContract.Contacts.CONTENT_URI)中查询用户名 (displa_name)包含有“zz”字符串(like %zz%)的记录,返回的结果集是_id,display_name和 has_phone_number这三个字段内容,且按display_name值降序排序(display_name desc)。 对应的SQL描述:select _id,display_name,has_phone_number from Contacts表 where display_name like %zz% orderby display_name desc
Android系统附带的ContentProvider包括:
Browser:存储如浏览器的信息。
CallLog:存储通话记录等信息。 Contacts:存储联系人等信息。 MediaStore:存储媒体文件的信息。 Settings:存储设备的设置和首选项信息。
【返回】
移动平台软件设计
移动平台软件设计
参数含义 -- 以查询为例
查询方法:通过Uri进行查询,返回一个Cursor。
resolver.query( Uri uri,
uri:查询的数据集 projection:返回数据集的字段 selection:查询条件 selectionArgs:查询条件的值 sortOrder:排序方式
移动平台软件设计
data表结构
移动平台软件设计
(3)contacts表
contacts表主要存储联系人lookup(查找联系人的关键)
contact表的数据是由系统组合raw_contact表中的数据而自动 生成。contact表中的一行表示一个联系人。
主要字段:
lookup:存储查找联系人的lookup信息 has_number_phone:联系人电话个数(0表示联系人无电话)
移动平台软件设计
ContentProvider
ContentProvider提供了应用程序之间共享数据的方法。
应用程序通过ContentProvider访问数据而不需要关心数据具体 的存储及访问过程,这样既提高了数据的访问效率,同时也保 护了数据。
移动平台软件设计
ContentProvider
移动平台软件设计
10.4 综合示例 -- 手机上的联系人操作
准备知识
查询操作
添加操作
更新操作
删除操作
自学
【返回】
移动平台软件设计
准备知识:系统联系人数据库分析
打开DDMS
/data/data/com.android.provider.contacts /databases/contacts2.db文件
表明:我们不可以直接向 contacts表中插入数据
_id :主键,表的ID,系统自动生成,是联系人的唯一标识
photo_id:头像的ID
times_contacted:通话记录的次数 last_time_contacted: 最后的通话时间
移动平台软件设计cont来自cts表结构contacts表数据示例
display_name: 联系人名称
phonebook_label:名称的字母索引 account_id:帐户类型
contact_id:外键,与contacts表的_ID字段关联(这个id值是系统 生成的)
移动平台软件设计
raw_contacts表结构
移动平台软件设计
mimetype_id取值
一般data1:存放主信息(如联系人名称、电话、Email信息) data2:存放data1信息对应的类型,如1(Phone.TYPE_HOME)表示家庭座 机,2(Phone.TYPE_MOBILE)表示为手机
momDataKinds包中定义了与常用的数据类型相对应的一些类, 如monDataKinds.Phone类: monDataKinds.Phone.NUMBER表示"data1" monDataKinds.Phone.TYPE表示"data2" monDataKinds.Phone.TYPE_MOBILE表示为手机类型
Android应用程序运行在不同的进程空间中,因此不同应用 程序的数据是不能够直接访问的。
为了增强程序之间的数据共享能力,Android系统虽然提供 了像SharedPreferences这类简单的跨越程序边界的访问方 法,但这些方法都存在一定的局限性。
Android四大核心组件: Activity、BroadcastReceiver、Service、ContentProvider
content://<authority>/<data_path>/<id>
固定前缀 数据路径 用来确定请求的 是哪个数据集 数据编号,用来匹配数据集中_ID字段的值 (用来唯一确定数据集中的一条记录) 如果请求的数据并不只限于一条数据,则 <id>可以省略
授权者名称(保证唯一性) 用来确定具体由哪一个 ContentProvider提供资源
URL是标识资源的物理位置,相当于文件的路径(例如 /logo.png);
URI则是标识资源的逻辑位置,并不提供资源的具体位置。
比如说电话薄中的数据,如果用URL来标识的话,可能会是一个很复杂 的文件结构,而且一旦文件的存储路径改变,URL也必须得改动。 但若是URI,则可以用诸如content://contract /people这样容易记录的逻辑 地址来标识,而且并不需要关心文件的具体位置,即使文件位置改动也 不需要做变化。 当然这都是对于用户来说,后台程序中URI到具体位置的映射还是需要程 序员来改动的。
raw_contacts表
移动平台软件设计
三 张 表 关 系
系统自动生成contacts表
【返回】
移动平台软件设计
1. 查询操作:显示所有人的电话信息
联系人id
联系人名称 display_name
联系人电话(可能有多个)
移动平台软件设计
查询主要思路
主要步骤:
从contacts、raw_contacts、data三表之间的关联入手
移动平台软件设计
主讲教师 张智 计算机学院
移动平台软件设计
第10章 ContentProvider
10.1 ContentProvider
10.2 ContentResolver
10.3 基本用法
10.4 综合示例
移动平台软件设计
10.1 ContentProvider
Why ContentProvider ?
String[] projection, String selection, String[] selectionArgs, String sortOrder );
移动平台软件设计
用法示例 -- 以查询为例
ContentResolver resolver = getContentResolver();
移动平台软件设计
URI示例
content://contacts/people/ 表示全部联系人信息的URI
content://contacts/people/1 表示ID=1的联系人信息的URI
content://com.android.contacts/contacts/ 原生写法
已不推 荐使用
ContentProvider数据集类似于数据库的数据表,每行是一 条记录,每列具有相同的数据类型。 如下表所示。每条记录都包含一个long型的字段_ID,用 来唯一标识每条记录
_ID NAME AGE HEIGHT
1
2
Tom
Jim
21
22
1.81
1.78
移动平台软件设计
什么是URI
URI:通用资源标志符(Uniform Resource Identifier), 用来定位远程或本地的可用资源。 URI基本格式: