4. 实现并注册一个系统级Binder服务
任务说明
本案例目标是在AIDL接口中传递自定义Parcelable对象,实现跨进程传输复杂数据。我们将创建一个包含用户信息(姓名、年龄、邮箱)的UserInfo对象,通过AIDL接口从客户端发送到服务端,服务端接收后返回处理结果,验证自定义对象能够正确跨进程传输。
实现方案
采用Android标准AIDL+Parcelable机制:定义UserInfo类实现Parcelable接口,创建对应的AIDL文件声明该类型,在服务端AIDL接口方法中接收该对象并返回处理后的字符串。客户端绑定服务后调用接口方法,观察返回结果验证传输成功。
SVG:跨进程对象传递时序
代码实现
1. 定义Parcelable对象 UserInfo.java
package com.example.binderdemo;
import android.os.Parcel;
import android.os.Parcelable;
public class UserInfo implements Parcelable {
private String name;
private int age;
private String email;
public UserInfo(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
protected UserInfo(Parcel in) {
name = in.readString();
age = in.readInt();
email = in.readString();
}
public static final Creator<UserInfo> CREATOR = new Creator<UserInfo>() {
@Override
public UserInfo createFromParcel(Parcel in) {
return new UserInfo(in);
}
@Override
public UserInfo[] newArray(int size) {
return new UserInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeString(email);
}
public String getName() { return name; }
public int getAge() { return age; }
public String getEmail() { return email; }
}
2. 声明AIDL类型 UserInfo.aidl
package com.example.binderdemo;
parcelable UserInfo;
3. 定义AIDL接口 IUserManager.aidl
package com.example.binderdemo;
import com.example.binderdemo.UserInfo;
interface IUserManager {
String processUser(in UserInfo user);
}
4. 服务端实现 UserManagerService.java
package com.example.binderdemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class UserManagerService extends Service {
private static final String TAG = "UserManagerService";
private final IUserManager.Stub binder = new IUserManager.Stub() {
@Override
public String processUser(UserInfo user) {
Log.d(TAG, "收到客户端对象: " + user.getName() + ", " + user.getAge() + ", " + user.getEmail());
// 模拟业务处理:将年龄加1后返回
return "处理完成: " + user.getName() + " 明年" + (user.getAge() + 1) + "岁";
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
5. 客户端调用 MainActivity.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 MainActivity extends AppCompatActivity {
private IUserManager userManager;
private TextView resultText;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
userManager = IUserManager.Stub.asInterface(service);
sendUser();
}
@Override
public void onServiceDisconnected(ComponentName name) {
userManager = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
resultText = findViewById(R.id.result_text);
Intent intent = new Intent(this, UserManagerService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
private void sendUser() {
try {
UserInfo user = new UserInfo("张三", 25, "zhangsan@example.com");
String result = userManager.processUser(user);
resultText.setText(result);
} catch (RemoteException e) {
resultText.setText("调用失败: " + e.getMessage());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}
6. AndroidManifest.xml 注册服务
<service android:name=".UserManagerService"
android:exported="false">
</service>
落地与验证
文件清单:UserInfo.java、UserInfo.aidl、IUserManager.aidl、UserManagerService.java、MainActivity.java、activity_main.xml(含一个id为result_text的TextView)。
构建步骤:将上述文件放入同一Android工程,确保AIDL文件与Java包名一致,编译生成后安装到设备或模拟器。
验证方法:启动应用,观察界面TextView显示内容。若显示“处理完成: 张三 明年26岁”,说明自定义Parcelable对象已成功从客户端跨进程传递到服务端,且服务端正确读取了对象字段并返回处理结果。同时可在Logcat中过滤UserManagerService标签,查看服务端打印的日志确认收到对象数据。
判定标准:界面显示上述预期文本且Logcat出现对应日志,即验证通过。若出现ClassNotFoundException或TransactionTooLargeException,需检查AIDL声明与Parcelable实现是否匹配。