Android IPC機(jī)制綁定Service實(shí)現(xiàn)本地通信
**寫(xiě)作原因:跨進(jìn)程通信的實(shí)現(xiàn)和理解是Android進(jìn)階中重要的一環(huán)。下面博主分享IPC一些相關(guān)知識(shí)、操作及自己在學(xué)習(xí)IPC過(guò)程中的一些理解。
這一章是為下面的Messenger和AIDL的使用做準(zhǔn)備,主要講解Android Service的綁定和Activity與本地Service之間通信相關(guān)知識(shí)。**
簡(jiǎn)介
我們都知道啟動(dòng)Service有兩種方式:startService()和bindService()。相比第一種方式,bindService()能夠更加靈活地實(shí)現(xiàn)與啟動(dòng)端Activity的數(shù)據(jù)通信,第一種啟動(dòng)方式啟動(dòng)Activity與Service之間并沒(méi)有直接關(guān)聯(lián),難以直接實(shí)現(xiàn)通信(當(dāng)然了,使用BroadCast或者事件總線也是可以實(shí)現(xiàn)的)。而使用綁定的方式啟動(dòng)Service則可以實(shí)現(xiàn)Service之間的通信。
下面就講述一下綁定Service實(shí)現(xiàn)本地通信的流程。
實(shí)例
結(jié)合圖片我們來(lái)模擬開(kāi)啟一個(gè)后臺(tái)執(zhí)行更新功能為例來(lái)講解本地Service的綁定。
先分析一下該需求的場(chǎng)景:首先我們需要點(diǎn)擊Start按鈕開(kāi)啟后臺(tái)更新數(shù)據(jù),后臺(tái)將數(shù)據(jù)返回給Activity并在ProgressBar展示進(jìn)度;當(dāng)我們點(diǎn)擊Pause時(shí)后臺(tái)暫停更新;點(diǎn)擊Stop按鈕時(shí)關(guān)閉后臺(tái)。本例中也用到Service通過(guò)BroadCast向Activity傳遞數(shù)據(jù)。由于只是實(shí)例,對(duì)于線程操作一塊有一些bug,希望大家能夠幫忙指正。
Activity的布局如下:
Service 實(shí)現(xiàn):
先看看Service的實(shí)現(xiàn):
思路是這樣的:先繼承Binder類(lèi)創(chuàng)建MyBinder類(lèi),把MyBinder看做Service與Activity通信的代理人,所以在MyBinder內(nèi)部中寫(xiě)好方法間接調(diào)用Service中的方法以供Activity去調(diào)用(如本例中callPauseUpgrade())。關(guān)于IBinder對(duì)象的獲取除了直接重寫(xiě)后面還有兩種方式,這里先不闡述了。在Service中我們開(kāi)啟一個(gè)Thread,在這個(gè)Thread中模擬持續(xù)更新進(jìn)度條直到isStop為False或者progress大于等于100時(shí),然后將進(jìn)度廣播出去,讓Activity接收到廣播進(jìn)行進(jìn)度條更新。Service中供Activity調(diào)用的方法實(shí)現(xiàn)暫停和停止Thread的功能,具體過(guò)程參照代碼。
public class UpgradeService extends Service { private Thread thread; private Intent intent; private int progress; private Boolean isStop; public class MyBinder extends Binder{ public void callPauseUpgrade(){ pauseUpgrade(); } public void callStopUpgrade() { stopUpgrade(); } } private void stopUpgrade() { progress = 0; isStop = false; intent.putExtra("progress",progress); sendBroadcast(intent); } @Override public void onCreate() { super.onCreate(); progress = 0; isStop = true; intent = new Intent(); thread = new Thread(new Runnable() { @Override public void run() { while(isStop){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } progress = progress +5; intent.putExtra("progress",progress); intent.setAction("UPGRADE_ACTION"); sendBroadcast(intent); if(progress>=100) break; } } }); thread.start(); } private void pauseUpgrade() { //TODO:Pause the upgrade Toast.makeText(getApplicationContext(),"暫停",Toast.LENGTH_SHORT).show(); isStop = false; } @Override public IBinder onBind(Intent intent) { return new MyBinder(); } }
Activity實(shí)現(xiàn)
下面是在客戶端實(shí)現(xiàn)與Service的通信代碼。主要思路是:先注冊(cè)廣播實(shí)現(xiàn)Service數(shù)據(jù)的返回;單擊Start按鈕時(shí)實(shí)現(xiàn)與Service的綁定,創(chuàng)建ServiceConnection對(duì)象實(shí)現(xiàn)ServiceConnection接口,分別回調(diào)綁定成功和失敗兩種情況下的邏輯。當(dāng)成功時(shí)獲取MyBinder對(duì)象,并將設(shè)置的isBound值設(shè)為true;當(dāng)失敗時(shí)將isBound設(shè)置為false。單擊Pause調(diào)用MyBinder對(duì)象的callPauseUpgrade()方法間接調(diào)用Service中的pauseUpgrade()方法。單擊Stop調(diào)用callStopUpgrade()方法并且解除綁定。注意解除綁定事件只能執(zhí)行一次,否則程序會(huì)崩潰。
具體實(shí)現(xiàn)并不難,主要是認(rèn)真理解上面的流程圖即可。
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button mBtStart; private Button mBtStop; private Button mBtPause; private ProgressBar mPbProgress; private UpgradeService.MyBinder myBinder; private boolean isBound; private UpgradeReceiver upgradeReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("UPGRADE_ACTION"); upgradeReceiver = new UpgradeReceiver(); registerReceiver(upgradeReceiver,intentFilter); initView(); initEvent(); } public class UpgradeReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { mPbProgress.setProgress(intent.getIntExtra("progress",0)); } } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(upgradeReceiver); } private void initEvent() { mBtPause.setOnClickListener(this); mBtStart.setOnClickListener(this); mBtStop.setOnClickListener(this); } private void initView() { mBtPause = (Button) findViewById(R.id.bt_pause); mBtStart = (Button) findViewById(R.id.bt_start); mBtStop = (Button) findViewById(R.id.bt_stop); mPbProgress = (ProgressBar) findViewById(R.id.pb_progress); } @Override public void onClick(View v) { switch(v.getId()){ case R.id.bt_pause: if(isBound&&myBinder!=null){ myBinder.callPauseUpgrade(); } break; case R.id.bt_start: bindService(new Intent(MainActivity.this,UpgradeService.class),conn,BIND_AUTO_CREATE); break; case R.id.bt_stop: if(isBound) { myBinder.callStopUpgrade(); unbindService(conn); isBound = false; } break; } } private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if(service != null){ myBinder = (UpgradeService.MyBinder) service; isBound = true; } } @Override public void onServiceDisconnected(ComponentName name) { isBound = false; } }; }
總結(jié):
這篇文章是為下面的Messenger和AIDL跨進(jìn)程通信做準(zhǔn)備的,實(shí)際上個(gè)人感覺(jué)真正開(kāi)發(fā)時(shí)可以使用EventBus或者RxJava取代這種同進(jìn)程各個(gè)組件通信的問(wèn)題,有興趣的讀者可以自行嘗試。
- Android IPC進(jìn)程間通信詳解最新AndroidStudio的AIDL操作)
- Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Client獲得Server遠(yuǎn)程接口過(guò)程源代碼分析
- Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server啟動(dòng)過(guò)程源代碼分析
- Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server和Client獲得Service Manager接口之路
- 淺談Service Manager成為Android進(jìn)程間通信(IPC)機(jī)制Binder守護(hù)進(jìn)程之路
- Android進(jìn)程間通信(IPC)機(jī)制Binder簡(jiǎn)要介紹
- Android IPC機(jī)制利用Messenger實(shí)現(xiàn)跨進(jìn)程通信
- android IPC之binder通信機(jī)制
- 開(kāi)放IPC$共享
- Android使用文件進(jìn)行IPC
相關(guān)文章
Android 6.0 藍(lán)牙搜索不到設(shè)備原因,MIUI權(quán)限申請(qǐng)機(jī)制方法
今天小編就為大家分享一篇Android6.0 藍(lán)牙搜索不到設(shè)備原因,MIUI權(quán)限申請(qǐng)機(jī)制方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07android通過(guò)led實(shí)現(xiàn)手電筒功能
這篇文章主要為大家詳細(xì)介紹了android通過(guò)led實(shí)現(xiàn)手電筒功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Android利用AudioRecord類(lèi)實(shí)現(xiàn)音頻錄制程序
這篇文章主要為大家詳細(xì)介紹了Android利用AudioRecord類(lèi)實(shí)現(xiàn)音頻錄制程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04android 修改launcher行數(shù)和列數(shù)的方法
這篇文章主要介紹了android 修改launcher行數(shù)和列數(shù)的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07Android用代碼獲取手機(jī)root之后的最高權(quán)限
機(jī)得root之后通過(guò)代碼可以獲得最高權(quán)限如果沒(méi)有root的話請(qǐng)不要往下看,毫無(wú)意義,root之后的朋友可以參考下本文或許有意想不到的收獲2013-03-03Android開(kāi)發(fā)實(shí)現(xiàn)ListView和adapter配合顯示圖片和文字列表功能示例
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)ListView和adapter配合顯示圖片和文字列表功能,涉及Android使用ListView結(jié)合adapter適配器實(shí)現(xiàn)圖文顯示功能相關(guān)的布局、解析、權(quán)限控制等操作技巧,需要的朋友可以參考下2019-04-04Android startActivityForResult實(shí)例詳解
這篇文章主要介紹了Android startActivityForResult實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05