android
一、Binder與傳統(tǒng)IPC對(duì)比
Binder | 共享內(nèi)存 | Socket | |
---|---|---|---|
性能 | 需要拷貝一次 | 無(wú)需拷貝 | 需要拷貝兩次 |
特點(diǎn) | 基于c/s架構(gòu),易用性高 | 控制復(fù)雜,易用性差 | 基于c/s架構(gòu),作為一款通用接口,其傳輸效率低,開(kāi)銷大 |
安全性 | 為每個(gè)APP分配UID,同時(shí)支持實(shí)名和匿名 | 依賴上層協(xié)議,訪問(wèn)接入點(diǎn)是開(kāi)放的,不安全 | 依賴上層協(xié)議,訪問(wèn)接入點(diǎn)是開(kāi)放的,不安全 |
二、AIDL(安卓接口描述語(yǔ)言)的使用
1、創(chuàng)建接口,使用到自定義類的話,需要導(dǎo)包,加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、自定義數(shù)據(jù)通信類,需要實(shí)現(xiàn)序列化
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中定義自定義數(shù)據(jù)通信類
// Person.aidl
package com.example.aidl.service;
// Declare any non-default types here with import statements
parcelable Person;
4、拷貝服務(wù)端的aidl,包名不變
5、拷貝自定義數(shù)據(jù)通信類,包名必須一致
6、創(chuàng)建服務(wù)端Service,new一個(gè)Binder(實(shí)現(xiàn)了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,綁定服務(wù)端。new一個(gè)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目的:如何獲取到另一個(gè)進(jìn)程服務(wù)的對(duì)象?
2、通過(guò)這個(gè)對(duì)象,如何跨進(jìn)程調(diào)用的?
客戶端proxy調(diào)用調(diào)用binder 的transact()方法傳輸數(shù)據(jù),c、c++方法
服務(wù)端sub的 onTransact()