资讯专栏INFORMATION COLUMN

Android IPC机制(一)——绑定Service实现本地通信

GitCafe / 1469人阅读

摘要:而使用绑定的方式启动则可以实现之间的通信。下面就讲述一下绑定实现本地通信的流程。单击调用方法并且解除绑定。注意解除绑定事件只能执行一次,否则程序会崩溃。

写作原因:跨进程通信的实现和理解是Android进阶中重要的一环。下面博主分享IPC一些相关知识、操作及自己在学习IPC过程中的一些理解。

这一章是为下面的Messenger和AIDL的使用做准备,主要讲解Android Service的绑定和Activity与本地Service之间通信相关知识。

简介

我们都知道启动Service有两种方式:startService()和bindService()。相比第一种方式,bindService()能够更加灵活地实现与启动端Activity的数据通信,第一种启动方式启动Activity与Service之间并没有直接关联,难以直接实现通信(当然了,使用BroadCast或者事件总线也是可以实现的)。而使用绑定的方式启动Service则可以实现Service之间的通信。下面就讲述一下绑定Service实现本地通信的流程。

以Activity调用Service中的方法为例,具体流程参考博主绘制的流程图:

实例

结合图片我们来模拟开启一个后台执行更新功能为例来讲解本地Service的绑定。

先分析一下该需求的场景:首先我们需要点击Start按钮开启后台更新数据,后台将数据返回给Activity并在ProgressBar展示进度;当我们点击Pause时后台暂停更新;点击Stop按钮时关闭后台。本例中也用到Service通过BroadCast向Activity传递数据。由于只是实例,对于线程操作一块有一些bug,希望大家能够帮忙指正。

Activity的布局如下:

Service实现

先看看Service的实现,思路是这样的:

</>复制代码

  1. 先继承Binder类创建MyBinder类,把MyBinder看做Service与Activity通信的代理人,所以在MyBinder内部中写好方法间接调用Service中的方法以供Activity去调用(如本例中callPauseUpgrade())。关于IBinder对象的获取除了直接重写后面还有两种方式,这里先不阐述了。在Service中我们开启一个Thread,在这个Thread中模拟持续更新进度条直到isStop为False或者progress大于等于100时,然后将进度广播出去,让Activity接收到广播进行进度条更新。Service中供Activity调用的方法实现暂停和停止Thread的功能,具体过程参照代码。

</>复制代码

  1. public class UpgradeService extends Service {
  2. private Thread thread;
  3. private Intent intent;
  4. private int progress;
  5. private Boolean isStop;
  6. public class MyBinder extends Binder{
  7. public void callPauseUpgrade(){
  8. pauseUpgrade();
  9. }
  10. public void callStopUpgrade() {
  11. stopUpgrade();
  12. }
  13. }
  14. private void stopUpgrade() {
  15. progress = 0;
  16. isStop = false;
  17. intent.putExtra("progress",progress);
  18. sendBroadcast(intent);
  19. }
  20. @Override
  21. public void onCreate() {
  22. super.onCreate();
  23. progress = 0;
  24. isStop = true;
  25. intent = new Intent();
  26. thread = new Thread(new Runnable() {
  27. @Override
  28. public void run() {
  29. while(isStop){
  30. try {
  31. Thread.sleep(1000);
  32. } catch (InterruptedException e) {
  33. e.printStackTrace();
  34. }
  35. progress = progress +5;
  36. intent.putExtra("progress",progress);
  37. intent.setAction("UPGRADE_ACTION");
  38. sendBroadcast(intent);
  39. if(progress>=100) break;
  40. }
  41. }
  42. });
  43. thread.start();
  44. }
  45. private void pauseUpgrade() {
  46. //TODO:Pause the upgrade
  47. Toast.makeText(getApplicationContext(),"暂停",Toast.LENGTH_SHORT).show();
  48. isStop = false;
  49. }
  50. @Override
  51. public IBinder onBind(Intent intent) {
  52. return new MyBinder();
  53. }
  54. }
Activity实现

