Android Service 服务(二)—— BroadcastReceiver
一、 BroadcastReceiver簡介
BroadcastReceiver,用于異步接收廣播Intent,廣播Intent是通過調用Context.sendBroadcast()發送、BroadcastReceiver()接收。
廣播Intent的發送是通過調用Context.sendBroadcast()、Context.sendOrderedBroadcast()、Context.sendStickyBroadcast()來實現的。通常一個廣播Intent可以被訂閱了此Intent的多個廣播接收者所接收,廣播接收者和JMS中的Topic消息接收者很相似。
廣播接收器只能接收廣播,對廣播的通知做出反應,很多廣播都產生于系統代碼,如:時區改變的通知、電池電量不足、用戶改變了語言偏好,或者開機啟動等
廣播接收器沒有用戶界面,但是它可以為它們接收到信息啟動一個Activity或者使用NotificationManager來通知用戶.
BroadcastReceiver 接收廣播方式:
1. Normal broadcasts(正常廣播),用 Context.sendBroadcast()發送是完全異步的,它們都運行在一個未定義的順序,通常是在同一時間。這樣會更有效,但意味著receiver不能包含所要使用的結果或中止的API。 ?
2. Ordered broadcasts(有序廣播),用 Context.sendOrderedBroadcast()發送每次被發送到一個receiver。所謂有序,就是每個receiver執行后可以傳播到下一個receiver,也可以完全中止傳播——不傳播給其他receiver。 而receiver運行的順序可以通過matched intent-filter 里面的android:priority來控制,當priority優先級相同的時候,Receiver以任意的順序運行。
二、 BroadcastReceiver注冊方式
AndroidManifest.xml中,application里面,定義receiver并設置要接收的action
<receiver android:name=".receiver.MusicReceiver" > <intent-filter> <action android:name="com.homer.receiver.musicReceiver" /> </intent-filter> </receiver>
2 動態注冊
Activity中,需在onStart()中調用registerReceiver()進行注冊和在onStop中調用unregisterReceiver()釋放服務
private MusicReceiver receiver; @Override protected void onStart(){ super.onStart(); receiver = new MusicReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("com.homer.receiver.musicReceiver"); this.registerReceiver(receiver, filter); } @Override protected void onStop(){ this.unregisterReceiver(receiver); super.onStop(); }
3 兩種注冊方式的比較
靜態注冊方式,由系統來管理receiver,而且程序里的所有receiver,可以在xml里面一目了然
動態注冊方式,隱藏在代碼中,比較難發現;需要特別注意的是,在退出程序前要記得調用Context.unregisterReceiver()方法。一般在activity的onStart()里面進行注冊, onStop()里面進行注銷。官方提醒,如果在Activity.onResume()里面注冊了,就必須在Activity.onPause()注銷。
三、 BroadcastReceiver生命周期
一個BroadcastReceiver 對象只有在被調用onReceive(Context, Intent)的才有效,當從該函數返回后,該對象就無效的了,結束生命周期。
因此從這個特征可以看出,在所調用的onReceive(Context, Intent)函數里,不能有過于耗時的操作,不能使用線程來執行。對于耗時的操作,應該在startService中來完成。因為當得到其他異步操作所返回的結果時,BroadcastReceiver 可能已經無效了。
四、 BroadcastReceiver示例
Activity
public class PlayMusicRecevicer extends Activity implements OnClickListener { private Button playBtn; private Button stopBtn; private Button pauseBtn; private Button exitBtn; private Button closeBtn; private Intent intent; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.music_receiver); playBtn = (Button) findViewById(R.id.play); stopBtn = (Button) findViewById(R.id.stop); pauseBtn = (Button) findViewById(R.id.pause); exitBtn = (Button) findViewById(R.id.exit); closeBtn = (Button) findViewById(R.id.close); playBtn.setOnClickListener(this); stopBtn.setOnClickListener(this); pauseBtn.setOnClickListener(this); exitBtn.setOnClickListener(this); closeBtn.setOnClickListener(this); } @Override public void onClick(View v) { int op = -1; intent = new Intent("com.homer.receiver.musicReceiver"); switch (v.getId()) { case R.id.play: // play music op = 1; break; case R.id.stop: // stop music op = 2; break; case R.id.pause: // pause music op = 3; break; case R.id.close: // close activity this.finish(); break; case R.id.exit: // process by MusicReceiver op = 4; this.finish(); break; } Bundle bundle = new Bundle(); bundle.putInt("op", op); intent.putExtras(bundle); sendBroadcast(intent); // sendBroadcast } // private MusicReceiver receiver; // // @Override // protected void onStart(){ // super.onStart(); // // receiver = new MusicReceiver(); // IntentFilter filter = new IntentFilter(); // filter.addAction("com.homer.receiver.musicReceiver"); // this.registerReceiver(receiver, filter); // } // // @Override // protected void onStop(){ // this.unregisterReceiver(receiver); // // super.onStop(); // } @Override public void onDestroy(){ super.onDestroy(); if(intent != null){ stopService(intent); } } }BroadcastReceiver
public class MusicReceiver extends BroadcastReceiver { // receive Broadcast @Override public void onReceive(Context context, Intent intent) { if(intent != null){ Bundle bundle = intent.getExtras(); Intent it = new Intent(context, MusicReceiverService.class); // call service for MusicReceiverService.class it.putExtras(bundle); if(bundle != null){ int op = bundle.getInt("op"); if(op == 4){ context.stopService(it); // stopService }else{ context.startService(it); // startService } } } } }Service(BroadcastReceiver調用的后臺服務)
public class MusicReceiverService extends Service { private MediaPlayer mediaPlayer; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show(); if (mediaPlayer == null) { mediaPlayer = MediaPlayer.create(this, R.raw.tmp); mediaPlayer.setLooping(false); } } @Override public void onDestroy() { Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT); if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); } } @Override public void onStart(Intent intent, int startId) { if (intent != null) { Bundle bundle = intent.getExtras(); if (bundle != null) { int op = bundle.getInt("op"); switch (op) { case 1: play(); break; case 2: stop(); break; case 3: pause(); break; } } } } public void play() { if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } public void pause() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } public void stop() { if (mediaPlayer != null) { mediaPlayer.stop(); try { mediaPlayer.prepare(); // 在調用stop后如果需要再次通過start進行播放,需要之前調用prepare函數 } catch (IOException ex) { ex.printStackTrace(); } } } }AndroidManifest.xml
<service android:name=".receiver.MusicReceiverService" android:enabled="true" > <intent-filter> <action android:name="com.homer.service.musicReceiverService" /> </intent-filter> </service> <receiver android:name=".receiver.MusicReceiver" > <intent-filter> <action android:name="com.homer.receiver.musicReceiver" /> </intent-filter> </receiver>
五、代碼解析
1、Activity中,PlayMusicService中通過重寫OnClickListener 接口onClick()方法實現對播放音樂的控制,把音樂各種操作用數字通過Intent傳遞給service
然后通過構造一個Intent , intent = new Intent("com.homer.receiver.musicReceiver");?
其中,com.homer.receiver.musicReceiver是?AndroidManifest.xml 對receiver的定義(或動態注冊addAction為filter.addAction("com.homer.receiver.musicReceiver");)
2、Activity中,音樂播放的控制,利用Bundle綁定數字op后,通過?sendBroadcast(intent);?廣播出去Bundle bundle = new Bundle();
bundle.putInt("op", op);
intent.putExtras(bundle);
startService(intent);
3、 BroadcastReceiver中,會處理Activity啟動的?sendBroadcast(intent); 廣播,通過實現onReceive()方法,解析Activity中Intent的Bundle數據。
然后通過Intent it = new Intent(context, MusicReceiverService.class); 初始化一個啟動Service服務的Intent
最后根據解析bundle的op數值決定啟動context.startService(it); 服務 或 關閉context.stopService(it);?服務
4、Service中,處理BroadcastReceiver廣播啟動的MusicReceiverService服務,即依次調用service的啟動過程:onCreate --> onStart(可多次調用) --> onDestroy
onCreate(), ?創建mediaPlayer
onStart(), ? ? ?通過獲取Bundle bundle = intent.getExtras();,提取int op = bundle.getInt("op");,然后執行響應的音樂播放操作
onDestroy(),停止并釋放mediaPlayer音樂資源,如果當執行context.stopService()時調用此方法
5、Activity中,onClick()函數中close與exit是執行含義是不同的:
close : 只是執行了this.finish(); 關閉了本Activity窗體,service并沒有被關掉,音樂依然會繼續在后臺播放
exit ?: 先調用了stopService(intent); 關閉了service服務,在Service中會調用3中的onDestroy()停止并釋放音樂資源,后才執行this.finish(); 關閉了本Activity窗體
六、BroadcastReceiver總結
BroadcastReceiver需要先注冊receriver(靜態或動態)—> 發送廣播sendBroadcast(intent)?—>?處理廣播onReceive(Context context, Intent intent)?—> 啟動服務startService(it)?—> 關閉服務stopService(it)?
其中,receriver兩種注冊方式,靜態注冊在AndroidManifest.xml中的receiver和動態注冊在PlayMusicRecevicer注釋的代碼部分,兩者選擇一種即可
代碼下載
參考推薦:
Android Service生命周期及用法
Android之BroadcastReceiver的使用(靜態和動態兩種注冊方式)
轉載于:https://www.cnblogs.com/springmvc-hibernate/archive/2012/03/17/2484016.html
總結
以上是生活随笔為你收集整理的Android Service 服务(二)—— BroadcastReceiver的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于Asp.net页面的刷新
- 下一篇: OpenDataSource,sql开放