3. 实现跨进程加法服务
任务说明
本案例需要完成一个可独立运行的跨进程加法服务:服务端通过AIDL定义加法接口并实现为Service,客户端绑定该Service后远程调用加法方法并获取结果。整个链路包含AIDL接口定义、服务端实现、客户端调用三个部分,全部代码在本案例内给出。
AIDL接口定义
首先创建AIDL文件,声明加法运算的远程接口。该接口只有一个方法add,接收两个整数参数,返回它们的和。
// IAddService.aidl
package com.example.binderdemo;
interface IAddService {
int add(int a, int b);
}
服务端实现
服务端是一个继承Service的组件,在onBind中返回AIDL接口的Stub实现。加法逻辑直接在Binder线程池中执行,无需额外处理线程同步。
// AddService.java
package com.example.binderdemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class AddService extends Service {
private static final String TAG = "AddService";
private final IAddService.Stub mBinder = new IAddService.Stub() {
@Override
public int add(int a, int b) {
int result = a + b;
Log.d(TAG, "add(" + a + ", " + b + ") = " + result);
return result;
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
客户端调用
客户端通过bindService绑定服务端,在ServiceConnection回调中获取IAddService代理对象,然后调用add方法。由于Binder调用是同步的,这里在子线程中执行以避免阻塞主线程。
// ClientActivity.java(关键代码)
package com.example.binderdemo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class ClientActivity extends AppCompatActivity {
private IAddService mAddService;
private TextView mResultText;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mAddService = IAddService.Stub.asInterface(service);
// 在子线程中执行远程调用
new Thread(() -> {
try {
int result = mAddService.add(3, 5);
runOnUiThread(() -> mResultText.setText("3 + 5 = " + result));
} catch (RemoteException e) {
e.printStackTrace();
}
}).start();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mAddService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
mResultText = findViewById(R.id.result_text);
Intent intent = new Intent(this, AddService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConnection);
}
}
AndroidManifest配置
服务端需要在Manifest中注册,并声明exported="true"以允许其他应用(或同应用不同进程)绑定。若仅在同一应用内跨进程使用,可省略权限声明。
<service android:name=".AddService"
android:exported="true" />
跨进程验证配置
为了验证真正的跨进程调用,需要在Manifest中为客户端Activity所在进程与服务端Service配置不同的android:process属性。例如:
<service android:name=".AddService"
android:exported="true"
android:process=":remote" />
这样AddService运行在独立的:remote进程中,客户端Activity运行在主进程,从而构成真实的Binder跨进程通信。
SVG:跨进程加法调用时序
验证方法与判定标准
运行步骤:
- 将上述代码分别放入对应文件,确保AIDL文件在
src/main/aidl/com/example/binderdemo/目录下; - 构建并安装应用到两台设备(或使用模拟器与adb),或同一设备上通过
android:process=":remote"实现双进程; - 启动
ClientActivity,观察界面显示的运算结果。
判定标准:
- 客户端界面显示“3 + 5 = 8”,说明远程调用成功返回;
- 通过
adb shell ps可看到两个进程(主进程与:remote进程),证明调用确实跨进程; - Logcat中过滤
AddService标签,能看到add(3, 5) = 8的日志,表明服务端确实执行了加法逻辑。
满足以上三点即可判定案例通过。若界面无结果或崩溃,检查Manifest中Service的进程配置、AIDL包名是否一致,以及客户端是否在子线程中执行了Binder调用。