android 利用AIDL实现Binder跨进程通信
来源:互联网 发布:淘宝刷单是什么 编辑:程序博客网 时间:2024/05/16 10:45
AIDL整体流程
使用AIDL实现安卓跨进程通信的时候,主要分为3步骤:
- 声明AIDL接口文件,android sdk会根据aidl文件生成接口形式的java文件,服务端实现接口中的抽象类Stub,其中包含了我们声明的方法。并在onBind回调中作为Binder返回给客户端
- 客户端与服务端绑定,在回调函数onServiceConnected中获取Binder
- 利用Stub的asInterface方法转换为我们声明的接口,通过接口调用服务端逻辑。
在使用AIDL时要注意,服务端可能同时和多个客户端进行绑定,所以要设计为线程安全的模式。
除此之外,Service依托于主线程而不依托于创建它的组件,这句话的意思是比如在某个Acitivity中创建Service,Activity关闭后Service仍可运行,然后那个应用关闭后,Service失去依托的主线程所以无法运行。基于此,我们也要注意在Server中的CPU密集和耗时操作,同样要放在新的线程中运行。
示例
1、声明AIDL接口文件
// ITimeManager.aidlpackage com.example.zxc.aidlserver;// Declare any non-default types here with import statementsinterface ITimeManager { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ String getTime();}
声明一个方法,获取服务端的时间。
2、在服务端实现Stub抽象类,实现其中的方法,并通过onBInd回调接口,在Server被绑定调用此回调接口时,将Binder暴露给客户端:
public class MyService extends Service { public MyService() { } private final ITimeManager.Stub binder = new ITimeManager.Stub() { @Override public String getTime() throws RemoteException { return String.valueOf(System.currentTimeMillis()); } }; @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return binder; }}
3、在客户端绑定Service,实现连接回调接口,连接成功时将收到的Binder,通过Stub中的asInterface方法转换为可以使用的接口
public class MainActivity extends AppCompatActivity { private ITimeManager iTimeManager; private ServiceConnection mConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iTimeManager = ITimeManager.Stub.asInterface(service); try { Log.d("TAG", iTimeManager.getTime()); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { iTimeManager = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService(new Intent(MainActivity.this, MyService.class), mConn, Context.BIND_AUTO_CREATE); }}
将客户端和服务端放在不同应用中
当然,这里客户端和服务端还是同一个应用,如果两个应用的话,首先要将Myservice放在服务端,MainActivity中设置连接回调和绑定服务的操作放在客户端。然后aidl下整个包拷贝至服务端应用和客户端应用,注意保持两者包文件名、文件结构相同。最后在服务端应用的Manifest文件设置Service的IntentFilter,这样我们就可以隐式调用了:
<service android:name=".MyService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.zxc.aidlserver.MyService"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
需要提到一个地方:客户端在绑定时隐式调用intent,由于安卓5.0以上不允许隐式调用的方式,会抛出异常
Service Intent must be explicit
解决方法是在隐式调用时,声明intent的时候同时调用setAction和setPackage方法,会被认为是显示调用,最后,客户端绑定服务:
//注意,Intent的action客户端和服务端保持相同即可,packageName要是aidl文件的包名 bindService(new Intent("com.example.zxc.aidlserver.MyService").setPackage("com.example.zxc.aidlserver"), mConn, Context.BIND_AUTO_CREATE);
操作时先打开服务端应用,再打开客户端应用绑定服务即可。可以看到客户端的应用打出了日志
08-22 21:45:31.543 31624-31624/com.example.zxc.myapplication:remote D/TAG: bind
08-22 21:45:31.553 31624-31624/com.example.zxc.myapplication:remote D/TAG: 1471873531564
- android 利用AIDL实现Binder跨进程通信
- Android 中的Binder跨进程通信机制与AIDL
- Android中的跨进程通信AIDL、Binder源码详解
- Android-服务跨进程通信(Binder/Messenger/AIDL)
- Android使用Aidl实现跨进程通信
- android 实现aidl跨进程通信之一
- Android Studio AIDL实现跨进程通信
- Android Studio实现AIDL跨进程通信
- AIDL实现跨进程通信
- AIDL实现跨进程通信
- AIDL实现跨进程通信
- Android 跨进程通信--Binder
- Android跨进程通信-AIDL
- Android跨进程通信-AIDL
- Android AIDL跨进程通信
- Android AIDL跨进程通信
- Android 跨进程通信: AIDL
- Android:AIDL跨进程通信
- 【HDU】-1286-找新朋友(欧拉函数)
- 基金查询
- LeetCode---Container with most water
- HDU 5671 Matrix
- Java 线程
- android 利用AIDL实现Binder跨进程通信
- 位运算求解n皇后问题[模板]
- html面试题
- bellman-ford算法
- 找女朋友
- EJB3 学习笔记七
- 介绍一个成功的 Git 分支模型 Release 分支
- 88. Merge Sorted Array
- uva 140 Bandwidth