<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 第九天.ContentProvider與BroadcastReceiver ## ### 9.1 ContentProvider ### #### 9.1.1 使用ContentProvider共享數據 #### 當應用繼承ContentProvider類,并重寫該類用于提供數據和存儲數據的方法,就可以向其他應用共享其數據。雖然使用其他方法也可以對外共享數據,但數據訪問方式會因數據存儲的方式而不同,如:采用文件方式對外共享數據,需要進行文件操作讀寫數據;采用sharedpreferences共享數據,需要使用sharedpreferences API讀寫數據。而使用ContentProvider共享數據的好處是統一了數據訪問方式。 當應用需要通過ContentProvider對外共享數據時,第一步需要繼承ContentProvider并重寫下面方法: ``` 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 就是他的域名: ``` <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由以下幾部分組成: ![](https://box.kancloud.cn/2016-05-21_573fc32a926e6.png) ``` 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路徑全部給注冊上,如下: ``` //常量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);//#號為通配符 switch (sMatcher.match(Uri.parse("content://com.lxt008.provider.personprovider/person/10"))){ 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部分: ``` Uri uri =Uri.parse("content://com.lxt008.provider.personprovider/person") Uri resultUri =ContentUris.withAppendedId(uri, 10); //生成后的Uri為:content://com.lxt008.provider.personprovider/person/10 ``` parseId(uri)方法用于從路徑中獲取ID部分: ``` Uri uri = Uri.parse("content://com.lxt008.provider.personprovider/person/10") 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中的數據進行添加、刪除、修改和查詢操作: ``` 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給其它的程序。 #### 9.3.2 廣播接收者--BroadcastReceiver #### 廣播接收者(BroadcastReceiver)用于異步接收廣播Intent,廣播Intent的發送是通過調用Context.sendBroadcast()、Context.sendOrderedBroadcast()或者Context.sendStickyBroadcast()來實現的。通常一個廣播Intent可以被訂閱了此Intent的多個廣播接收者所接收,廣播接收者和JMS中的Topic消息接收者很相似。要實現一個廣播接收者方法如下: 第一步:繼承BroadcastReceiver,并重寫onReceive()方法。 ``` public class IncomingSMSReceiver extendsBroadcastReceiver { @Overridepublic void onReceive(Context context, Intent intent) { } } ``` 第二步:訂閱感興趣的廣播Intent,訂閱方法有兩種: 第一種:使用代碼進行訂閱 ``` IntentFilter filter = newIntentFilter("android.provider.Telephony.SMS_RECEIVED"); IncomingSMSReceiver receiver = newIncomingSMSReceiver(); registerReceiver(receiver, filter); ``` 第二種:在AndroidManifest.xml文件中的<application>節點里進行訂閱: ``` <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中獲取短信內容。 ``` 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進行訂閱: ``` <receiverandroid:name=".IncomingSMSReceiver"> <intent-filter><actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver> ``` 在AndroidManifest.xml文件中添加以下權限: ``` <uses-permissionandroid:name="android.permission.RECEIVE_SMS"/><!-- 接收短信權限 --> <uses-permissionandroid:name="android.permission.SEND_SMS"/><!-- 發送短信權限 --> ``` #### 9.3.4 廣播接收者 #### 除了短信到來廣播Intent,Android還有很多廣播Intent,如:開機啟動、電池電量變化、時間已經改變等廣播Intent。 + 接收電池電量變化廣播Intent ,在AndroidManifest.xml文件中的<application>節點里訂閱此Intent: ``` <receiverandroid:name=".IncomingSMSReceiver"> <intent-filter> <action android:name="android.intent.action.BATTERY_CHANGED"/> </intent-filter> </receiver> ``` + 接收開機啟動廣播Intent,在AndroidManifest.xml文件中的<application>節點里訂閱此Intent: ``` <receiverandroid:name=".IncomingSMSReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> ``` 并且要進行權限聲明: ``` <uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/> ``` 通常一個BroadcastReceiver對象的生命周期不超過5秒,所以在BroadcastReceiver里不能做一些比較耗時的操作,如果需要完成一項比較耗時的工作,可以通過發送Intent給Activity或Service,由Activity或Service來完成。 ``` 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 [示例下載](http://www.apkbus.com/android-83449-1-1.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看