四大跨进程通信组件之AIDL(跨进程service通信)
来源:互联网 发布:python 分布式计算 编辑:程序博客网 时间:2024/06/05 18:22
AIDL:Android Interface Definition Language,即Android接口定义语言
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程
百度百科
过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案 一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
AIDL作为四大跨进程通讯手段之一,我们就算不能完全掌握它,也需要大概了解下它是如何运行的,下面我就写个小例子去展示它。
我会使用本进程AIDL的使用和跨进程AIDL的使用来讲解它
- 列表内容
新建一个项目,在其中建立一个AIDL文件
interface AIDLTest { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ int add(int x,int y); int multiplication(int x , int y );}
上面是定义的AIDL接口,里面有两个方法,一个加法一个乘法,我会在本进程实现加法,在外部进程实现乘法,然后log出来
5.创建一个server
private static final String TAG = "server"; public void onCreate() { Log.e(TAG, "onCreate"); } public IBinder onBind(Intent t) { Log.e(TAG, "onBind"); return mBinder; } public void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); } public boolean onUnbind(Intent intent) { Log.e(TAG, "onUnbind"); return super.onUnbind(intent); } public void onRebind(Intent intent) { Log.e(TAG, "onRebind"); super.onRebind(intent); } private final AIDLTest.Stub mBinder = new AIDLTest.Stub() { @Override public int add(int x, int y) throws RemoteException { return x + y; } @Override public int multiplication(int x, int y) throws RemoteException { return 0; }
注意看最后一段,在这里面实现接口里面定义的方法,然后再onBind中返回给activity,点击进Stub我们可以发现,他其实是一个继承Binder的抽象类
public static abstract class Stub extends android.os.Binder implements com.example.myapplication.AIDLTest
而Binder又是接口IBinder
public class Binder implements IBinder
所以AIDL和binder的关系其实是密不可分的,不过这里暂且不谈binder,我在这里,把乘法的返回值设为0,就是为了区分是本地进程,还是外部进程。
下面是mainactivity的代码
package com.example.myapplication;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import android.view.View;import android.widget.Toast;public class MainActivity extends Activity implements ServiceConnection { private AIDLTest aidlTest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /** * 点击BindService按钮时调用 * * @param view */ public void bindService(View view) { Intent intent = new Intent(MainActivity.this, MyService.class); bindService(intent, this, Context.BIND_AUTO_CREATE); } /** * 点击bindOtherServer按钮时调用 * * @param view */ public void bindOtherServer(View view) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.another","com.example.another.MyOtherServer")); bindService(intent,this,BIND_AUTO_CREATE); } /** * 点击2+3按钮时调用 * * @param view */ public void add(View view) throws Exception { if (aidlTest != null) { int addRes = aidlTest.add(2, 3); Log.i("bindServer", "这是当前server加法的值为" + addRes); Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "重新绑定服务端", Toast.LENGTH_SHORT) .show(); } } /** * 点击2*3按钮时调用 * * @param view */ public void multiplication(View view) throws Exception { if (aidlTest != null) { int addRes = aidlTest.multiplication(2, 3); Log.i("bindServer", "这是当前server乘法的值为0?" + addRes); Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "重新绑定服务端", Toast.LENGTH_SHORT) .show(); } } @Override public void onServiceConnected(ComponentName name, IBinder service) { aidlTest = AIDLTest.Stub.asInterface(service); if (aidlTest != null) { try { int addRes = aidlTest.multiplication(58, 12); Log.i("bindServer", "这是外部server乘法的值为" + addRes); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public void onServiceDisconnected(ComponentName name) { }}
这里代码量不多 我就干脆把xml也贴出来,免得给下载链接
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="bindService" android:text="绑定本地的服务" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="bindOtherServer" android:text="绑定其他的服务" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="add" android:text="2+3" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="multiplication" android:text="2*3" /></LinearLayout>
上面其实就可以运行了 ,点击绑定本地的服务,点击下面两个计算按键可得 11-28 10:23:56.700 7654-7654/? I/bindServer: 这是当前server加法的值为5
11-28 10:23:57.900 7654-7654/? I/bindServer: 这是当前server乘法的值为0?0
下面在写一个另外一个项目:AIDLModeAnOther,这个的MainActivity和server比较简单
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.content_main); startService(new Intent(this,MyOtherServer.class)); }}
直接启动server即可,不过server中的方法和上面一致,就是这里改一下
private final AIDLTest.Stub mBinder = new AIDLTest.Stub() { @Override public int add(int x, int y) throws RemoteException { return x + y; } @Override public int multiplication(int x, int y) throws RemoteException { return x*y; } };
好知道这里能得出乘法的值。
然后再这个项目中也建立一个aidl包,重点来了,这两个项目的aidl要完全一样,从内容到包名。复制上面的下来即可
一切做完了之后,先点击下面这个AIDLModeAnOther运行,成了之后再 点击上面那个项目运行,点击绑定本地的服务,点击计算按键,显示本进程计算结果。再点击绑定其他的服务,就不用点击计算按键了,我图方便,直接就显示出来了 ,如下所示
11-28 10:32:41.650 7921-7921/? I/bindServer: 这是当前server加法的值为511-28 10:32:42.070 7921-7921/? I/bindServer: 这是当前server乘法的值为0?011-28 10:32:43.410 7921-7921/? I/bindServer: 这是外部server乘法的值为6
到这里就算是演示完毕了 不过最后再说一个:从 Android 5.0 以后只能通信显式 Intent 来启动服务
开启服务用我上面所写的那样
Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.another","com.example.another.MyOtherServer")); bindService(intent,this,BIND_AUTO_CREATE);
而不能继续使用进程间通信 Intent机制 隐式启动了。
隐式启动就是在你的AndroidManifest,你要启动的服务或activity下加一个
<intent-filter> <action android:name="xxxxxxxxxx" />
然后在程序中
Intent intent = new Intent("xxxxxxxx"); //这个为隐式启动Activity的搜索名称
这样调用它
,好了这篇博客就将这么多,希望看过的人觉得好的留个言,点个赞,谢谢了!
- 四大跨进程通信组件之AIDL(跨进程service通信)
- 跨进程通信之AIDL
- AIDL跨进程通信
- AIDL跨进程通信
- AIDL跨进程通信和Service调用
- AIDL Service实现跨进程通信
- 【跨进程】跨进程通信---AIDL
- Android 跨进程通信之:AIDL
- android之AIDL跨进程通信详解
- Android跨进程通信之AIDL
- Android跨进程通信-AIDL
- Android跨进程通信-AIDL
- AIDL实现跨进程通信
- AIDL实现跨进程通信
- Android AIDL跨进程通信
- AIDL实现跨进程通信
- Android AIDL跨进程通信
- 使用AIDL跨进程通信
- 关于内存管理的总结 -02-
- Eclipse中如何设置JSP的模板为pageEncoding="UTF-8"?
- 开启 MySQL 的远程登陆
- 关于开发项目的注意事项-以javaEE为例
- LeetCode-Two Sum
- 四大跨进程通信组件之AIDL(跨进程service通信)
- hdoj 阿牛的EOF牛肉串
- ILSpy For MacOsX
- UML——类图和对象图
- java.util.ResourceBundle使用详解
- android---logcat
- POJ 3628 Bookshelf 2(用DFS做01背包)
- MYSQL数据库字段命名及设计规范
- JSP基础