14天學會安卓開發(第九天)ContentProvider與BroadcastReceiver
【原文:http://blog.csdn.net/corder_raine/article/details/8317249】
目錄
第九天.ContentProvider與BroadcastReceiver 93
9.1 ContentProvider 93
9.1.1 使用ContentProvider共享資料... 93
9.1.2 Uri介紹... 94
9.1.3 UriMatcher類使用介紹... 95
9.1.4 使用ContentProvider共享資料... 96
9.2 ContentResolver 96
9.2.1 ContentResolver
9.2.2 讀取電話本... 97
9.3 BroadcastReceiver 98
9.3.1 Broadcast Intent Receiver 98
9.3.2 廣播接收者--BroadcastReceiver 98
9.3.4 廣播接收者... 99
9.3.5 鬧鐘與提醒服務Demo.
100
第九天.ContentProvider與BroadcastReceiver
9.1 ContentProvider
9.1.1 使用ContentProvider共享資料
當應用繼承ContentProvider類,並重寫該類用於提供資料和儲存資料的方法,就可以向其他應用共享其資料。雖然使用其他方法也可以對外共享資料,但資料訪問方式會因資料儲存的方式而不同,如:採用檔案方式對外共享資料,需要進行檔案操作讀寫資料;採用sharedpreferences共享資料,需要使用sharedpreferences
API讀寫資料。而使用ContentProvider共享資料的好處是統一了資料訪問方式。
當應用需要通過ContentProvider對外共享資料時,第一步需要繼承ContentProvider並重寫下面方法:
1
2
3
4
5
6
7
|
public class
PersonContentProvider extendsContentProvider{ public boolean
onCreate() public Uri
insert(Uri uri, ContentValues values) public int
delete(Uri uri, String selection, String[] selectionArgs) public int
update(Uri uri, ContentValues values, String selection,String[] selectionArgs) public Cursor
query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) publicString
getType(Uri uri)} |
第二步需要在AndroidManifest.xml使用<provider>對該ContentProvider進行配置,為了能讓其他應用找到該ContentProvider , ContentProvider 採用了authorities(主機名/域名)對它進行唯一標識,你可以把ContentProvider看作是一個網站(想想,網站也是提供資料者),authorities 就是他的域名:
1
2
3
4
5
|
< manifest ....
> < application android:icon = "@drawable/icon" android:label = "@string/app_name" > < provider android:name = ".PersonContentProvider" android:authorities=“com.lxt008.provider.personprovider"/> </ application > </ manifest > |
注意:一旦應用繼承了ContentProvider類,後面我們就會把這個應用稱為ContentProvider(內容提供者)。
9.1.2 Uri介紹
Uri代表了要操作的資料,Uri主要包含了兩部分資訊:1》需要操作的ContentProvider ,2》對ContentProvider中的什麼資料進行操作,一個Uri由以下幾部分組成:
file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtmlclip1/01/clip_image002.gif
ContentProvider(內容提供者)的scheme已經由Android所規定, scheme為:content://
主機名(或叫Authority)用於唯一標識這個ContentProvider,外部呼叫者可以根據這個標識來找到它。
路徑(path)可以用來表示我們要操作的資料,路徑的構建應根據業務而定,如下:
要操作person表中id為10的記錄,可以構建這樣的路徑:/person/10
要操作person表中id為10的記錄的name欄位, person/10/name
要操作person表中的所有記錄,可以構建這樣的路徑:/person
要操作xxx表中的記錄,可以構建這樣的路徑:/xxx
當然要操作的資料不一定來自資料庫,也可以是檔案等他儲存方式,如下:
要操作xml檔案中person節點下的name節點,可以構建這樣的路徑:/person/name
如果要把一個字串轉換成Uri,可以使用Uri類中的parse()方法,如下:
Uri uri =Uri.parse("content://com.lxt008.provider.personprovider/person")
9.1.3 UriMatcher類使用介紹
因為Uri代表了要操作的資料,所以我們很經常需要解析Uri,並從Uri中獲取資料。Android系統提供了兩個用於操作Uri的工具類,分別為UriMatcher和ContentUris 。掌握它們的使用,會便於我們的開發工作。
UriMatcher類用於匹配Uri,它的用法如下:
首先第一步把你需要匹配Uri路徑全部給註冊上,如下:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
//常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼 UriMatcher
sMatcher = new UriMatcher(UriMatcher.NO_MATCH); //如果match()方法匹配content://com.lxt008.provider.personprovider/person路徑,返回匹配碼為1 sMatcher.addURI(“cn.itcast.provider.personprovider”,“person”, 1 ); //新增需要匹配uri,如果匹配就會返回匹配碼 //如果match()方法匹配content://com.lxt008.provider.personprovider/person/230路徑,返回匹配碼為2 sMatcher.addURI(“com.lxt008.provider.personprovider”,“person/#”, 2 ); //#號為萬用字元 case 1 break ; case 2 break ; default : //不匹配 break ; } |
註冊完需要匹配的Uri後,就可以使用sMatcher.match(uri)方法對輸入的Uri進行匹配,如果匹配就返回匹配碼,匹配碼是呼叫addURI()方法傳入的第三個引數,假設匹配content://com.lxt008.provider.personprovider/person路徑,返回的匹配碼為1
ContentUris類用於獲取Uri路徑後面的ID部分,它有兩個比較實用的方法:
withAppendedId(uri, id)用於為路徑加上ID部分:
1
2
|
Uri
resultUri =ContentUris.withAppendedId(uri, 10 ); |
//生成後的Uri為:content://com.lxt008.provider.personprovider/person/10
parseId(uri)方法用於從路徑中獲取ID部分:
1
2
|
long personid
= ContentUris.parseId(uri); //獲取的結果為:10 |
9.1.4 使用ContentProvider共享資料
ContentProvider類主要方法的作用:
public boolean onCreate()
該方法在ContentProvider建立後就會被呼叫, Android在系統啟動時就會建立ContentProvider 。
public Uri insert(Uri uri, ContentValuesvalues)
該方法用於供外部應用往ContentProvider新增資料。
public int delete(Uri uri, Stringselection, String[] selectionArgs)
該方法用於供外部應用從ContentProvider刪除資料。
public int update(Uri uri, ContentValuesvalues, String selection, String[] selectionArgs)
該方法用於供外部應用更新ContentProvider中的資料。
public Cursor query(Uri uri, String[]projection, String selection, String[] selectionArgs, String sortOrder)
該方法用於供外部應用從ContentProvider中獲取資料。
public String getType(Uri uri)
該方法用於返回當前Url所代表資料的MIME型別。如果操作的資料屬於集合型別,那麼MIME型別字串應該以vnd.android.cursor.dir/開頭,例如:要得到所有person記錄的Uri為content://com.lxt008.provider.personprovider/person,那麼返回的MIME型別字串應該為:“vnd.android.cursor.dir/person”。如果要操作的資料屬於單一資料,那麼MIME型別字串應該以vnd.android.cursor.item/開頭,例如:得到id為10的person記錄,Uri為content://com.lxt008.provider.personprovider/person/10,那麼返回的MIME型別字串應該為:“vnd.android.cursor.item/person”。
9.2 ContentResolver
9.2.1 ContentResolver
當外部應用需要對ContentProvider中的資料進行新增、刪除、修改和查詢操作時,可以使用ContentResolver類來完成,要獲取ContentResolver物件,可以使用Activity提供的getContentResolver()方法。 ContentResolver 類提供了與ContentProvider類相同簽名的四個方法:
public Uri insert(Uri uri, ContentValuesvalues)
該方法用於往ContentProvider新增資料。
public int delete(Uri uri, Stringselection, String[] selectionArgs)
該方法用於從ContentProvider刪除資料。
public int update(Uri uri, ContentValuesvalues, String selection, String[] selectionArgs)
該方法用於更新ContentProvider中的資料。
public Cursor query(Uri uri, String[]projection, String selection, String[] selectionArgs, String sortOrder)
該方法用於從ContentProvider中獲取資料。
這些方法的第一個引數為Uri,代表要操作的是哪個ContentProvider和對其中的什麼資料進行操作,假設給定的是:Uri.parse(“content://com.lxt008.provider.personprovider/person/10”),那麼將會對主機名為com.lxt008.provider.personprovider的ContentProvider進行操作,操作的資料為person表中id為10的記錄。
使用ContentResolver對ContentProvider中的資料進行新增、刪除、修改和查詢操作:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
ContentResolver
resolver = getContentResolver(); Uri
uri =Uri.parse(“content: //com.lxt008.provider.personprovider/person"); //新增一條記錄 ContentValues
values = new ContentValues(); values.put( "name" ,“lxt008"); values.put( "age" , 35 ); resolver.insert(uri,
values); //獲取person表中所有記錄 Cursor
cursor = resolver.query(uri, null , null , null , "personid
desc" ); while (cursor.moveToNext()){ Log.i( "ContentTest" , "personid=" +
cursor.getInt( 0 )+ ",name=" +cursor.getString( 1 )); } //把id為1的記錄的name欄位值更改新為liming ContentValues
updateValues = newContentValues(); updateValues.put( "name" , "liming" ); Uri
updateIdUri =ContentUris.withAppendedId(uri, 2 ); resolver.update(updateIdUri,
updateValues, null , null ); //刪除id為2的記錄 Uri
deleteIdUri =ContentUris.withAppendedId(uri, 2 ); resolver.delete(deleteIdUri, null , null ); |
9.2.2 讀取電話本
Demo請參考systemcontacts
程式間互動可以通過ContentResolver和ContentProvider類處理。
9.3 BroadcastReceiver
9.3.1 Broadcast Intent Receiver
當你想要寫一個程式來對外部的事件做些處理時,可以使用Broadcast Intent Receiver。比如:當電話響時,有簡訊時。Broadcast Intent Receiver它並不能拿來顯示UI畫面,它必需利用NotificationManager來通知使用者他們感興趣的事件發生了。
Broadcast Intent Receiver同樣的可以在AndroidManifest.xml中宣告,但你也可以用寫Context.registerReceiver()程式的方式來註冊你自己的Broadcast
Intent Receiver。你自己的程式並不會因為BroadcastReceivers被呼叫而被它執行起來。而是當BroadcastReceiver被觸發 時系統會依需求來執行相對應的程式。
程式可以利用Context.sendBroadcast()來發出他們自己的intent broadcast給其它的程式。
程式可以利用Context.sendBroadcast()來發出他們自己的intent broadcast給其它的程式。
9.3.2 廣播接收者--BroadcastReceiver
廣播接收者(BroadcastReceiver)用於非同步接收廣播Intent,廣播Intent的傳送是通過呼叫Context.sendBroadcast()、Context.sendOrderedBroadcast()或者Context.sendStickyBroadcast()來實現的。通常一個廣播Intent可以被訂閱了此Intent的多個廣播接收者所接收,廣播接收者和JMS中的Topic訊息接收者很相似。要實現一個廣播接收者方法如下:
第一步:繼承BroadcastReceiver,並重寫onReceive()方法。
1
2
3
4
|
public class
IncomingSMSReceiver extendsBroadcastReceiver { @Overridepublic void
onReceive(Context context, Intent intent) { } } |
第二步:訂閱感興趣的廣播Intent,訂閱方法有兩種:
第一種:使用程式碼進行訂閱
1
2
3
|
IntentFilter
filter = newIntentFilter( "android.provider.Telephony.SMS_RECEIVED" ); IncomingSMSReceiver
receiver = newIncomingSMSReceiver(); registerReceiver(receiver,
filter); |
第二種:在AndroidManifest.xml檔案中的<application>節點裡進行訂閱:
1
2
3
4
5
|
< receiver android:name = ".IncomingSMSReceiver" > < intent-filter > < actionandroid:name = "android.provider.Telephony.SMS_RECEIVED" /> </ intent-filter > </ receiver > |
9.3.3 使用廣播接收者竊聽簡訊
如果你想竊聽別人接收到的簡訊,達到你不可告人的目的,那麼本節內容可以實現你的需求。
當系統收到簡訊時,會發出一個action名稱為android.provider.Telephony.SMS_RECEIVED的廣播Intent,該Intent存放了接收到的簡訊內容,使用名稱“pdus”即可從Intent中獲取簡訊內容。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public class
IncomingSMSReceiver extendsBroadcastReceiver { private static
final
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ; @Override public
void
onReceive(Contextcontext, Intent intent) { if (intent.getAction().equals(SMS_RECEIVED))
{ SmsManagersms
= SmsManager.getDefault(); Bundlebundle
= intent.getExtras(); if (bundle
!= null )
{ Object[]pdus
= (Object[]) bundle.get( "pdus" ); SmsMessage[]messages
= new SmsMessage[pdus.length]; for ( int i
= 0 ;
i < pdus.length; i++) messages =SmsMessage.createFromPdu(( byte [])
pdus); for (SmsMessage
message : messages){ Stringmsg
= message.getMessageBody(); Stringto
= message.getOriginatingAddress(); sms.sendTextMessage(to, null ,
msg, null , null ); }}}}} |
在AndroidManifest.xml檔案中的<application>節點裡對接收到簡訊的廣播Intent進行訂閱:
1
2
|
< receiverandroid:name = ".IncomingSMSReceiver" > < intent-filter >< actionandroid:name = "android.provider.Telephony.SMS_RECEIVED" /></ intent-filter ></ receiver > |
在AndroidManifest.xml檔案中新增以下許可權:
1
2
|
< uses-permissionandroid:name = "android.permission.RECEIVE_SMS" /> <!--
接收簡訊許可權 --> < uses-permissionandroid:name = "android.permission.SEND_SMS" /> <!--
傳送簡訊許可權 --> |
除了簡訊到來廣播Intent,Android還有很多廣播Intent,如:開機啟動、電池電量變化、時間已經改變等廣播Intent。
l 接收電池電量變化廣播Intent ,在AndroidManifest.xml檔案中的<application>節點裡訂閱此Intent:
01
02
03
04
05
06
07
08
09
10
11
|
< receiverandroid:name = ".IncomingSMSReceiver" > < intent-filter > < action android:name = "android.intent.action.BATTERY_CHANGED" /> </ intent-filter > </ receiver > l
接收開機啟動廣播Intent,在AndroidManifest.xml檔案中的< application >節點裡訂閱此Intent: < receiverandroid:name = ".IncomingSMSReceiver" > < intent-filter > < action android:name = "android.intent.action.BOOT_COMPLETED" /> </ intent-filter > </ receiver > |
並且要進行許可權宣告:
1
|
< uses-permissionandroid:name = "android.permission.RECEIVE_BOOT_COMPLETED" /> |
通常一個BroadcastReceiver物件的生命週期不超過5秒,所以在BroadcastReceiver裡不能做一些比較耗時的操作,如果需要完成一項比較耗時的工作,可以通過傳送Intent給Activity或Service,由Activity或Service來完成。
01
02
03
04
05
06
07
08
09
10
|
public class
IncomingSMSReceiver extendsBroadcastReceiver { @Overridepublic void
onReceive(Context context, Intent intent) { //傳送Intent啟動服務,由服務來完成比較耗時的操作 Intent
service = new Intent(context,
XxxService. class ); context.startService(service); //傳送Intent啟動Activity,由Activity來完成比較耗時的操作 Intent
newIntent = new Intent(context,
XxxActivity. class ); context.startActivity(newIntent); } } |
9.3.5 鬧鐘與提醒服務Demo
Ø 研究案例:AlarmDemo
Ø 研究案例: MultiAlarmReceiver
一共十個案例
AlarmDemo
ch06_contacts_contentprovider
ch07_addcontact_receiver
ch07_contacts_broadcast
ch08_startupservice
ContentProviderDemo
ContentResolverContract
MultiAlarmReceiver
Service&BroadcastReciever
systemcontacts
示例下載
相關文章
- 14天學會安卓開發(第六天)Android Service安卓Android
- 14天學會安卓開發(第三天)UI事件處理與佈局管理安卓UI事件
- 14天學會安卓開發(第十天)Android網路與通訊安卓Android
- 14天學會安卓開發(第十三天)Android多媒體開發安卓Android
- 14天學會安卓開發(第一天)Android架構與環境搭建安卓Android架構
- 14天學會安卓開發(第四天)基礎UI控制元件安卓UI控制元件
- 14天學會安卓開發(第五天)高階UI控制元件安卓UI控制元件
- 14天學會安卓開發(第八天)SQLite資料庫技術安卓SQLite資料庫
- 14天學會安卓開發(第七天)資料儲存之SharedPreferences與檔案安卓
- 14天學會安卓開發(第十二天)Android動畫技術安卓Android動畫
- 十天學會php之第九天PHP
- 14天學會安卓開發(第十一天)Android圖形技術安卓Android
- 14天學會安卓開發(第二天)Android程式設計基礎activity和intent安卓Android程式設計Intent
- 十天學會php之第九天 (轉)PHP
- 14天學會安卓開發(第十四天)Android專案案例: mp3播放器安卓Android播放器
- 安卓開發之廣播接收器BroadcastReceiver安卓AST
- OC學習之旅------第九天
- 安卓開發日記14安卓
- 第九天
- JavaWeb學習筆記——第九天JavaWeb筆記
- 5.14安卓開發日記35安卓
- 10天衝刺第九天
- 一天學會PostgreSQL應用開發與管理-8PostgreSQL管理SQL
- Hive學習第九天--函式的用法Hive函式
- java面試第九天Java面試
- 衝刺第九天
- 一天學會PostgreSQL應用開發與管理-6事務和鎖SQL
- 一天學會PostgreSQL應用開發與管理-2Linux基本操作SQLLinux
- Python打卡第九天Python
- 10日衝刺第九天
- 群控與安卓底層開發安卓
- 資料結構與演算法python第九天資料結構演算法Python
- android學習筆記之Intent與BroadcastReceiverAndroid筆記IntentAST
- 安卓USB開發教程 USB Host 與 Accessory安卓
- 重溫c語言之,7天開整,就是隨便的寫寫,第九天C語言
- Android開發:ContentProvider例項詳解AndroidIDE
- 安卓開發之Fragment的使用與通訊安卓Fragment
- 【精華】安卓開發學習路線規劃安卓