AIDL进程间传递复杂数据类型—AIDL传递其他AIDL接口
2015-08-15 14:32
555 查看
AIDL进程间传递复杂数据类型系列:
AIDL进程间传递复杂数据类型—AIDL传递其他AIDL接口
AIDL进程间传递复杂数据类型—AIDL传递android.os.Parcelable接口
=========================================
首先我们来写一个简单的服务:
AIDL文件:
客户端文件MainActivity.java:
服务端代码为MyService.java
layout布局文件:
当我们在使用bindService来绑定服务的时候,只需要在AndrodManifest配置文件中,在Service的属性中加上android:process=”:remote”,remote这个名字可以自定义,我们就可以在一个新的进程中绑定一个服务。
代码如下:
上面的过程很简单,也很熟悉,按照流程走就可以了。
上面只是传递了简单的int类型的值,这里想说的就是使用AIDL进行这种进程间通信的时候,可以传递哪些数据类型。
下面进行了一些总结。
1.AIDL支持Java原始数据类型
2.AIDL支持String和CharSequence
3.AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个import语句,即使位于同一个包中
4.AIDL支持传递实现了android.os.Parcelable接口的复杂类型,同样在引用这些类型时也需要import语句
5.AIDL支持java.util.List和java.util.Map,但是有一些限制。集合中项的允许数据类型包括Java原始类型、String、CharSequence或是android.os.Parcelable。无需为List和Map提供import语句,但需要为Parcelable提供import语句。
具体为什么AIDL可以传递这些数据类型以及它可以传递的详细数据类型可以参考文章浅析Android中Parcel类 。
另外需要注意的是:非原始类型中,除了String和CharSequence以外,其余均需要一个方向指示符。方向指示符包括in、out、和inout。in表示由客户端设置,out表示由服务端设置,inout表示客户端和服务端都设置了该值。
我们这里主要介绍后面的第3和第4种,前面的两种比较简单,我们上面代码已经展示了用法,把第3种和第4种弄明白了,第5种应该没什么问题。
一、AIDL传递其他AIDL接口
在客户端和服务端分别有两个AIDL文件,是一个是绑定服务使用,一个是传递使用
可以看到IListener是IManager里面registerListener的一个参数,即这里传递的就是AIDL接口。
服务端代码:
客户端代码:
客户端布局文件activity_main.xml:
可以看到,我们服务直接传递了一个IListener类型的参数去在服务端注册了一个回调,然后在服务端就可以回调客户端的实现函数。这个非常的有用。
运行代码,首先启动服务端,然后启动客户端:
客户端的运行界面如下:
首先点击”绑定服务”
客户端打印的Log如下:
服务端打印的Log如下:
当点击”计算”
客户端打印的Log如下:
当点击”传递监听”
客户端打印的Log如下:
服务端打印的Log如下:
我们可以看到,服务端回调了mListener.onChange(4),客户端确实执行了这个函数,并且得到了服务端传递过来的这个值。
第二种参看下面这篇文章:
AIDL进程间传递复杂数据类型—AIDL传递android.os.Parcelable接口
AIDL进程间传递复杂数据类型—AIDL传递其他AIDL接口
AIDL进程间传递复杂数据类型—AIDL传递android.os.Parcelable接口
=========================================
首先我们来写一个简单的服务:
AIDL文件:
interface IManager { int add(int x , int y); int min(int x , int y ); }
客户端文件MainActivity.java:
public class MainActivity extends Activity { private IManager manager; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i("MyService", "onServiceConnected"); //得到本地代理对象 manager = IManager.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void bindService(View view) { Log.i("MyService", "bindService"); Intent intent = new Intent("com.startservice.MyService"); bindService(intent, connection, Context.BIND_AUTO_CREATE); } public void unbindService(View view) { unbindService(connection); } public void caculate(View view){ if (manager == null) { Toast.makeText(this, "请绑定服务", Toast.LENGTH_SHORT).show(); } else { int result = 0; try { result = manager.add(4, 5); } catch (Exception e) { e.printStackTrace(); } Toast.makeText(this, result + "",Toast.LENGTH_SHORT).show(); } } }
服务端代码为MyService.java
public class MyService extends Service { private Manager manager = new Manager(); public MyService() { } @Override public IBinder onBind(Intent intent) { Log.i("MyService", "onBind"); return manager; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("MyService", "onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i("MyService", "onDestroy"); super.onDestroy(); } class Manager extends IManager.Stub{ @Override public int add(int x, int y) throws RemoteException { return x + y; } @Override public int min(int x, int y) throws RemoteException { return x - y; } } }
layout布局文件:
<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" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <Button android:text="绑定服务" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="bindService"/> <Button android:text="解绑服务" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="unbindService"/> <Button android:text="计算" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="caculate"/> </LinearLayout>
当我们在使用bindService来绑定服务的时候,只需要在AndrodManifest配置文件中,在Service的属性中加上android:process=”:remote”,remote这个名字可以自定义,我们就可以在一个新的进程中绑定一个服务。
代码如下:
<service android:name="com.bindserviceclient.MyService" android:process=":remote" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="com.bindservice.MyService"/> </intent-filter> </service>
上面的过程很简单,也很熟悉,按照流程走就可以了。
上面只是传递了简单的int类型的值,这里想说的就是使用AIDL进行这种进程间通信的时候,可以传递哪些数据类型。
下面进行了一些总结。
1.AIDL支持Java原始数据类型
2.AIDL支持String和CharSequence
3.AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个import语句,即使位于同一个包中
4.AIDL支持传递实现了android.os.Parcelable接口的复杂类型,同样在引用这些类型时也需要import语句
5.AIDL支持java.util.List和java.util.Map,但是有一些限制。集合中项的允许数据类型包括Java原始类型、String、CharSequence或是android.os.Parcelable。无需为List和Map提供import语句,但需要为Parcelable提供import语句。
具体为什么AIDL可以传递这些数据类型以及它可以传递的详细数据类型可以参考文章浅析Android中Parcel类 。
另外需要注意的是:非原始类型中,除了String和CharSequence以外,其余均需要一个方向指示符。方向指示符包括in、out、和inout。in表示由客户端设置,out表示由服务端设置,inout表示客户端和服务端都设置了该值。
我们这里主要介绍后面的第3和第4种,前面的两种比较简单,我们上面代码已经展示了用法,把第3种和第4种弄明白了,第5种应该没什么问题。
一、AIDL传递其他AIDL接口
在客户端和服务端分别有两个AIDL文件,是一个是绑定服务使用,一个是传递使用
// IManager.aidl package com.xxx.cn.client; import com.xxx.cn.client.IListener; interface IManager { int add(int x , int y); void registerListener(in IListener listener); }
// IListener.aidl package com.xxx.cn.client; interface IListener { void onChange(int x); }
可以看到IListener是IManager里面registerListener的一个参数,即这里传递的就是AIDL接口。
服务端代码:
//MyService.java: package com.xxx.cn.client; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class MyService extends Service { private static final String TAG = "MyService"; private IListener mListener; private Manager manager = new Manager(); public MyService() { } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind"); return manager; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "onDestroy"); super.onDestroy(); } class Manager extends IManager.Stub{ @Override public int add(int x, int y) throws RemoteException { return x + y; } @Override public void registerListener(IListener listener) throws RemoteException { mListener = listener; //得到这个listner后,就可以在需要的地方回调客户端的onChange函数 mListener.onChange(4); Log.i(TAG, "onChange"); } } }
客户端代码:
//MainActivity.java: package com.xxx.cn.client; 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; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; class Listener extends IListener.Stub { @Override public void onChange(int x) throws RemoteException { Log.i(TAG, "服务端回调了方法onChange,x = " + x); } } private IManager manager; private Listener mListener = new Listener(); private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG, "onServiceConnected"); //得到本地代理对象 manager = IManager.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void bindService(View view) { Log.i(TAG, "bindService"); Intent intent = new Intent("com.bindservice.MyService"); bindService(intent, connection, Context.BIND_AUTO_CREATE); } public void unbindService(View view) { unbindService(connection); } public void caculate(View view){ if (manager == null) { Log.i(TAG, "请绑定服务"); } else { int result = 0; try { result = manager.add(4, 5); } catch (Exception e) { e.printStackTrace(); } Log.i(TAG, "result=" + result); } } public void listener(View view){ if (manager == null) { Log.i(TAG, "请绑定服务"); } else { try { manager.registerListener(mListener); Log.i(TAG, "注册监听"); } catch (Exception e) { e.printStackTrace(); } } } }
客户端布局文件activity_main.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" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <Button android:text="绑定服务" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="bindService"/> <Button android:text="解绑服务" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="unbindService"/> <Button android:text="计算" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="caculate"/> <Button android:text="传递监听" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="listener"/> </LinearLayout>
可以看到,我们服务直接传递了一个IListener类型的参数去在服务端注册了一个回调,然后在服务端就可以回调客户端的实现函数。这个非常的有用。
运行代码,首先启动服务端,然后启动客户端:
客户端的运行界面如下:
首先点击”绑定服务”
客户端打印的Log如下:
服务端打印的Log如下:
当点击”计算”
客户端打印的Log如下:
当点击”传递监听”
客户端打印的Log如下:
服务端打印的Log如下:
我们可以看到,服务端回调了mListener.onChange(4),客户端确实执行了这个函数,并且得到了服务端传递过来的这个值。
第二种参看下面这篇文章:
AIDL进程间传递复杂数据类型—AIDL传递android.os.Parcelable接口
相关文章推荐
- Could not find action or result: /SendMail/servlet/UploadServlet
- 简易智能自动问答机器人
- hdu 5289 Assignment 2015 Multi-University Training Contest 1
- HDU Train Problem I (STL_栈)
- RAID磁盘阵列RAID级别的介绍
- 实现Pop3s&maildrop(有错待解决)
- HDU 1023 Train Problem II(Catalan)
- freemaker 中显示变量的类的名称,真的是baidu很久才找到的。唉,,,
- Web性能压力测试工具之WebBench详解
- 职责链模式(Chain of Responsibility)
- 关于main函数的返回值
- HDU 4300 Clairewd’s message
- 理解Time-Wait
- HDOJ 1021 Fibonacci Again 【数论】
- HDOJ 1021 Fibonacci Again 【数论】
- android调用httpclient.excute报android.os.NetworkOnMainThreadException 异常处理
- hit2060Fibonacci Problem Again
- Hdu 2015 Multi-University Training Contest8
- HIT 2060 Fibonacci Problem Again(矩阵乘法)
- dailyAdvice服务器与客户端