android
一、Binder与传统IPC对比
Binder | 共享内存 | Socket | |
---|---|---|---|
性能 | 需要拷贝一次 | 无需拷贝 | 需要拷贝两次 |
特点 | 基于c/s架构,易用性高 | 控制复杂,易用性差 | 基于c/s架构,作为一款通用接口,其传输效率低,开销大 |
安全性 | 为每个APP分配UID,同时支持实名和匿名 | 依赖上层协议,访问接入点是开放的,不安全 | 依赖上层协议,访问接入点是开放的,不安全 |
二、AIDL(安卓接口描述语言)的使用
1、创建接口,使用到自定义类的话,需要导包,加in。
// TestAidl.aidl
package com.example.aidl.service;
// Declare any non-default types here with import statements
import com.example.aidl.service.Person;
interface TestAidl {
void addPerson(in Person person);
List<Person> getPersonList();
}
2、自定义数据通信类,需要实现序列化
package com.example.aidl.service;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
private String name;
private int grade;
public Person(String name, int grade) {
this.name = name;
this.grade = grade;
}
protected Person(Parcel in) {
this.name = in.readString();
this.grade = in.readInt();
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@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(grade);
}
}
3、在AIDL中定义自定义数据通信类
// Person.aidl
package com.example.aidl.service;
// Declare any non-default types here with import statements
parcelable Person;
4、拷贝服务端的aidl,包名不变
5、拷贝自定义数据通信类,包名必须一致
6、创建服务端Service,new一个Binder(实现了aidl接口)
package com.example.app.aidl.service;
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;
public class TestAidlService extends Service {
private ArrayList<Person> persons;
@Nullable
@Override
public IBinder onBind(Intent intent) {
persons = new ArrayList<>();
Log.e("TestAidlService", "success onBind");
return iBinder;
}
private IBinder iBinder = new TestAidl.Stub() {
@Override
public void addPerson(Person person) throws RemoteException {
persons.add(person);
}
@Override
public List<Person> getPersonList() throws RemoteException {
return persons;
}
};
@Override
public void onCreate() {
super.onCreate();
Log.e("TestAidlService", "onCreate:onBind");
}
}
5、客户端bindService,绑定服务端。new一个serviceConnection,onServiceConnected方法中
package com.example.app.aidl.client;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.app.R;
import com.example.app.aidl.service.Person;
import com.example.app.aidl.service.TestAidl;
import java.util.List;
public class AidlClientActivity extends AppCompatActivity {
private final static String TAG = "TestActivity";
private TestAidl testAidl;
private Button btn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl_client);
initView();
bindService();
}
private void initView() {
btn = findViewById(R.id.but_click);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
testAidl.addPerson(new Person("leo", 3));
List<Person> persons = testAidl.getPersonList();
Log.e(TAG, persons.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private void bindService() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.app", "com.example.app.aidl.service.TestAidlService"));
bindService(intent, connection, BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "onServiceConnected:success");
testAidl = TestAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "onServiceDisconnected:success");
testAidl = null;
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}
三、aidl源码分析
1、AIDL目的:如何获取到另一个进程服务的对象?
2、通过这个对象,如何跨进程调用的?
客户端proxy调用调用binder 的transact()方法传输数据,c、c++方法
服务端sub的 onTransact()