Android Service 服務(二)—— BroadcastReceiver

來源:互聯網
上載者:User

一、 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註冊方式

1 靜態註冊
AndroidManifest.xml中,application裡面,定義receiver並設定要接收的action
<receiver android:name=".receiver.MusicReceiver" ><br /> <intent-filter><br /> <action android:name="com.homer.receiver.musicReceiver" /><br /> </intent-filter><br /> </receiver>
2 動態註冊
Activity中,需在onStart()中調用registerReceiver()進行註冊和在onStop中調用unregisterReceiver()釋放服務
private MusicReceiver receiver;</p><p>@Override<br />protected void onStart(){<br />super.onStart();</p><p>receiver = new MusicReceiver();<br />IntentFilter filter = new IntentFilter();<br />filter.addAction("com.homer.receiver.musicReceiver");<br />this.registerReceiver(receiver, filter);<br />}</p><p>@Override<br />protected void onStop(){<br />this.unregisterReceiver(receiver);</p><p>super.onStop();<br />}
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 {</p><p>private Button playBtn;<br />private Button stopBtn;<br />private Button pauseBtn;<br />private Button exitBtn;<br />private Button closeBtn;</p><p>private Intent intent;</p><p>@Override<br />public void onCreate(Bundle savedInstanceState) {<br />super.onCreate(savedInstanceState);<br />setContentView(R.layout.music_receiver);</p><p>playBtn = (Button) findViewById(R.id.play);<br />stopBtn = (Button) findViewById(R.id.stop);<br />pauseBtn = (Button) findViewById(R.id.pause);<br />exitBtn = (Button) findViewById(R.id.exit);<br />closeBtn = (Button) findViewById(R.id.close);</p><p>playBtn.setOnClickListener(this);<br />stopBtn.setOnClickListener(this);<br />pauseBtn.setOnClickListener(this);<br />exitBtn.setOnClickListener(this);<br />closeBtn.setOnClickListener(this);</p><p>}</p><p>@Override<br />public void onClick(View v) {<br />int op = -1;<br /> intent = new Intent("com.homer.receiver.musicReceiver");</p><p>switch (v.getId()) {<br />case R.id.play:// play music<br />op = 1;<br />break;<br />case R.id.stop:// stop music<br />op = 2;<br />break;<br />case R.id.pause:// pause music<br />op = 3;<br />break;<br />case R.id.close:// close activity<br />this.finish();<br />break;<br />case R.id.exit:// process by MusicReceiver<br />op = 4;<br />this.finish();<br />break;<br />}</p><p>Bundle bundle = new Bundle();<br />bundle.putInt("op", op);<br />intent.putExtras(bundle);</p><p> sendBroadcast(intent);// sendBroadcast<br />}</p><p>//private MusicReceiver receiver;<br />//<br />//@Override<br />//protected void onStart(){<br />//super.onStart();<br />//<br />//receiver = new MusicReceiver();<br />//IntentFilter filter = new IntentFilter();<br />//filter.addAction("com.homer.receiver.musicReceiver");<br />//this.registerReceiver(receiver, filter);<br />//}<br />//<br />//@Override<br />//protected void onStop(){<br />//this.unregisterReceiver(receiver);<br />//<br />//super.onStop();<br />//}</p><p>@Override<br />public void onDestroy(){<br />super.onDestroy();</p><p>if(intent != null){<br />stopService(intent);<br />}<br />}<br />}

BroadcastReceiver

public class MusicReceiver extends BroadcastReceiver {// receive Broadcast</p><p>@Override<br />public void onReceive(Context context, Intent intent) {</p><p>if(intent != null){<br />Bundle bundle = intent.getExtras();<br />Intent it = new Intent(context, MusicReceiverService.class);// call service for MusicReceiverService.class<br />it.putExtras(bundle);<br />if(bundle != null){<br />int op = bundle.getInt("op");<br />if(op == 4){<br />context.stopService(it);// stopService<br />}else{<br />context.startService(it);// startService<br />}<br />}<br />}<br />}<br />}

Service(BroadcastReceiver調用的後台服務)

public class MusicReceiverService extends Service {</p><p>private MediaPlayer mediaPlayer;</p><p>@Override<br />public IBinder onBind(Intent arg0) {<br />return null;<br />}</p><p>@Override<br />public void onCreate() {<br />Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show();</p><p>if (mediaPlayer == null) {<br />mediaPlayer = MediaPlayer.create(this, R.raw.tmp);<br />mediaPlayer.setLooping(false);<br />}<br />}</p><p>@Override<br />public void onDestroy() {<br />Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);<br />if (mediaPlayer != null) {<br />mediaPlayer.stop();<br />mediaPlayer.release();<br />}<br />}</p><p>@Override<br />public void onStart(Intent intent, int startId) {<br />if (intent != null) {<br />Bundle bundle = intent.getExtras();<br />if (bundle != null) {<br />int op = bundle.getInt("op");<br />switch (op) {<br />case 1:<br />play();<br />break;<br />case 2:<br />stop();<br />break;<br />case 3:<br />pause();<br />break;<br />}<br />}<br />}<br />}</p><p>public void play() {<br />if (!mediaPlayer.isPlaying()) {<br />mediaPlayer.start();<br />}<br />}</p><p>public void pause() {<br />if (mediaPlayer != null && mediaPlayer.isPlaying()) {<br />mediaPlayer.pause();<br />}<br />}</p><p>public void stop() {<br />if (mediaPlayer != null) {<br />mediaPlayer.stop();<br />try {<br />mediaPlayer.prepare();// 在調用stop後如果需要再次通過start進行播放,需要之前調用prepare函數<br />} catch (IOException ex) {<br />ex.printStackTrace();<br />}<br />}<br />}<br />}

AndroidManifest.xml

<service<br /> android:name=".receiver.MusicReceiverService"<br /> android:enabled="true" ><br /> <intent-filter><br /> <action android:name="com.homer.service.musicReceiverService" /><br /> </intent-filter><br /> </service><br /> <receiver android:name=".receiver.MusicReceiver" ><br /> <intent-filter><br /> <action android:name="com.homer.receiver.musicReceiver" /><br /> </intent-filter><br /> </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的使用(靜態和動態兩種註冊方式)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.