2、廣播事件監聽的兩種方法android
使用廣播進行事件監聽有兩種方法,靜態註冊和動態註冊,又或者稱冷插拔和熱插拔。靜態註冊就是將廣播接收器的相關信息寫在應用的配置文件中。當有廣播事件發生時,組件管理服務就會從安裝包管理服務中獲取已安裝應用的廣播組件信息。動態註冊則是經過Context.registerReceiver和Context.unregisterRecever,動態將廣播接收器與所須要監聽的事件綁定。web
<receiver android:name=".ColdReceiver"><!-- 你的Receiver名稱 --> <intent-filter> <action android:name="android.intent.action.COLD_BROADCAST"/> <!-- 你廣播要接受的intent名稱 --> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
而後咱們建一個ColdReceiver的類,繼承BroadcastReceiver,裏面代碼以下
安全
public class ColdReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //跳轉到service中 intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(1); //開啓service context.startService(intent); //日誌打印 Log.d("TEST","靜態註冊"); } }
上面的Service啓動看到了嗎,這裏我用了上次說過的快捷跳轉。其中service的配置和內容以下
網絡
<service android:name=".BroadcastService"><!-- 你自定義的service文件 (在<application></application>裏面加)--> <intent-filter> <action android:name="android.intent.action.BroadcastService" /><!-- 用intent啓動時的快捷名(也能夠用常規的方式啓動) --> <category android:name="android.intent.category.default" /> </intent-filter> </service>
1 public class BroadcastService extends Service{ 2 3 @Override 4 public IBinder onBind(Intent intent) { 5 // TODO Auto-generated method stub 6 return null; 7 } 8 9 @Override 10 public void onCreate() { 11 //開啓服務時會首先調用該方法 12 super.onCreate(); 13 } 14 15 @Override 16 public int onStartCommand(Intent intent, int flags, int startId) { 17 //根據每次intent傳過來的信息進行判斷來顯示不一樣信息 18 switch(intent.getFlags()){ 19 case 1:{ 20 Toast.makeText(getApplicationContext(), "靜態註冊", Toast.LENGTH_SHORT).show(); 21 break; 22 } 23 case 2:{ 24 Toast.makeText(getApplicationContext(), "動態註冊", Toast.LENGTH_SHORT).show(); 25 break; 26 } 27 case 3:{ 28 Toast.makeText(getApplicationContext(), "普通廣播", Toast.LENGTH_SHORT).show(); 29 break; 30 } 31 case 4:{ 32 Toast.makeText(getApplicationContext(), "有序廣播", Toast.LENGTH_SHORT).show(); 33 break; 34 } 35 } 36 return START_STICKY; 37 } 38 39 @Override 40 public void onDestroy() { 41 // 中止service後會調用此方法 42 Log.d("TEST", "destroy"); 43 super.onDestroy(); 44 } 45 46 }
那麼靜態廣播的建立就完成了,簡單吧,就兩個步驟,一是配置廣播,二是繼承BroadcastReceiver,重寫裏面的onReceive函數。
接下來咱們在新建一個工程來檢測廣播是否能夠響應消息。(檢測應用的代碼所有都在下方,而且不用再作更改了)
app
1 public class MainActivity extends Activity implements OnClickListener{ 2 3 private Button b1,b2,b3,b4; 4 private Intent intent; 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 intent = new Intent(); 10 //得到界面的控件 11 b1 = (Button) findViewById(R.id.button1); 12 b1.setOnClickListener(this); 13 b2 = (Button) findViewById(R.id.button2); 14 b2.setOnClickListener(this); 15 b3 = (Button) findViewById(R.id.button3); 16 b3.setOnClickListener(this); 17 b4 = (Button) findViewById(R.id.button4); 18 b4.setOnClickListener(this); 19 Log.d("TEST","===初始化完成==="); 20 } 21 22 @Override 23 public void onClick(View v) { 24 // TODO Auto-generated method stub 25 switch(v.getId()){ 26 case R.id.button1:{//發送到靜態註冊廣播 27 intent = new Intent("android.intent.action.COLD_BROADCAST"); 28 sendBroadcast(intent); 29 //intent.putExtra("msg", "hello coldreceiver."); 30 break; 31 } 32 case R.id.button2:{//發送到動態註冊廣播 33 intent = new Intent("android.intent.action.HOT_BROADCAST"); 34 //intent.putExtra("msg", "hello hotreceiver."); 35 sendBroadcast(intent); 36 break; 37 } 38 case R.id.button3:{//普通廣播 39 intent = new Intent("android.intent.action.NORMAL_BROADCAST"); 40 sendBroadcast(intent); 41 break; 42 } 43 case R.id.button4:{//有序廣播 44 intent = new Intent("android.intent.action.SORT_BROADCAST"); 45 sendOrderedBroadcast(intent, "scott.permission.SORT_BROADCAST_PERMISSION"); 46 break; 47 } 48 } 49 } 50 51 public void show(String str){ 52 Toast.makeText(this, str, Toast.LENGTH_LONG).show(); 53 } 54 55 @Override 56 protected void onDestroy() { 57 // TODO Auto-generated method stub 58 super.onDestroy(); 59 } 60 }
ok,將兩個應用都安裝到設備上,啓動測試用的應用,點擊第一個按鈕,運行的效果以下
同時,會出現"靜態註冊"的Toast(不方便截圖)。能夠看出靜態註冊廣播可以跨應用來響應信息,這都要歸功於安卓上的組件管理服務,它會讀取每一個應用的配置文件,而後獲取裏面的組件信息,每當有消息響應時,組件管理服務會從中查找有沒有須要調用的組件,並判斷是否進行執行異步
public class HotReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //String msg = intent.getStringExtra("msg"); intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(2); context.startService(intent); Log.d("TEST","動態註冊"); } }
在Activity中進行動態註冊
ide
public class MainActivity extends Activity { private HotReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //動態註冊廣播 //新建一個廣播對象 receiver = new HotReceiver(); //新建一個intent管理機制,(功能是對組件進行過濾,只獲取須要的消息) IntentFilter filter = new IntentFilter(); //添加白名單(只獲取該動做的信息) filter.addAction("android.intent.action.HOT_BROADCAST"); //與廣播綁定,進行註冊 registerReceiver(receiver, filter); } @Override protected void onDestroy() { //取消註冊,必定要記得,否則系統會報錯誤 unregisterReceiver(receiver); stopService(new Intent("android.intent.action.BroadcastService")); super.onDestroy(); } }
ok,再使用測試應用來檢查一下效果,注意步驟,安裝好廣播應用打開,不要讓它退出,切換到測試用的廣播,點擊第二個按鈕。
函數
測試成功。那麼咱們關掉廣播應用在測試一下,會發現不會再出現動態註冊的打印消息。這說明動態註冊的廣播是與Activity綁定的,當Activity銷燬時,廣播也會被銷燬。
在Android中,不少時候最好是使用動態註冊的方式使用廣播,好比時間變化事件,電量變動事件等,這些事件觸發率過高,若是使用靜態註冊,會致使進程頻繁的被構造和銷燬從而影響整個系統的效率。測試
3、廣播的兩種類型this
public class NormalReceiver1 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(3); context.startService(intent); Log.d("TEST","普通廣播1"); abortBroadcast(); } }
public class NormalReceiver2 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(3); context.startService(intent); Log.d("TEST","普通廣播2"); abortBroadcast(); } }
public class NormalReceiver3 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(3); context.startService(intent); Log.d("TEST","普通廣播3"); abortBroadcast(); } }
<receiver android:name=".NormalReceiver1"> <intent-filter> <action android:name="android.intent.action.NORMAL_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name=".NormalReceiver2"> <intent-filter> <action android:name="android.intent.action.NORMAL_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name=".NormalReceiver3"> <intent-filter> <action android:name="android.intent.action.NORMAL_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
安裝完畢後,咱們點擊檢測應用的第三個按鈕,能夠看到
public class SortReceiver1 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub //String msg = intent.getStringExtra("msg"); intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(4); context.startService(intent); Log.d("TEST","有序廣播1"); abortBroadcast(); } }
public class SortReceiver2 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub //String msg = intent.getStringExtra("msg"); intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(4); context.startService(intent); Log.d("TEST","有序廣播2"); } }
public class SortReceiver3 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub //String msg = intent.getStringExtra("msg"); intent = new Intent("android.intent.action.BroadcastService"); intent.addFlags(4); context.startService(intent); Log.d("TEST","有序廣播3"); } }
<receiver android:name=".SortReceiver1"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.SORT_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name=".SortReceiver2"> <intent-filter android:priority="999"> <action android:name="android.intent.action.SORT_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name=".SortReceiver3"> <intent-filter android:priority="998"> <action android:name="android.intent.action.SORT_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
咱們看到,如今這三個接收者的<intent-filter>多了一個android:priority屬性,而且依次減少。這個屬性的範圍在-1000到1000,數值越大,優先級越高。
一樣發送廣播的代碼也是不同的
sendOrderedBroadcast(intent, "scott.permission.SORT_BROADCAST_PERMISSION");
注意,使用sendOrderedBroadcast方法發送有序廣播時,須要一個權限參數,若是爲null則表示不要求接收者聲明指定的權限,若是不爲 null,則表示接收者若要接收此廣播,需聲明指定權限。這樣作是從安全角度考慮的,例如系統的短信就是有序廣播的形式,一個應用多是具備攔截垃圾短信 的功能,當短信到來時它能夠先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權限。
因此咱們在AndroidMainfest.xml中定義一個權限,並得到權限:(是要在廣播的應用中聲明)
<permission android:protectionLevel="normal" android:name="scott.permission.SORT_BROADCAST_PERMISSION" /> <uses-permission android:name="scott.permission.SORT_BROADCAST_PERMISSION" />
(這裏不是寫在application內部,而是同application同級)
運行後只會出現這麼一個消息:
由於在第一個廣播出咱們就終止了廣播的繼續傳遞,因此就只會出現這麼一條打印消息。
4、形形色色的廣播
在android中有不少系統自帶的intent.action,經過監聽這些事件咱們能夠完成不少功能。