android中的AIDL学习笔记
一、定义
AIDL是用来解决进程间通信的(一般有四种方式:Activity、Service、ContentProvider、Broadcast Receiver),两个进程间无法直接通信,所以要用AIDL(属于前面提到的Service)来借助操作系统底层来间接进行通信,示意图如下:
AIDL全称为 Android Interface Definition Language,即Android接口定义语言。
二、AIDL开发(操作)流程
开发流程一般为:
1、定义AIDL文件(先在服务端定义,客户端也要定义,内容路服务端一样)
2、服务端实现接口
3、客户端调用接口
三、AIDL语法规则
语法规则如下:
1、语法跟Java的接口很相似
2、AIDL只支持方法,不能定义静态成员
3、AIDL运行方法有任何类型的参数(除short外)和返回值
4、除默认类型,均需要导包
四、AIDL支持的数据类型
1、除short外的基本数据类型
2、String, CharSequence
3、List(作为参数时,要指明是输入in 还是输出out), Map
4、Parcelable (自定义类型要实现 Parcelable 接口)
五、AIDL服务端与客户端之间的关系
六、AIDL适用场景
使用了IPC通信,多个客户端,多线程,否则可使用Binder或Messager
七、示例
1、在服务端定义自定义类型Person,实现 Parcelable 接口:
package com.atwal.aidl;import android.os.Parcel;import android.os.Parcelable;/** * Created by Du on 2016/2/25. */public class Person implements Parcelable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public Person(Parcel source) { this.name = source.readString(); this.age = source.readInt(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.name); dest.writeInt(this.age); } public static final Creator<Person> CREATOR = new Creator<Person>() { @Override public Person createFromParcel(Parcel source) { return new Person(source); } @Override public Person[] newArray(int size) { return new Person[0]; } }; @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
2、在服务端定义 Person.aidl :
// IImoocAidl.aidlpackage com.atwal.aidl;parcelable Person;
3、在服务端定义 IImoocAidl.aidl :
// IImoocAidl.aidlpackage com.atwal.aidl;import com.atwal.aidl.Person;interface IImoocAidl { //计算两个数的和 int add(int num1, int num2); List<String> basicTypes( byte aByte, int aInt, long aLong, boolean aBoolean, float aFloat, double aDouble, char aChar, String aString, in List<String> list); List<Person> addPerson(in Person person);}
4、在服务端定义Service(注意要在AndroidManifest.xml中定义):
package com.atwal.aidl;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.support.annotation.Nullable;import android.util.Log;import java.util.ArrayList;import java.util.List;/** * Created by Du on 2016/2/25. */public class IRemoteService extends Service { private ArrayList<Person> persons; /** * 当客户端绑定到该服务的时候,会执行 * * @param intent * @return */ @Nullable @Override public IBinder onBind(Intent intent) { persons = new ArrayList<>(); return iBinder; } private IBinder iBinder = new IImoocAidl.Stub() { @Override public int add(int num1, int num2) throws RemoteException { Log.d("TAG", "收到了远程的请求,输入的参数是 " + num1 + " 和 " + num2); return num1 + num2; } @Override public List<String> basicTypes(byte aByte, int aInt, long aLong, boolean aBoolean, float aFloat, double aDouble, char aChar, String aString, List<String> list) throws RemoteException { return null; } @Override public List<Person> addPerson(Person person) throws RemoteException { persons.add(person); return persons; } };}
5、在客户端添加Person类,内容和包名都跟服务端一样
6、在客户端添加Person.aidl文件,内容和包名都跟服务端一样
7、在客户端添加IImoocAidl.aidl文件,内客和包名都跟服务端一样
8、客户端调用
布局文件:
<?xml version="1.0" encoding="utf-8"?><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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.atwal.aidlclient.MainActivity"> <EditText android:id="@+id/et_num1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="num1" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="+" android:textSize="20sp" /> <EditText android:id="@+id/et_num2" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="num2" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="=" android:textSize="20sp" /> <TextView android:id="@+id/tv_result" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_add" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="AIDL远程计算" /></LinearLayout>
代码:
package com.atwal.aidlclient;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.IBinder;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import com.atwal.aidl.IImoocAidl;import com.atwal.aidl.Person;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private EditText mEtNum1, mEtNum2; private TextView mTvResult; private Button mBtnAdd; private IImoocAidl iImoocAidl; private ServiceConnection conn = new ServiceConnection() { //绑定上服务的时候 @Override public void onServiceConnected(ComponentName name, IBinder service) { //拿到了远程的服务代理 iImoocAidl = IImoocAidl.Stub.asInterface(service); } //断开服务的时候 @Override public void onServiceDisconnected(ComponentName name) { //回收资源 iImoocAidl = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //应用一启动就绑定服务 bindSersvice(); } private void initView() { mEtNum1 = (EditText) findViewById(R.id.et_num1); mEtNum2 = (EditText) findViewById(R.id.et_num2); mTvResult = (TextView) findViewById(R.id.tv_result); mBtnAdd = (Button) findViewById(R.id.btn_add); mBtnAdd.setOnClickListener(this); } @Override public void onClick(View v) { int num1 = Integer.parseInt(mEtNum1.getText().toString()); int num2 = Integer.parseInt(mEtNum2.getText().toString()); try { //调用远程的服务 int res = iImoocAidl.add(num1, num2); mTvResult.setText(String.valueOf(res)); } catch (RemoteException e) { e.printStackTrace(); mTvResult.setText("错误了"); } try { List<Person> persons = iImoocAidl.addPerson(new Person("atwal", 21)); Log.d("TAG", persons.toString()); } catch (RemoteException e) { e.printStackTrace(); } } private void bindSersvice() { //获取到服务端 Intent intent = new Intent(); //新版本(5.0以上)必须显示Intent启动绑定服务 intent.setComponent(new ComponentName("com.atwal.aidl", "com.atwal.aidl.IRemoteService")); bindService(intent, conn, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); }}
整个项目目录结构如下:
更多相关文章
- Android(安卓)自定义标题栏
- 关于android多分辨率中的density和density-independent pixel的
- 在Android中实现RN的自定义Native Modeule
- android gallery 自定义边框+幻灯片效果
- android 自定义控件的style
- Socket(TCP)
- 它们的定义android滑动菜单
- Android自定义控件实战——滚动选择器PickerView
- Android(安卓)自定义 HorizontalScrollView 打造再多图片(控件)也