Android基础知识总结---四大组件之一ContentProvider(一)
2016-07-23 23:46
561 查看
一、ContentProvider的简介
1.当系统部署多个Android应用之后,有时候就需要在不同的应用之间共享数据,比如现在有一个短信接收应用,用户想把接收到的陌生短信的发信人添加到联系人管理应用中,就需要不同应用之间共享数据。对于这种需要在不同应用之间共享数据的需求,可以让一个应用程序直接去操作另外一个应用程序所记录的数据,比如可以操作它所记录的SharedPreferences,文件或数据库等。但这种方式显得太杂乱了。不同应用程序记录数据的方式差别很大,这种方式不利于应用程序之间进行数据交换。为了在不同应用程序之间交换数据,Android提供了不同应用程序之间进行数据交换的标准API:ContentProvider,它也是Android中四大组件之一,当然ContentProvider既然作为Android应用的四大组件之一,那么就需要在AndroidManifest.xml文件中进行配置。当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用程序就可以通过提供ContentProvider来实现,其他应用程序就可通过ContentResolver来操作ContentProvider暴露的数据,包括增加数据,删除数据,修改数据,查询数据等。同时Android已经为常见的一些数据提供了默认的ContentProvider.比如说:短信,通讯录,通话记录,多媒体等。二、开发自己应用程序的ContentProvider
第一步:定义自己的ContentProvider类,该类继承ContentProvider基类第二步:暴露需要提供的数据:
重写onCreate():该方法在ContentProvider创建后被调用
重写getType():该方法用于返回当前Uri所代表的数据的MIME类型,
如果该Uri对应的数据可能包括多条记录,那么MIME类型字符串应用以vnd.android.cursor.dir/开始
如果该Uri对应的数据只包括一条记录,那么MIME类型字符串应用以vnd.android.cursor.item/开始
重写insert(Uri,ContentValue values):根据Uri插入values对应的数据
重写delete(Uri,String selection,String[] selectArgs):根据Uri删除select条件匹配的全部记录
重写update():根据Uri修改select条件所匹配的全部记录
重写query():根据Uri查询出select条件所匹配的全部记录
注意:重写的这些方法并不是给该应用本身调用的,而是供其他应用通过ContentResolver来调用。
第三步:在AndroidManifest.xml文件中注册该ContentProvider,指定android:authorities属性
三、ContentProvider中一些属性的含义
1.Uri:用于表示这个ContentProvider所提供的数据
Uri:统一资源标识符–URL:统一资源定位符
–URN:统一资源命名符
如:http://www.baidu.com/index.html
http:// 是URL的协议部分,是固定的
www.baidu.com是域名部分,是固定的
index.html是网站资源部分,是动态的
而ContentProvider提供的Uri,例如:
如:content://com.ecjtu.dictprovider/users
content://是Uri的协议部分,暴露ContentProvider,访问contentProvider的协议默认是content://,这个部分是固定的。
com.ecjtu.dictprovider:是ContentProvider的authority。系统就是由这个部分找到操作哪个ContentProvider.
如果需要访问指定的ContentProvider,这个部分也是固定的。
users:是资源部分,当访问者需要访问不同资源时,这个部分是动态改变的。
Uri提供了parse()静态方法,可以将字符串转换为Uri:
Uri uri = Uri.parse(“content://com.ecjtu.dictprovider/user/2”);
2、ContentResolver
通过ContentResolver来操作ContentProvider所暴露的数据使用步骤:
第一步:通过Context中获取ContentResolver象:getContentResolver()
第二步:调用ContentResolver中相应的方法:insert,delete,update,query
四、实现原理
A应用:通过ContentProvider提供数据^
|
|
Uri
^
|
|
B应用: 通过ContentResolver获取数据
注意:
当B应用调用ContentResolver的insert方法时,实际上相当于调用了该Uri对应的ContentProvider(属于A应用)的insert方法。
当B应用调用ContentResolver的update方法时,实际上相当于调用了该Uri对应的ContentProvider(属于A应用)的update方法。
在A应用里编写ContentProvider
1)重写onCreate(),getType(),insert(),delete(),update(),query()
2)在Manifest中配置标签
android:name provider的全类名
android:authorities 为该Provider设置访问该URI的Host部分
android:exported 设置该Provider可以被其他应用程序访问
在B应用
1)调用getContentResolver,获取resolver对象
2)调用insert(),delete(),update(),query(),传入URI实现数据访问
五、操作系统的ContentProvider提供的数据:
a)全部短信的Uri为:content://sms/查询出所有的短信:
Cursor cursor=cr.query(“content://sms/”, new String[]{“_id”,”address”,”body”,”date”}, null, null,null);
然后在ListView中显示出来
注意需要添加权限:android.permission.READ_SMS
上面只是获取的部分内容:完整的内容可以在数据库表中看到:
通讯录数据库是:/data/data/com.android.providers.contacts/databases/contacts2.db
短信数据库是:/data/data/com.android.providers.telephony/databases/mmssms.db
b)自己编写发送短信的应用并将短信写入到数据库中
短信管理器SmsManager(android.telephony.SmsManager)
SmsManager是Android中提供的另一个非常常见的服务。
获取SmsManager的方式:manager = SmsManager.getDefault();
SmsManager提供了系列sendXxxMessage()方法用于发送短信,不过在实际应用来看,短信都是普通的文本内容,也就是调用sendTextMessage()方法进行发送即可。
sendTextMessage(String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent)
第一个参数:收件人的手机号码
第二个参数:短信服务中心,如果为null,就是用当前默认的短信服务中心
第三个参数:短信内容
第四个参数:如果 sentIntent不为空,当短信发出时,成功或者失败的信息报告是通过sentIntent来广播给接收器接收。
接收的方式:在接收器中getResultCode()获取,这个PendingIntent被广播出去,成功的结果代码是Activity.RESULT_OK,或者下面这些错误之一 :
RESULT_ERROR_GENERIC_FAILURE
RESULT_ERROR_RADIO_OFF
RESULT_ERROR_NULL_PDU
对于 RESULT_ERROR_GENERIC_FAILURE,这个sentIntent可能包括额外的”errorCode”,包含一些具体有用的信息帮助检查 。基于SMS控制的全部程序去检查 sentIntent.
如果 sentIntent 为空,如果该参数为空,则发信程序会被所有未知的应用程序检查一遍,这样会导致发送的时间延长
第五个参数:如果不为null,当这个短信发送到接收者那里时,这个PendtingIntent会被广播,状态报告生成的pdu数据(指对等层次之间传递的数据单位)会拓展到数据(”pdu”)
c)写入到数据库
Uri uri= Uri.parse(“content://sms/sent”);
ContentValues contentValues=new ContentValues();
contentValues.put(“address”,address);
contentValues.put(“body”,body);
contentValues.put(“date”, System.currentTimeMillis()); //创建时间
contentValues.put(“read”, 0); //0:未读;1:已读
contentValues.put(“type”, 2); //1:接收;2:发送
cr.insert(uri,contentValues);
注意:需要添加权限
六、操作系统的ContentProvider
Android系统本身提供了大量的ContentProvider,例如联系人信息,系统的多媒体信息等。开发者自己开发Android应用也可以通过ContentResolver来调用系统的ContentProvider提供的数据。为了操作系统的ContentProvider,需要了解ContentProvider的Uri,以及该ContentProvider所操作的数据列的列名。a)使用ContentProvider管理联系人
ContactsContract.Contacts.CONTENT_URI: 管理联系人的Uri
ContactsContract.CommonDataKinds.Phone.CONTENT_URI: 管理联系人的电话的URI
ContactsContract.CommonDataKinds.Email.CONTENT_URI: 管理联系人的Email的URI
例:查看手机SD卡中的音乐媒体文件
通过Android ContentResolver提供的查询方法:
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
各参数的含义:
Uri:指明要查询的数据库名称加上表的名称,从MediaStore中我们可以找到相应信息的参数。
Projection: 指定查询数据库表中的哪几列,返回的游标中将包括相应的信息。Null则返回所有信息。
selection: 指定查询条件
selectionArgs:填充通配符,如果查询条件里面没有通配符则可以为null
SortOrder:指定查询结果的排列顺序
下面的命令将返回所有在外部存储卡上的音乐文件的信息:
Cursor cursor = query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
得到cursor后,我们可以调用Cursor的相关方法具体的音乐信息:
歌曲ID:MediaStore.Audio.Media._ID
Int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
歌曲的名称:MediaStore.Audio.Media.TITLE
String tilte = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
歌曲的专辑名:MediaStore.Audio.Media.ALBUM
String album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
歌曲的艺术家:MediaStore.Audio.Media.ARTIST
String artist = cursor.getString(cursor .getColumnIndex(MediaStore.Audio.Media.ARTIST));
歌曲的歌手名:MediaStore.Audio.Media.ARTIST
String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
歌曲文件的路径:MediaStore.Audio.Media.DATA
String url = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
歌曲的总播放时长:MediaStore.Audio.Media.DURATION
Int duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
歌曲文件的大小:MediaStore.Audio.Media.SIZE
Int size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
歌曲是否为音乐:MediaStore.Audio.Media.IS_MUSIC
int isMusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));
七、ContentProvider续:
1.UriMatcher和ContentUris的使用:为了确定该ContentProvider实际能处理的Uri,以及确定每个方法中Uri参数所操作的数据,
Android系统提供了UriMatcher工具类。
a)UriMatcher工具类提供了如下两个主要方法:
addURI(String authority,String path,int code):
该方法用于向UriMatcher对象注册Uri.其中authority和path组合成一个Uri,而code则代表该Uri对应的标识码。
int match(Uri uri):根据前面注册的Uri来判断指定Uri对应的标识码。如果找不到匹配的标识码,该方法返回-1.
比如:
UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI(“com.ecjtu.dictprovider”,”users”,1)
matcher.addURI(“com.ecjtu.dictprovider”,”user/#”,2)#号是通配符,上面的代码注册了两个Uri。
匹配标识符:
matcher.match(Uri.parse(“content://com.ecjtu.dictprovider/users”)//返回标识符1
matcher.match(Uri.parse(“content://com.ecjtu.dictprovider/user/2”)//返回标识符2
matcher.match(Uri.parse(“content://com.ecjtu.dictprovider/user/10”)//返回标识符2
至少需要为UriMatcher对象注册多少个Uri,取决于系统的业务需求。
对于content://com.ecjtu.dictprovider/users通常代表返回所有数据
对于content://com.ecjtu.dictprovider/user/2通常代表访问指定数据项,其中最后一个数值往往代表了该数据的ID。
b)ContentUris
它是一个操作Uri字符串的工具类。提供如下两个方法:
withAppendedId(uri,id)用于为路径后加上ID部分
如:Uri resultUri=ContentUris.withAppendedId(uri,2)
parseId(uri):用于从指定Uri中解析所包含的ID值
2.监听ContentProvider的数据改变—>ContentObserver
当ContentProvider将数据共享出来之后,ContentResolver会根据业务需要去主动查询ContentProvider所共享数据,在有些时候,应用程序需要实时监听ContentProvider所共享数据的改变,并随着ContentProvider的数据的改变而提供响应,这就需要利用ContentObserver了。前面介绍开发ContentProvider时,不管实现insert,delete,update方法中的哪一个,只要该方法导致了ContentProvider里的数据的改变,程序就会调用了如下代码:
getContext().getContentResolver().notifyChange(uri,null);
这行代码可用于通知所有注册在该Uri上的监听者,该ContentProvider所共享的数据发生了改变。监听ContentProvider数据改变的监听器需要继承ContentObserver类,并重写该基类的onChange()方法,当它所监听的ContentProvider的数据发生改变时,该onChange()方法将会被触发。为了监听指定的ContentProvider的数据变化,需要通过ContnetResolver向指定Uri注册ContentObserver监听器:
注册监听器:ContentResolver的registerContentObserver(Uri,boolean,ContentObserver)方法。
第一个参数:监听的Uri
第二个参数:如果该参数设为true,假如注册监听的uri为content://abc,那么Uri为content://abc/xyz,content://abc/xyz/foo的数据改变时也会触发该监听器。如果该参数设为false,假如注册监听的uri为content://abc,那么只有content://abc的数据发生改变时会触发该监听器。
第三个参数:监听器实例
3.自动朗读TTS
自动朗读可以对指定文本内容进行朗读,从而发生声音。这种自动朗读支持的英文名称为TextToSpeech,简称TTS.
创建TTS:TextToSpeech(Context,TextToSpeech.onOnitListener),
传入的监听器负责监听TextToSpeech的初始化结果。创建对象之后,setLanguage(Locale)设置TTS发声引擎使用的语言,国家选项。
speak(String text,int queueMode,HashMap):指定发音任务
queueMode:指定发音队列模式,该参数支持的值有:
TextToSpeech.QUEUE_FLUSH:会中断当前实例正在运行的任务
TextToSpeech.QUEUE_ADD:把新的发音任务添加到当前发音队列中。
shutdown()关闭TextToSpeech,释放资源
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories