博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Service实现双向通信(一)
阅读量:5101 次
发布时间:2019-06-13

本文共 3649 字,大约阅读时间需要 12 分钟。

首先,大概来总结一下与Service的通信方式有很多种:

  1. 通过BroadCastReceiver:这种方式是最简单的,只能用来交换简单的数据;
  2. 通过Messager:这种方式是通过一个传递一个Messager给对方,通过这个它来发送Message对象。这种方式只能单向传递数据。可以是ServiceActivity,也可以是从Activity发送数据给Service。一个Messeger不能同时双向发送;
  3. 通过Binder来实现远程调用(IPC):这种方式是Android的最大特色之一,让你调用远程Service的接口,就像调用本地对象一样,实现非常灵活,写起来也相对复杂。

本文最重点谈一下怎么使用AIDL实现Service端和Client端的双向通信(或者叫"调用")。

首先定义一个AIDL接口如下:

// IRemoteService.aidlpackage com.race604.servicelib; interface IRemoteService { int someOperate(int a, int b); }

这里只定义了一个简单的接口someOperate(),输入参数ab,返回一个int值。

Service的实现如下:

// RemoteService.javapackage com.race604.remoteservice; import ... public class RemoteService extends Service { private static final String TAG = RemoteService.class.getSimpleName(); private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { @Override public int someOperate(int a, int b) throws RemoteException { Log.d(TAG, "called RemoteService someOperate()"); return a + b; } }; @Override public IBinder onBind(Intent intent) { return mBinder; // 注意这里返回binder } }

这里,在RemoteService里面实现一个IRemoteService.Stub接口的Binder,并且在onBind()中返回此Binder对象。 在AndroidManifest.xmlRemoteService的申明如下:

这里android:exported="true"表示可以让其他进程绑定,这里还有一个<action android:name="com.race604.servicelib.IRemoteService" />,这里是为了让后面的Client通过此Action来绑定。

Client的调用方法如下:

package com.race604.client; import ... public class MainActivity extends ActionBarActivity implements View.OnClickListener { private static final String TAG = MainActivity.class.getSimpleName(); private IRemoteService mService; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_SHORT).show(); mService = IRemoteService.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { Toast.makeText(MainActivity.this, "Service disconnected", Toast.LENGTH_SHORT).show(); mService = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.bind).setOnClickListener(this); findViewById(R.id.unbind).setOnClickListener(this); findViewById(R.id.call).setOnClickListener(this); } private void callRemote() { if (mService != null) { try { int result = mService.someOperate(1, 2); Toast.makeText(this, "Remote call return: " + result, Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); Toast.makeText(this, "Remote call error!", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "Service is not available yet!", Toast.LENGTH_SHORT).show(); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bind: Intent intent = new Intent(IRemoteService.class.getName()); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); break; case R.id.unbind: unbindService(mServiceConnection); break; case R.id.call: callRemote(); break; } } }

在客户端,使用Context.bindService()函数,绑定到远程的Service。注意到这里的Intent intent = new Intent(IRemoteService.class.getName());,和上面的Service申明的Action一致。BIND_AUTO_CREATE这个Flag从名字就能看出,表示如果Bind的时候,如果还没有Service的实例,就自动创建。

这里有一个地方需要注意,在Android 5.0以后,就不允许使用非特定的Intent来绑定Service了,需要使用如下方法:

Intent intent = new Intent(IRemoteService.class.getName()); intent.setClassName("com.race604.remoteservice", "com.race604.remoteservice.RemoteService"); // 或者setPackage() // intent.setPackage("com.race604.remoteservice"); bindService(intent, mServiceConnection, BIND_AUTO_CREATE);

到这里就基本实现了一个完整的Client调用远程Service的实例了。

源代码可以参考这个。

转载于:https://www.cnblogs.com/android-blogs/p/5735608.html

你可能感兴趣的文章
ad logon hour
查看>>
获得进程可执行文件的路径: GetModuleFileNameEx, GetProcessImageFileName, QueryFullProcessImageName...
查看>>
证件照(1寸2寸)拍摄处理知识汇总
查看>>
罗马数字与阿拉伯数字转换
查看>>
Eclipse 反编译之 JadClipse
查看>>
asp.net 获取IP地理位置的几个主要接口
查看>>
Python入门-函数
查看>>
[HDU5727]Necklace(二分图最大匹配,枚举)
查看>>
距离公式汇总以及Python实现
查看>>
设计模式之装饰者模式
查看>>
一道不知道哪里来的容斥题
查看>>
Blender Python UV 学习
查看>>
window添加右键菜单
查看>>
入手腾龙SP AF90mm MACRO
查看>>
python学习4 常用内置模块
查看>>
Window7上搭建symfony开发环境(PEAR)
查看>>
ResolveUrl的用法
查看>>
Linux内核态、用户态简介与IntelCPU特权级别--Ring0-3
查看>>
第23月第24天 git命令 .git-credentials git rm --cached git stash clear
查看>>
java SE :标准输入/输出
查看>>