前语
上一篇咱们叙述了Service的进阶用法,特别是在运用跨进程Service的时分,咱们运用了AIDL技能,本篇咱们详细来理一理所谓的AIDL技能,它究竟帮咱们做了什么事情。
一、AIDL生成了什么文件
1.1 新建模块代码
咱们新建一个MainActivity和MainService,详细代码如下所示:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RethinkingService">
<activity
android:name="com.afs.rethinkingservice.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.afs.rethinkingservice.MainService"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="com.afs.rethinkingservice.maidl.MainAIDLService" />
</intent-filter>
</service>
</application>
“`
“`
<?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"
tools:context=".MainActivity">
<Button android:id="@+id/btn_start_service" android:layout_width="match_parent"
android:layout_height="wrap_content" android:text="开启服务" />
<Button android:id="@+id/btn_bind_service" android:layout_width="match_parent"
android:layout_height="wrap_content" android:text="绑定服务" />
<Button android:id="@+id/btn_test_aidl_method" android:layout_width="match_parent"
android:layout_height="wrap_content" android:text="测验AIDL中的办法" />
<Button android:id="@+id/btn_stop_service" android:layout_width="match_parent"
android:layout_height="wrap_content" android:text="停止服务" />
</LinearLayout>
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity=========";
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected() executed");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected() executed");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate() executed");
Log.d(TAG, "onCreate() executed Thread id is " + Thread.currentThread().getId());
Log.d(TAG, "onCreate() executed process id is " + Process.myPid());
findViewById(R.id.btn_start_service).setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, MainService.class);
startService(intent);
});
findViewById(R.id.btn_bind_service).setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, MainService.class);
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
});
findViewById(R.id.btn_stop_service).setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, MainService.class);
stopService(intent);
});
findViewById(R.id.btn_test_aidl_method).setOnClickListener(v -> {
});
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() executed");
}
}
package com.afs.rethinkingservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Process;
import android.util.Log;
import androidx.annotation.Nullable;
public class MainService extends Service {
public static final String TAG = "MainService=========";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() executed");
Log.d(TAG, "onCreate() executed Thread id is " + Thread.currentThread().getId());
Log.d(TAG, "onCreate() executed process id is " + Process.myPid());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand() executed");
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind() executed");
return null;
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy() executed");
super.onDestroy();
}
}
1.2 新建aidl文件
右键新建一个名为MainAIDLService.aidl的文件
package com.afs.rethinkingservice.maidl;
// Declare any non-default types here with import statements
interface MainAIDLService {
int plus(int a, int b);
String toUpperCase(String str);
}
然后编译该文件,会在build/generated/aidl_source_output_dir目录下生成一个同名的MainAIDLService.java文件。
/*
* This file is auto-generated. DO NOT MODIFY.
*/
package com.afs.rethinkingservice.maidl;
// Declare any non-default types here with import statements
public interface MainAIDLService extends android.os.IInterface {
/** Default implementation for MainAIDLService. */
public static class Default implements com.afs.rethinkingservice.maidl.MainAIDLService {
@Override
public int plus(int a, int b) throws android.os.RemoteException {
return 0;
}
@Override
public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException {
return null;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAIDLService {
private static final java.lang.String DESCRIPTOR = "com.afs.rethinkingservice.maidl.MainAIDLService";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.afs.rethinkingservice.maidl.MainAIDLService interface,
* generating a proxy if needed.
*/
public static com.afs.rethinkingservice.maidl.MainAIDLService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAIDLService))) {
return ((com.afs.rethinkingservice.maidl.MainAIDLService) iin);
}
return new com.afs.rethinkingservice.maidl.MainAIDLService.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_plus: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.plus(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_toUpperCase: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.toUpperCase(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.afs.rethinkingservice.maidl.MainAIDLService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public int plus(int a, int b) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(a);
_data.writeInt(b);
boolean _status = mRemote.transact(Stub.TRANSACTION_plus, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().plus(a, b);
}
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(str);
boolean _status = mRemote.transact(Stub.TRANSACTION_toUpperCase, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().toUpperCase(str);
}
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.afs.rethinkingservice.maidl.MainAIDLService sDefaultImpl;
}
static final int TRANSACTION_plus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_toUpperCase = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.afs.rethinkingservice.maidl.MainAIDLService impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.afs.rethinkingservice.maidl.MainAIDLService getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public int plus(int a, int b) throws android.os.RemoteException;
public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException;
}
1.3 整理aidl生成的文件内容
对着MainAIDLService.java文件,乍一看咱们可能会觉得一脸懵逼,该文件如同非常混乱,可是假如细心整理一下,其实会发现里边的结构是这样的
主要是主动生成了四个类,MainAIDLService、Default、Stub、Proxy,假如咱们把代码精简一下,大概是下面这样的:
public interface MainAidlService extends android.os.IInterface {
/**
* MainAidlService接口的默许完结类(高版别SDK才会生成)
*/
public static class Default implements com.afs.rethinkingservice.maidl.MainAidlService {
}
/**
* 本地IPC通讯的完结类父类
*/
public static abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
/**
* 长途IPC通讯的完结类
*/
private static class Proxy implements com.afs.rethinkingservice.maidl.MainAidlService {
}
}
}
由此可见,aidl主要是帮咱们生成了以下四个东西
- 【MainAidlService】接口,承继了android.os.IInterface的接口
- 【Default】类,完结了MainAidlService接口的类(高版别SDK才会生成MainAidlService接口的默许完结类)
- 【Stub】抽象类,承继自android.os.Binder并完结了MainAidlService接口(本地IPC通讯的完结类父类)
- 【Proxy】类,完结了MainAidlService接口(长途IPC通讯的完结类)
二、去除AIDL文件,创立Java类完结Binder通讯
2.1 复制aidl生成的类
在理清了这四个类之后,接下来咱们能够把上面说到的四个类全部复制出来,放到咱们的java包中,
删去本来右键新建的MainAIDLService.aidl文件,以及在build文件夹中生成的文件。
之后修复代码(主要是拜访权限的修正),去除错误提示之后,各个类的代码如下所示:
public interface MainAidlService extends android.os.IInterface {
public int plus(int a, int b) throws android.os.RemoteException;
public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException;
}
public class Default implements com.afs.rethinkingservice.maidl.MainAidlService {
@Override
public int plus(int a, int b) throws android.os.RemoteException {
return 0;
}
@Override
public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException {
return null;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
public class Proxy implements com.afs.rethinkingservice.maidl.MainAidlService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public int plus(int a, int b) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(a);
_data.writeInt(b);
boolean _status = mRemote.transact(Stub.TRANSACTION_plus, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().plus(a, b);
}
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(str);
boolean _status = mRemote.transact(Stub.TRANSACTION_toUpperCase, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().toUpperCase(str);
}
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static MainAidlService sDefaultImpl;
}
public abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
public static final java.lang.String DESCRIPTOR = "com.afs.rethinkingservice.maidl.MainAidlService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.afs.rethinkingservice.maidl.MainAidlService interface,
* generating a proxy if needed.
*/
public static com.afs.rethinkingservice.maidl.MainAidlService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAidlService))) {
return ((com.afs.rethinkingservice.maidl.MainAidlService) iin);
}
return new Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_plus: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.plus(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_toUpperCase: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.toUpperCase(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
static final int TRANSACTION_plus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_toUpperCase = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.afs.rethinkingservice.maidl.MainAidlService impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static MainAidlService getDefaultImpl() {
return Proxy.sDefaultImpl;
}
}
2.2 运用咱们复制的类来完结Binder通讯
依照咱们之前生成binder目标实例的办法,重新修正咱们的MainActivity和MainService的代码,代码如下所示:
public class MainActivity extends AppCompatActivity {
private MainAidlService mBinder;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected() executed");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected() executed");
mBinder = Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_test_aidl_method).setOnClickListener(v -> {
try {
int total = mBinder.plus(1, 1);
Log.d(TAG, "total === " + total);
String newString = mBinder.toUpperCase("aaabbbcccddd");
Log.d(TAG, "newString === " + newString);
} catch (RemoteException e) {
e.printStackTrace();
}
});
}
}
public class MainService extends Service {
public class MainBinder extends Stub {
@Override
public int plus(int a, int b) throws RemoteException {
return a + b;
}
@Override
public String toUpperCase(String str) throws RemoteException {
return str.toUpperCase();
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind() executed");
return new MainBinder();
}
}
2.3 验证成果通讯成果
咱们发动app,然后别离点击绑定服务,测验AIDL中的办法按钮,日志信息如下:
2022-03-31 15:46:16.793 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onCreate() executed
2022-03-31 15:46:16.794 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onCreate() executed Thread id is 2
2022-03-31 15:46:16.794 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onCreate() executed process id is 32638
2022-03-31 15:46:29.837 739-739/com.afs.rethinkingservice03 D/MainService=========: onCreate() executed
2022-03-31 15:46:29.838 739-739/com.afs.rethinkingservice03 D/MainService=========: onCreate() executed Thread id is 2
2022-03-31 15:46:29.838 739-739/com.afs.rethinkingservice03 D/MainService=========: onCreate() executed process id is 739
2022-03-31 15:46:29.838 739-739/com.afs.rethinkingservice03 D/MainService=========: onBind() executed
2022-03-31 15:46:29.843 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onServiceConnected() executed
2022-03-31 15:46:44.757 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: total === 2
2022-03-31 15:46:44.758 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: newString === AAABBBCCCDDD
依据日志信息可知,咱们成功完结了Binder通讯。
这就阐明,AIDL技能只是依照某种规范,主动帮咱们生成了一些类来帮咱们完结Binder通讯,
那么假如咱们不用AIDL技能,能否手动创立相关的类来帮咱们完结Binder通讯呢?
答案当然是能够的,咱们完全能够手动创立相关的类来完结Binder通讯,只不过相比较而言,aidl主动生成这种办法更简单高效。
三、AIDL生成的几个类的效果是什么?
咱们已经完结了Binder通讯,接下来咱们继续来看看这四个类的效果别离是什么。
MainActivity中的代码告知咱们,咱们在和MainService进行通讯的时分,主要是调用了mBinder办法来完结的:
mBinder.plus(1, 1);
mBinder.toUpperCase("aaabbbcccddd");
而Bindder主要是经过Stub.asInterface(service)来赋值的:
private MainAidlService mBinder;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected() executed");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected() executed");
mBinder = Stub.asInterface(service);
}
};
那么咱们就来看看Stub.asInterface究竟做了什么事情:
public abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
public static final java.lang.String DESCRIPTOR = "com.afs.rethinkingservice.maidl.MainAidlService";//**要害点2**
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);//**要害点4**
}
/**
* Cast an IBinder object into an com.afs.rethinkingservice.maidl.MainAidlService interface,
* generating a proxy if needed.
*/
public static com.afs.rethinkingservice.maidl.MainAidlService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//**要害点1**
if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAidlService))) {//**要害点5**
return ((com.afs.rethinkingservice.maidl.MainAidlService) iin);
}
return new Proxy(obj);//**要害点6**
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_plus: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.plus(_arg0, _arg1);//要害点10
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_toUpperCase: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.toUpperCase(_arg0);//要害点10
reply.writeNoException();
reply.writeString(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
}
public class Binder implements IBinder {
//**要害点4**
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
//**要害点3**
public @Nullable
IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
//**要害点9**
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
}
public class Proxy implements com.afs.rethinkingservice.maidl.MainAidlService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {//**要害点7**
mRemote = remote;
}
@Override
public int plus(int a, int b) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(a);
_data.writeInt(b);
boolean _status = mRemote.transact(Stub.TRANSACTION_plus, _data, _reply, 0);//**要害点8**
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;//要害点11
}
@Override
public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(str);
boolean _status = mRemote.transact(Stub.TRANSACTION_toUpperCase, _data, _reply, 0);//**要害点8**
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;//要害点11
}
}
- 1.在Stub.asInterface办法中,当object为null的时分,直接回来null
- 2.调用android.os.IBinder实例目标obj的queryLocalInterface()办法,其中DESCRIPTOR字段其实便是【MainAidlService的包名途径】
- 3.IBinder的queryLocalInterface会判别本身的mDescriptor字段是否等于【MainAidlService的包名途径】,假如等于就回来mOwner,而mOwner其实是在Stub目标的结构办法中,调用attachInterface()进行赋值的,mOwner=本身,mDescriptor=【MainAidlService的包名途径】,而咱们在MainService中创立的MainBinder就承继了Stub,Stub又完结了MainAidlService接口,MainAidlService接口又承继了android.os.IInterface接口。这样android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR),其实获取的便是MainBinder实例目标;
- 4.在要害点5处进行了判别,假如不为空,且完结了MainAidlService接口,就直接回来MainBinder实例目标;这儿之所以做这个判别是因为,当MainService和MainActivity两者处于同一个进程的时分,MainBinder实例目标是能够成功回来的,可是当两者不在同一个进程则会回来失败**
- 5.在要害点6处,当回来MainBinder失败的时分,阐明MainService和MainActivity不在同一个进程,就开端创立Proxy目标,
- 6.而Proxy其实是个署理类,它也完结了MainAidlService接口;别的Proxy的结构办法传入的便是Binder实例目标,然后当咱们调用plus(int a, int b)和toUpperCase(java.lang.String str)办法的时分,在要害点8处,Proxy都会经过调用Binder的transact办法。
- 7.在要害点9,在Binder的transact办法中又会调用onTransact()办法,在要害点10处,咱们复制的Stub类就完结了onTransact(),该办法会匹配相应的办法名,然后调用详细的办法,也便是MainBinder中的办法终究同步走完这段代码,来到要害点11处,成功回来函数调用成果
以上内容总结一句话便是, mBinder = Stub.asInterface(service)这个办法,当MainService和MainActivity两者处于同一个进程的时分,直接回来MainBinder实例目标。 当两者不在同一个进程的时分,会主动创立一个内部持有Binder实例的Proxy署理目标,内部经过Binder来完结进程间办法调用通讯功用
最后咱们再总结一下四个类各自的效果:
- 【MainAidlService】接口类,能够理解为通讯的协议标准,其他三个类都完结了这个接口
- 【Default】类,在低版别SDK编译器,AIDL不会生成这个类,而在高版别SDK编译器中,Aidl会生成这个类,MainAidlService接口的默许完结类。
- 【Stub】抽象类,承继自android.os.Binder并完结了MainAidlService接口,咱们的MainBinder便是承继了它,asInterface()和onTransact() 办法是他的核心。
- 【Proxy】类,完结了MainAidlService接口,长途IPC通讯的详细完结类,内部持有Binder实例目标,调用Binder的transact()办法完结跨进程通讯
四、验证咱们的定论
别离在MainActivity中和Stub中增加日志打印代码:
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity=========";
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected() executed");
mBinder = Stub.asInterface(service);
Log.d(TAG, "mBinder的类型==================" + mBinder.getClass());
}
};
}
public abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
public static final String TAG = "Stub=========";
public static com.afs.rethinkingservice.maidl.MainAidlService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (iin == null) {
Log.d(TAG, "iin的类型==================null");
} else {
Log.d(TAG, "iin的类型==================" + iin.getClass());
}
if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAidlService))) {
return ((com.afs.rethinkingservice.maidl.MainAidlService) iin);
}
return new Proxy(obj);
}
}
4.1 当MainActivity和MainService不在同一个进程的时分:
2022-03-31 17:16:58.440 6389-6389/com.afs.rethinkingservice03 D/MainActivity=========: onServiceConnected() executed
2022-03-31 17:16:58.440 6389-6389/com.afs.rethinkingservice03 D/Stub=========: iin的类型==================null
2022-03-31 17:16:58.440 6389-6389/com.afs.rethinkingservice03 D/MainActivity=========: mBinder的类型==================class com.afs.rethinkingservice.maidl.Proxy
4.2 去掉AndroidManifest中MainService的Process字段,当MainActivity和MainService在同一个进程的时分:
2022-03-31 17:20:26.020 6722-6722/com.afs.rethinkingservice03 D/MainActivity=========: onServiceConnected() executed
2022-03-31 17:20:26.020 6722-6722/com.afs.rethinkingservice03 D/Stub=========: iin的类型==================class com.afs.rethinkingservice.MainService$MainBinder
2022-03-31 17:20:26.021 6722-6722/com.afs.rethinkingservice03 D/MainActivity=========: mBinder的类型==================class com.afs.rethinkingservice.MainService$MainBinder
经过上面的两端日志信息,能够进一步证明咱们的定论: Stub.asInterface(service)这个办法,当MainService和MainActivity两者处于同一个进程的时分,直接回来MainBinder实例目标。 当两者不在同一个进程的时分,会主动创立一个内部持有Binder实例的Proxy署理目标,内部经过Binder来完结进程间办法调用通讯功用