下面是在客户端实现与Service的通信代码。主要思路是:先注册广播实现Service数据的返回;单击Start按钮时实现与Service的绑定,创建ServiceConnection对象实现ServiceConnection接口,分别回调绑定成功和失败两种情况下的逻辑。当成功时获取MyBinder对象,并将设置的isBound值设为true;当失败时将isBound设置为false。单击Pause调用MyBinder对象的callPauseUpgrade()方法间接调用Service中的pauseUpgrade()方法。单击Stop调用callStopUpgrade()方法并且解除绑定。注意解除绑定事件只能执行一次,否则程序会崩溃。具体实现并不难,主要是认真理解上面的流程图即可。

</>复制代码

  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener{
  2. private Button mBtStart;
  3. private Button mBtStop;
  4. private Button mBtPause;
  5. private ProgressBar mPbProgress;
  6. private UpgradeService.MyBinder myBinder;
  7. private boolean isBound;
  8. private UpgradeReceiver upgradeReceiver;
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. IntentFilter intentFilter = new IntentFilter();
  14. intentFilter.addAction("UPGRADE_ACTION");
  15. upgradeReceiver = new UpgradeReceiver();
  16. registerReceiver(upgradeReceiver,intentFilter);
  17. initView();
  18. initEvent();
  19. }
  20. public class UpgradeReceiver extends BroadcastReceiver{
  21. @Override
  22. public void onReceive(Context context, Intent intent) {
  23. mPbProgress.setProgress(intent.getIntExtra("progress",0));
  24. }
  25. }
  26. @Override
  27. protected void onDestroy() {
  28. super.onDestroy();
  29. unregisterReceiver(upgradeReceiver);
  30. }
  31. private void initEvent() {
  32. mBtPause.setOnClickListener(this);
  33. mBtStart.setOnClickListener(this);
  34. mBtStop.setOnClickListener(this);
  35. }
  36. private void initView() {
  37. mBtPause = (Button) findViewById(R.id.bt_pause);
  38. mBtStart = (Button) findViewById(R.id.bt_start);
  39. mBtStop = (Button) findViewById(R.id.bt_stop);
  40. mPbProgress = (ProgressBar) findViewById(R.id.pb_progress);
  41. }
  42. @Override
  43. public void onClick(View v) {
  44. switch(v.getId()){
  45. case R.id.bt_pause:
  46. if(isBound&&myBinder!=null){
  47. myBinder.callPauseUpgrade();
  48. }
  49. break;
  50. case R.id.bt_start:
  51. bindService(new Intent(MainActivity.this,UpgradeService.class),conn,BIND_AUTO_CREATE);
  52. break;
  53. case R.id.bt_stop:
  54. if(isBound) {
  55. myBinder.callStopUpgrade();
  56. unbindService(conn);
  57. isBound = false;
  58. }
  59. break;
  60. }
  61. }
  62. private ServiceConnection conn = new ServiceConnection() {
  63. @Override
  64. public void onServiceConnected(ComponentName name, IBinder service) {
  65. if(service != null){
  66. myBinder = (UpgradeService.MyBinder) service;
  67. isBound = true;
  68. }
  69. }
  70. @Override
  71. public void onServiceDisconnected(ComponentName name) {
  72. isBound = false;
  73. }
  74. };
  75. }
总结

这篇文章是为下面的Messenger和AIDL跨进程通信做准备的,实际上个人感觉真正开发时可以使用EventBus或者RxJava取代这种同进程各个组件通信的问题,有兴趣的读者可以自行尝试。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64925.html

相关文章

  • 02.AndroidIPC机制问题

    摘要:中为何新增来作为主要的方式运行机制是怎样的机制有什么优势运行机制是怎样的基于通信模式,除了端和端,还有两角色一起合作完成进程间通信功能。 目录介绍 2.0.0.1 什么是Binder?为什么要使用Binder?Binder中是如何进行线程管理的?总结binder讲的是什么? 2.0.0.2 Android中进程和线程的关系?什么是IPC?为何需要进行IPC?多进程通信可能会出现什么问...

    Donne 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<