Android 高级工程师进阶 ~ 网易云课堂 学习笔记
什么是Binder ?
安卓的IPC机制
Linux 的驱动
安卓系统中的Binder 类,实现了IBinder接口
Binder在安卓中的使用
四大组件
系统 service 如 AMS,PMS 的实现都依赖于Binder 的通信机制
为什么要在增加 Binder机制
常见的进程间通信机制: 管道、消息队列、共享 内存和Socket
原因:基于性能、稳定性 和安全性几方面考虑
性能方面
====================================================
IPC 数据拷贝次数
共享内存 0
Binder 1
Socket/管道/消息队列 2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
稳定性方面
Binder:基于C/S架构,客户端(client)有什么需求就丢给服务端(Server)去完成
架构清晰,职责明确又相互独立,自然稳定性更好
共享内存:虽然无需拷贝,但是控制复杂,难以使用
从稳定性的角度讲 ,Binder 机制是优于共享内存的。
安全性方面
传统的IPC没有任何安全措施,安全依赖上层协议来确保
传统的IPC方法无法获得对方可靠的进程用户ID/进程ID(UID/PID)从而无法鉴别对方身份
传统的IPC只能由用户在数据包中填入UID/PID 容易被恶意程序利用
传统的IPC访问接入点是开放的,无法阻止恶意程序通过猜测接收方地址获得连接。
Binder既支持实名Binder,又支持 匿名Binder,安全性高。
一个demo 教你如何实现实现跨进程通讯
定义 aidl 文件
// Student.aidl
package com.github.yoyozhangh.studydemo;
// Declare any non-default types here with import statements
parcelable Student;
// IStudentManger.aidl
package com.github.yoyozhangh.studydemo;
import com.github.yoyozhangh.studydemo.Student;
interface IStudentManger {
List<Student> getStudentList();
void addStudent(in Student student);
}
界面1
package com.github.yoyozhangh.studydemo;
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.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.github.yoyozhangh.studydemo.binder.SecondActivity;
import java.util.List;
public class BinderMainActivity extends AppCompatActivity {
private final static String TAG = BinderMainActivity.class.getSimpleName();
private IStudentManger mRemoteStudentManger;
private int student_size = 2;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取到IstudentManger 对象
IStudentManger iStudentManger = IStudentManger.Stub.asInterface(service);
mRemoteStudentManger = iStudentManger;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteStudentManger = null;
Log.e(TAG, "onServiceDisconnected.threadName :" + Thread.currentThread().getName());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.binder_main_activity);
Intent intent = new Intent(this, StudentMangerService.class);
bindService(intent, connection, BIND_AUTO_CREATE);
}
public void toSecondActivity(View view) {
Student.NAME = "netEase";
startActivity(new Intent(this, SecondActivity.class));
Log.e(TAG, "toSecondActivity name=" + Student.NAME);
}
public void getStudentList(View view) {
Toast.makeText(this, "正在获取学生列表", Toast.LENGTH_SHORT).show();
//由于服务端的查询是耗时操作
new Thread(new Runnable() {
@Override
public void run() {
if (mRemoteStudentManger != null) {
try {
final List<Student> studentList = mRemoteStudentManger.getStudentList();
student_size = studentList.size();
Log.e(TAG, "获取到的学生列表 " + studentList.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void addStudent(View view) {
if (mRemoteStudentManger != null) {
int student_id = student_size + 1;
Student newStudent = new Student(student_id, "zhangsan" + student_id, "man");
try {
mRemoteStudentManger.addStudent(newStudent);
Log.e(TAG, "添加一位学生 " + newStudent.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
界面2 SecondActivity
package com.github.yoyozhangh.studydemo.binder;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.github.yoyozhangh.studydemo.R;
import com.github.yoyozhangh.studydemo.Student;
public class SecondActivity extends AppCompatActivity {
private final static String TAG = SecondActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "SecondActivity onCreate: name =" + Student.NAME);
}
}
binder_main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:onClick="toSecondActivity"
android:text="打开 SecondActivity"
android:textAllCaps="false" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:onClick="getStudentList"
android:textAllCaps="false"
android:text="get Student list" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="addStudent"
android:text="add Student" />
</LinearLayout>
<activity android:name=".BinderMainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
StudentMangerService
package com.github.yoyozhangh.studydemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
public class StudentMangerService extends Service {
private static final String TAG = StudentMangerService.class.getSimpleName();
//判断当前的service是否销毁
private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);
// 用于进程安全的传输列表类
private CopyOnWriteArrayList<Student> mStudentList = new CopyOnWriteArrayList<>();
@Override
public void onCreate() {
super.onCreate();
//在服务端先手动添加两个学生
mStudentList.add(new Student(1, "netease", "man"));
mStudentList.add(new Student(2, "net", "woman"));
}
@Override
public void onDestroy() {
mIsServiceDestoryed.set(true);
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return new MyStudentManger();
}
class MyStudentManger extends IStudentManger.Stub {
@Override
public List<Student> getStudentList() throws RemoteException {
SystemClock.sleep(2000);//休眠2s 模拟服务端的耗时操作
return mStudentList;
}
@Override
public void addStudent(Student student) throws RemoteException {
mStudentList.add(student);
}
}
}
<service
android:name=".StudentMangerService"
android:process=":remote" />
Student
package com.github.yoyozhangh.studydemo;
import android.os.Parcel;
import android.os.Parcelable;
public class Student implements Parcelable {
public static String NAME = "THINK";
private int s_id;
private String s_name;
private String s_gender;
public Student(int s_id, String s_name, String s_gender) {
this.s_id = s_id;
this.s_name = s_name;
this.s_gender = s_gender;
}
protected Student(Parcel in) {
s_id = in.readInt();
s_name = in.readString();
s_gender = in.readString();
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(s_id);
dest.writeString(s_name);
dest.writeString(s_gender);
}
@Override
public String toString() {
return "Student{" +
"s_id=" + s_id +
", s_name='" + s_name + '\'' +
", s_gender='" + s_gender + '\'' +
'}';
}
}
源码地址:https://github.com/yoyo0316/StudyDemo/commit/b309c28611dbd9f1a0ee2a3b38bd16bf2ce383d9