Android中AIDL的实现使用
AIDL简介
AIDL即Android接口描述语言,用于跨进程之间的数据通信。关于其详细的信息可以网上搜,相关内容还是蛮多的。
基本类型的AIDL
AIDL支持的6中基本类型
byte,double,float,int,long,String
现在我们来实现AIDL的方法吧
1.实现*.aidl文件
IAIDLTest.aidl
package com.pachongzhang.myservice;interface IAIDLTest { int add(int a, int b);}
aidl文件的生成与一个接口类(interface)类的实现差不多,首先声明其所在的包名,然后定义其接口类,只是少了public,private这些属性,并且其支持的类型比较少。那我们要实现自定义类用于参数传递,我们就需要让自定义类实现Parcelable接口。下面我们来看下自定义类的AIDL的实现。
自定义类的AIDL
自定义类实现Parcelable,我们需要创建两个文件,.java和.aidl,下面举一个具体的实例。
CustomParcelable.java
package com.pachongzhang.myservice;import android.os.Parcel;import android.os.Parcelable;public class CustomParcelable implements Parcelable { private int a; private String b; public CustomParcelable(Parcel source) { this.a = source.readInt(); this.b = source.readString(); } public CustomParcelable(int a, String b) { this.a = a; this.b = b; } public int getA() { return a; } public void setA(int a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(a); dest.writeString(b); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public CustomParcelable createFromParcel(Parcel source) { return new CustomParcelable(source); } @Override public CustomParcelable[] newArray(int size) { return new CustomParcelable[size]; } };}
CustomParcelable.aidl
package com.pachongzhang.myservice;parcelable CustomParcelable;
从CustomParcelable.java可知其主要用于自定义类的实现方法,CustomParcelable.aidl用于其在AIDL的声明,那么我们要怎么样才能使用这个自定义类呢。
IAIDLTest.aidl
package com.pachongzhang.myservice;import com.pachongzhang.myservice.CustomParcelable;interface IAIDLTest { int add(int a, int b); void getCustom(in CustomParcelable custom);}
从代码中我们可以看到IAIDLTest.aidl文件多了import com.pachongzhang.myservice.CustomParcelable;一个这样的声明,这个就是我们自己定义的那个类,有了这个声明我们就可以在.aidl文件中使用CustomParcelable这个类了,同时要注意的两点就是我们定义了CustomParcelable.java文件还是声明其CustomParcelable.aidl文件,其次是做为参数传递时要声明其是in还是out的方式表示其是输入参数还是输出参数。
说了这么多,我们看下具体的使用吧
AIDL的实践
Service端
首先,我们看service端的实现
代码结构
从Myservice的结构中,我们已经实现了CustomParcelable.java,CustomParcelable.aidl和IAIDLTest.aidl,下面我就看下MyService.java和AndroidManifest.xml。
MyService.java
package com.pachongzhang.myservice;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class MyService extends Service{ protected static final String TAG = "MyService"; @Override public IBinder onBind(Intent intent) { return mBinder; } private Binder mBinder = new IAIDLTest.Stub() { @Override public int add(int a, int b) throws RemoteException { return (a+b); } @Override public void getCustom(CustomParcelable custom) throws RemoteException { Log.d(TAG,"getCustom:"+custom.getA()+",getB:"+custom.getB()); } }; @Override public void onDestroy() { mBinder = null; }}
从MyService.java中我们可以看到我们实现了IAIDLTest.Stub()类,这个类就是用于接口数据传递及其实现,可以看到我们实现了add和getCustom方法。然后通过onBind把IAIDLTest.Stub()对象传递给别的进程,已使其调用MyService 里的方法。我们定义了服务自然而然就要在AndroidManifest.xml中声明。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
可以看到我们声明了MyService服务,并定义了一个action=”com.pachongzhang.myservice.MyService.start”方便别的进程启动本服务。下面来看下Client端访问本服务的方法。
Client端
Client端的代码结构
从结构中我们知道,我们要把那些接口类都搬过来,如果使用了自定义类,还要把自定义的类的java和aidl文件搬过来。所以这么我们就只需要看下MainActivity.java和activity_main.xml的实现了。先来看下Client端实现的效果吧。
这里我们通过调用Service的add方法实现了加法运算。并且通过getCustom打印了对应的信息
效果看过后我们看MainActivity.java和activity_main.xml的实现吧。
activity_main.xml
MainActivity.java
package com.pachongzhang.myclient;import com.pachongzhang.myservice.CustomParcelable;import com.pachongzhang.myservice.IAIDLTest;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.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;public class MainActivity extends Activity implements OnClickListener { private static final String SERVICE_START = "com.pachongzhang.myservice.MyService.start"; private EditText mEditNum1; private EditText mEditNum2; private EditText mEditNum3; private Button mBtnEqual; private IAIDLTest mService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); bindService(true); } @Override protected void onDestroy() { bindService(false); super.onDestroy(); } private void bindService(boolean isBind){ if (isBind) { Intent intent = new Intent(SERVICE_START); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } else { if (mServiceConnection != null) { unbindService(mServiceConnection); mServiceConnection = null; } } } private void initView() { mEditNum1 = (EditText) findViewById(R.id.id_edit_num1); mEditNum2 = (EditText) findViewById(R.id.id_edit_num2); mEditNum3 = (EditText) findViewById(R.id.id_edit_num3); mBtnEqual = (Button) findViewById(R.id.id_btn_equal); mBtnEqual.setOnClickListener(this); } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IAIDLTest.Stub.asInterface(service); } }; @Override public void onClick(View v) { if (v.getId() == R.id.id_btn_equal) { int num1 = Integer.valueOf(mEditNum1.getText().toString()); int num2 = Integer.valueOf(mEditNum2.getText().toString()); try { int num3 = mService.add(num1, num2); mEditNum3.setText(num3+""); CustomParcelable customParcelable = new CustomParcelable(num3, "Success"); mService.getCustom(customParcelable); } catch (RemoteException e) { e.printStackTrace(); } } }}
MainActivity.java的实现也是比较简单的,就简单介绍下,通过bindService获得远程服务的binder,然后通过它就可以调用那些接口了。
Android自定义类序列化
Android序列化一般是用于对象的传递的,因为在Android中一些自定义类对象是不能直接传递的,需要序列化。那我们来看看有哪些序列化的方式,Serializable是java提供的,Parcelable是Android提供的,相对来说Serializable的实现要简单很多,但Parcelable的效率要比Serializable高,可以参考这篇文章Android系统中Parcelable和Serializable的区别。下面我们来看下Parcelable和Serializable的简单实现。
Parcelable
MyParcelable.java
import android.os.Parcel;import android.os.Parcelable;public class MyParcelable implements Parcelable{ private int a; private String b; public MyParcelable(Parcel source) { this.a = source.readInt(); this.b = source.readString(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(a); dest.writeString(b); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public MyParcelable createFromParcel(Parcel source) { return new MyParcelable(source); } @Override public MyParcelable[] newArray(int size) { return new MyParcelable[size]; } };}
Serializable
MySerializable.java
import java.io.Serializable;public class MySerializable implements Serializable { private static final long serialVersionUID = 6285493298229159093L; private int a; private String b;}
从上面两个简单类里我们可以看出Parcelable要比Serializable 复杂的多,但是效率上正好相反。所以在使用上还是推荐使用Parcelable。
更多相关文章
- 如何将Eclipse中的项目迁移到Android(安卓)Studio 中
- Android(安卓)init.rc文件解析过程详解
- React-native 开发之: 安卓(android) app 打签名包
- Android中背光系统架构
- Android(安卓)Studio如何自动 import
- 导入已有工程和更换工作空间
- android JNI 使用 for mac
- ubuntu+ndk编译ffmpeg
- PC 与 Android(安卓)的adb同步通信(一)