恢弘志士之气,不宜妄自菲薄。这篇文章主要讲述Android Studio创建AIDL文件并实现进程间通讯相关的知识,希望能为你提供帮助。
在android系统中,
跨进程通信是非常普遍的事情,
它用到了Binder机制处理进程之间的交互。Binder机制会开放一些接口给java层,
供android开发工程师调用进程之间通信。这些接口android封装到了AIDL文件里,
当我们项目用到跨进程通信时可以创建.aidl文件,
.aidl文件可以协助我们达到跨进程的通信。下面简单介绍用AndroidStudio创建AIDL文件的过程。
a.新建AIDL文件
1.项目文件夹右键--->
new --->
选择AIDL
文章图片
2.自定义一个接口名称
文章图片
3.创建之后我们看到了xxx.aidl文件, 然后编辑自己项目需要实现的方法, 这里很简单就获取一个字符串的方法getAllName。
文章图片
4.写好之后, 我们需要重新ReBuild, 完后在项目build/generated/source/aidl/debug/包名 目录下就看到了系统为我们生成的以刚才.aidl文件名命名的java文件。
【Android Studio创建AIDL文件并实现进程间通讯】
文章图片
该java文件系统会自动生成代码:
Stub: 描述了一个Java服务, 对应是一个远程的Service。
Proxy: 描述了一个Java服务的代理对象, 在Client端就会得到这个对象。
这两者都实现了IPersonManager接口。
asInterface: 将Java服务的代理对象即一个BinderProxy封装成了一个IPersonManager.Stub.Proxy对象, 实现了IPersonManager接口。
onTransact: 负责接收分发进程间的通信。它首先会收到Client发来的请求, 不同的方法进入相应的case代码中, 然后交给Stub的子类去处理事件, 例如 java.lang.String _result = this.getAllName(); 这里的this就可以让它的子类去接收该请求并处理。
IBinder的transact方法: 用来发送进程间的请求。
b.利用AIDL实现进程间的通讯
一: 接口文件中只含有基础数据类型
如上aidl文件, IPersonManager中只用到了基本数据类型, 此时要完善Server端的小项目, 还需要新建一个Service。
Server端代码如下
public class PersonService extends Service {private static String names =
"
alice &
iland"
;
public PersonBinder mPersonBinder;
@
Override
public void onCreate() {
super.onCreate();
mPersonBinder =
new PersonBinder();
}@
Override
public IBinder onBind(Intent intent) {
return mPersonBinder;
}
public class PersonBinder extends IPersonManager.Stub{@
Override
public String getAllName() throws RemoteException {
return names;
}
}}
继承系统的Service, 并建立一个内部类继承IPersonManager.Stub,这里很简单, 当客户端请求要获取名字时我们这里把names给到客户端。
Client端代码如下
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG =
"
MainActivity"
;
private Button btnGet;
private EditText etShow;
public IPersonManager mIPersonManager;
ServiceConnection sc =
new ServiceConnection() {
@
Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "
onServiceConnected: "
);
mIPersonManager =
IPersonManager.Stub.asInterface(service);
}@
Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "
onServiceDisconnected: "
);
mIPersonManager =
null;
}
};
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGet =
(Button) findViewById(R.id.btn_getname);
etShow =
(EditText) findViewById(R.id.et_allnamef);
btnGet.setOnClickListener(this);
Intent intent =
new Intent("
com.ly.testaidlserver.aidl.AIDL_SERVICE"
);
intent.setPackage("
com.ly.testaidlserver"
);
bindService(intent,sc, Service.BIND_AUTO_CREATE);
}@
Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_getname:
String names =
null;
try {
if (mIPersonManager!=
null)
names =
mIPersonManager.getAllName();
} catch (RemoteException e) {
e.printStackTrace();
}
etShow.setText(names);
break;
default:
break;
}
}@
Override
protected void onDestroy() {
super.onDestroy();
unbindService(sc);
}}
在onServiceConnected方法中拿到IPersonManager的代理对象, 最终获取到 alice & ilan, 与服务端数据一致。
注意:
1.bindService方法在5.0以后做出改变, 隐式意图需要设置Package 或者 Commponent, 直接定义一个action是报异常的。
Intent intent =
new Intent("
com.ly.testaidlserver.aidl.AIDL_SERVICE"
);
intent.setPackage("
com.ly.testaidlserver"
);
bindService(intent,sc, Service.BIND_AUTO_CREATE);
2.我们需要把Server端的aidl文件复制到Client端, 在Client中存放aidl的文件夹也需要跟Server端包名一致。
如图:
文章图片
文章图片
上图为aidl文件在Server端存放的路径, 下图为复制到Client端aidl文件的路径, 这里要保持一致, 因此Client端需要针对Server端的包名新建一个Package。
3.当我们启动项目的时候, 如果在Activity中IPersonManager找不到报出异常, 请在app的build.gradle中添加aidl文件指名目录, 如本例中添加,
sourceSets{
main {
aidl.srcDirs = [' src/main/aidl' ,' src/main/java' ]
}
}
二: 接口文件中含有复杂数据类型、
1.新建一个Person.aidl内容非常简单
parcelable Person;
2.新建一个Person实体类, 为了能在进程间进行通信必须实现Parcelable接口。
3.在IPersonManager中添加了一个方法, 这里注意用到的Person类必须将包名improt进去。
4.将IPersonManager.aidl、Person.aidl、Person.java复制到客户端的aidl包下。
5.查看是否需要修改build.gradle中sourceSets设置
代码基本没有变化:
Person.java
public class Person implements Parcelable {
String name;
int age;
public Person(String name, int age) {
this.name =
name;
this.age =
age;
}public static final Creator<
Person>
CREATOR =
new Creator<
Person>
() {
@
Override
public Person createFromParcel(Parcel in) {
return new Person(in.readString(), in.readInt());
}@
Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@
Override
public int describeContents() {
return 0;
}@
Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}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;
}
}
IPersonManager.aidl
interface IPersonManager {
String getAllName();
List<
Person>
getPersonList();
}
Server
public class PersonService extends Service {private List<
Person>
persons =
new ArrayList<
Person>
();
public PersonBinder mPersonBinder;
@
Override
public void onCreate() {
super.onCreate();
mPersonBinder =
new PersonBinder();
Person p1 =
new Person("
alice"
,23);
persons.add(p1);
Person p2 =
new Person("
iland"
,18);
persons.add(p2);
}@
Override
public IBinder onBind(Intent intent) {
return mPersonBinder;
}
public class PersonBinder extends IPersonManager.Stub{@
Override
public String getAllName() throws RemoteException {
return "
"
;
}@
Override
public List<
Person>
getPersonList() throws RemoteException {
return persons;
}
}
}
Clent
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG =
"
MainActivity"
;
private Button btnGet;
private EditText etShow;
public IPersonManager mIPersonManager;
ServiceConnection sc =
new ServiceConnection() {
@
Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "
onServiceConnected: "
);
mIPersonManager =
IPersonManager.Stub.asInterface(service);
}@
Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "
onServiceDisconnected: "
);
mIPersonManager =
null;
}
};
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGet =
(Button) findViewById(R.id.btn_getname);
etShow =
(EditText) findViewById(R.id.et_allnamef);
btnGet.setOnClickListener(this);
Intent intent =
new Intent("
com.ly.testaidlserver.aidl.AIDL_SERVICE"
);
intent.setPackage("
com.ly.testaidlserver"
);
bindService(intent,sc, Service.BIND_AUTO_CREATE);
}@
Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_getname:
ArrayList<
Person>
persons =
null;
try {
if (mIPersonManager!=
null)
persons =
(ArrayList<
Person>
) mIPersonManager.getPersonList();
} catch (RemoteException e) {
e.printStackTrace();
}
String result =
"
"
;
for (Person person : persons){
result =
result+
person.getName()+
"
__"
+
person.getAge();
}
etShow.setText(result);
break;
default:
break;
}
}@
Override
protected void onDestroy() {
super.onDestroy();
unbindService(sc);
}}
推荐阅读
- 40. leetcode 202. Happy Number
- Android基础TOP6_2:Gallery +Image完成画廊
- Android中 string.xml资源 如何添加参数()
- 安卓的异步下载(Asynchttpclient以及Volley)
- SDK manager.exe 运行时报错(系统找不到指定的文件 android.bat)
- Android基础TOP6_1:FrameLyayout和ImageView制作层叠图片
- applicationContext.xml
- 为android编译libsocket的脚本
- Cannot read lifecycle mapping metadata for artifact org.apache.maven.plugins问题的解决