Intent和BroadcastReceiver
Intent簡介
Intent是一種消息傳遞機制,作用:
- 使用類名顯示啟動一個特定的Service或Activity
- 啟動Activity或Service來執行一個Intent
- 廣播某個事件已經發生
使用Intent啟動Activity
顯式啟動Activity
Intent intent = new Intent(MyActivity.this, MyOtherActivity.class);
startActivity(intent);
調用新Activity的finish或按下返回按鈕將關閉該Activity,並出棧。
隱式的Intent和運行時綁定
隱式調用,就是讓匿名的應用程序組件響應動作請求。如撥打電話:
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:xxxx"));
startActivity(intent);
隱式調用需要一個執行的動作,也可提供執行動作需要的數據URI。還可以通過向Intent添加extra來向目標Activity發送數據。
確定Intent能否解析
有的時候需要判斷intent能否解析:
PackageManager pm = getPackageManager();
ComponentName cn = intent.resolveActivity(pm);
從Activity返回結果
調用startActivityForResult,回調為onActivity。如選取聯系人:
Uri uri = Uri.parse("content://contacts/people");
Intent intent = new Intent(Intent.ACTION_PICK,uri);
startActivityForResult(intent,REQUEST_CODE);
然後請求完成後:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //處理返回的結果 }
Android 原生Action
- ACTION_ALL_APPS 打開一個列出所有已安裝應用程序的Activity
- ACTION_ANSWER 打開一個處理來電的Activity
- ACTION_BUG_REPORT 顯示一個可以報告bug的Activity
- ACTION_CALL 打開一個電話撥號程序
- ACTION_CALL_BUTTON 用戶按下撥打按鈕觸發,調用撥號Activity
- ACTION_DELETE 啟動一個Activity,允許刪除Intent數據URI中指定的數據
- ACTION_DIAL 打開一個撥號程序
- ACTION_EDIT 請求一個Activity,要求該Activity可以編輯Intent的數據URI中的數據
- ACTION_INSERT 打開一個能夠在Intent的數據URI指定的遊標處插入新項的Activity
- ACTION_PICK 啟動一個子Activity,可以從Intent的數據URI指定的Content Provider中選擇
- ACTION_SEARCH 通常用於啟動特定的搜索Activity
- ACTION_SEARCH_LONG_PRESS 允許截獲對硬件搜索鍵的長按操作
- ACTION_SENDTO 啟動一個Activity來向Intent的數據URI所指定的聯系人發送消息
- ACTION_SEND 啟動一個Activity,該Activity會發送Intent中指定的數據
- ACTION_VIEW 視圖要求以最合理的方式查看Intent的數據URI中提供的數據
- ACTION_WEB_SEARCH 打開一個瀏覽器,進行搜索
使用Intent廣播事件
Intent可以在進程之間發送結構化的消息,可以通過實現Broadcast Receiver來監聽和響應應用程序內的Broadcast Intent。
廣播Intent:
Intent intent = new Intent();
intent.putExtra(key, value);
sendBroadcast(intent);
處理廣播Intent:
private class MyBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//處理事件
}
}
註冊廣播兩種方式:
代碼中註冊
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(action);
//註冊
registerReceiver(receiver,intentFilter);
//取消註冊
unregisterReceiver(receiver);
Manifest註冊
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
</intent-filter>
</receiver>
這種方式Receiver總是活動的,並且一直可以接受廣播事件。
廣播有序的Intent
sendOrderdBroadcast可以按照優先級順序發送廣播事件。
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
android:priority = "100">
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
</intent-filter>
</receiver>
廣播Sticky Intent
Sticky Intent可以保存它們最後一個廣播的值,一旦有新的接收器被註冊為接收該廣播時,它們會把這些值作為Intent返回。使用sendStickyBroadcast廣播,刪除使用removeStickyBroadcast。
Pending Intent
Pending Intent用於包裝在響應將來的事件時觸發的Intent。
Intent intent = new Intent(this,MyOtherActivity.class);
PendingIntent.getActivity(this,requestCode,intent,flags);
Intent intent = new Intent(this,MyService.class);
PendingIntent.getService(this,requestCode,intent,flags);
Intent intent = new Intent();
PendingIntent.getBroadcast(this,requestCode,intent,flags);
創建Intent Filter
使用Intent Filter為隱式Intent提供服務
Intent Filter標簽:
- action 服務的動作標簽,唯一字串
- category 指定提供服務的情況
- ALTERNATIVE 在特定數據類型上執行的默認動作的可選項
- SELECTED_ALTERNATIVE 與ALTERNATIVE類似,但是要求可以有多種可能性
- BROWSABLE 指定瀏覽器內部可用的動作
- DEFAULT 默認動作
- HOME 作為本地屏幕的可選項
- data data標簽允許指定組件可以執行的數據類型:
- android:host 指定一個有效的主機名
- android:mimetype 指定組件可以執行的數據類型
- android:path 指定URI的有效路徑
- android:port 指定主機的有效端口
- android:scheme 要求一種特定的模式(如http)
Android解析Intent Filter
- Android將安裝包的可用Filter放到一個列表中
- 從列表中移除在解析Intent時相關聯的動作或者類別不匹配的Intent Filter
- Intent的數據URI的每一個部分都和Intent Filter的data標簽進行比較
監聽本地Broadcast Intent
可以監聽系統事件,然後進行自己程序的相應動作,經常使用的系統事件:
- ACTION_BOOT_COMPLETED 系統完成啟動後,會觸發這個動作
- ACTION_CAMERA_BUTTON 當單擊拍照按鍵時觸發
- ACTION_DATE_CHANGED 和ACTION_TIME_CHANGED 日期和時間被手動修改,或觸發
- ACTION_MEDIA_EJECT 用戶彈出外部存儲,會觸發,如果正在操作外部存儲,記得保存和關閉文件句柄
- ACTION_MEDIA_MOUNTED和ACTION_MEDIA_UNMOUNTED 新的外部存儲成功添加或者移除,會觸發
- ACTION_NEW_OUTGOING_CALL 向外撥打電話就會觸發
- ACTION_SCREEN_OFF和ACTION_SCREEN_ON 屏幕關閉或者打開時觸發
- ACTION_TIMEZONE_CHANGED 時區改變會觸發
有的時候需要在運行時管理Manifest Receiver
使用PackageManager.setComponentEnabledSetting(ReceiverName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP)
啟用一個Receiver
使用PackageManager.setComponentEnabledSetting(ReceiverName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP)
禁用一個Receiver
Intent和BroadcastReceiver