Android Binder 用法详解
Binder 是 Android 系统中的一种进程间通信(IPC)机制,它允许不同进程之间进行高效通信。Binder 在 Android 系统中被广泛使用,例如在 Activity 与 Service 的交互中。
Binder 的基本组成
实现 Binder 通信通常包含以下几个关键部分:
- AIDL 接口定义:通过 Android Interface Definition Language 定义接口
- 服务端实现:实现 AIDL 接口并在 Service 中提供服务
- 客户端调用:绑定服务并调用远程方法
下面通过一个完整的示例来展示 Binder 的使用方法。
示例:创建一个计算器服务
第一步:定义 AIDL 接口
创建文件 ICalculator.aidl:
// ICalculator.aidl package com.example.binderexample; interface ICalculator { int add(int a, int b); int subtract(int a, int b); int multiply(int a, int b); int divide(int a, int b); }
第二步:创建服务端 Service
// CalculatorService.java package com.example.binderexample; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class CalculatorService extends Service { private static final String TAG = "CalculatorService"; // Binder 实现 private final ICalculator.Stub mBinder = new ICalculator.Stub() { @Override public int add(int a, int b) throws RemoteException { Log.d(TAG, "add() called with: a = [" + a + "], b = [" + b + "]"); return a + b; } @Override public int subtract(int a, int b) throws RemoteException { Log.d(TAG, "subtract() called with: a = [" + a + "], b = [" + b + "]"); return a - b; } @Override public int multiply(int a, int b) throws RemoteException { Log.d(TAG, "multiply() called with: a = [" + a + "], b = [" + b + "]"); return a * b; } @Override public int divide(int a, int b) throws RemoteException { Log.d(TAG, "divide() called with: a = [" + a + "], b = [" + b + "]"); if (b == 0) { throw new RemoteException("Division by zero"); } return a / b; } }; @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind: Service bound"); return mBinder; } }
第三步:在 AndroidManifest.xml 中注册服务
第四步:客户端实现
// MainActivity.java package com.example.binderexample; 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.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private EditText mNum1EditText, mNum2EditText; private TextView mResultTextView; private Button mAddButton, mSubtractButton, mMultiplyButton, mDivideButton; private ICalculator mCalculator; private boolean mBound = false; // 服务连接对象 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mCalculator = ICalculator.Stub.asInterface(service); mBound = true; Log.d(TAG, "onServiceConnected: Service connected"); Toast.makeText(MainActivity.this, "Calculator Service Connected", Toast.LENGTH_SHORT).show(); } @Override public void onServiceDisconnected(ComponentName name) { mCalculator = null; mBound = false; Log.d(TAG, "onServiceDisconnected: Service disconnected"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化 UI 组件 mNum1EditText = findViewById(R.id.editText_num1); mNum2EditText = findViewById(R.id.editText_num2); mResultTextView = findViewById(R.id.textView_result); mAddButton = findViewById(R.id.button_add); mSubtractButton = findViewById(R.id.button_subtract); mMultiplyButton = findViewById(R.id.button_multiply); mDivideButton = findViewById(R.id.button_divide); // 添加按钮点击事件 mAddButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { performOperation("add"); } }); mSubtractButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { performOperation("subtract"); } }); mMultiplyButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { performOperation("multiply"); } }); mDivideButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { performOperation("divide"); } }); } private void performOperation(String operation) { if (!mBound) { Toast.makeText(this, "Service not bound", Toast.LENGTH_SHORT).show(); return; } try { // 获取输入值 int num1 = Integer.parseInt(mNum1EditText.getText().toString()); int num2 = Integer.parseInt(mNum2EditText.getText().toString()); int result = 0; // 执行远程操作 switch (operation) { case "add": result = mCalculator.add(num1, num2); break; case "subtract": result = mCalculator.subtract(num1, num2); break; case "multiply": result = mCalculator.multiply(num1, num2); break; case "divide": result = mCalculator.divide(num1, num2); break; } // 显示结果 mResultTextView.setText("结果: " + result); } catch (RemoteException e) { Log.e(TAG, "RemoteException: " + e.getMessage()); Toast.makeText(this, "Remote exception: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } catch (NumberFormatException e) { Toast.makeText(this, "Please enter valid numbers", Toast.LENGTH_SHORT).show(); } } @Override protected void onStart() { super.onStart(); // 绑定服务 Intent intent = new Intent(); intent.setAction("com.example.binderexample.ICalculator"); intent.setPackage(getPackageName()); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // 解绑服务 if (mBound) { unbindService(mConnection); mBound = false; } } }
第五步:布局文件
Binder 工作原理解释
-
AIDL 编译:编译时,Android 工具会根据 AIDL 文件生成相应的 Java 接口,其中包含一个内部抽象类 Stub,继承自 Binder 并实现了该接口
-
Stub 类:
- 服务端继承并实现 Stub 类的抽象方法
- Stub 类拥有 asInterface() 静态方法,用于将 IBinder 转换为接口类型
-
通信过程:
- 客户端调用 bindService() 绑定服务
- 服务端返回 Binder 对象
- 客户端通过 Stub.asInterface() 将 Binder 对象转换为接口
- 客户端调用接口方法,实际上是通过 Binder 驱动进行跨进程通信
高级用法:传输复杂对象
如果需要传输复杂对象,需要实现 Parcelable 接口:
// Person.java package com.example.binderexample; import android.os.Parcel; import android.os.Parcelable; public class Person implements Parcelable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } protected Person(Parcel in) { name = in.readString(); age = in.readInt(); } public String getName() { return name; } public int getAge() { return age; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } @Override public int describeContents() { return 0; } public static final Creator CREATOR = new Creator() { @Override public Person createFromParcel(Parcel in) { return new Person(in); } @Override public Person[] newArray(int size) { return new Person[size]; } }; }
然后在 AIDL 文件中引用这个类:
// Person.aidl package com.example.binderexample; parcelable Person;
// IPersonService.aidl package com.example.binderexample; import com.example.binderexample.Person; interface IPersonService { void addPerson(in Person person); List getAllPersons(); }
Android C++ 中的 Binder 使用
在 Android C++ 层也可以使用 Binder 进行进程间通信。实际上,Android 框架中的核心 Binder 实现就是用 C++ 编写的,位于 native 层。C++ 中的 Binder 框架是 Java Binder 框架的基础。
Android Native Binder 主要组件
在 C++ 层使用 Binder 主要涉及以下几个关键类:
- IBinder:表示一个 Binder 对象的基类
- BpBinder:代理端的 Binder 实现(客户端)
- BBinder:本地端的 Binder 实现(服务端)
- BnInterface:服务端接口模板类
- BpInterface:客户端接口模板类
- IInterface:Binder 接口的基类
- ProcessState:管理进程的 Binder 状态
- IPCThreadState:管理线程的 Binder 状态
C++ Binder 实现示例
下面是一个完整的 C++ Binder 示例,包括服务端和客户端。
第一步:定义接口
首先,我们需要定义一个计算器服务的接口:
// ICalculator.h #ifndef ICALCULATOR_H #define ICALCULATOR_H #include #include namespace android { // 接口标识符 enum { CALCULATOR_ADD = IBinder::FIRST_CALL_TRANSACTION, CALCULATOR_SUBTRACT, CALCULATOR_MULTIPLY, CALCULATOR_DIVIDE }; // 接口定义 class ICalculator : public IInterface { public: DECLARE_META_INTERFACE(Calculator); // 声明接口元信息 // 纯虚函数,需要子类实现 virtual int32_t add(int32_t a, int32_t b) = 0; virtual int32_t subtract(int32_t a, int32_t b) = 0; virtual int32_t multiply(int32_t a, int32_t b) = 0; virtual int32_t divide(int32_t a, int32_t b) = 0; }; // 服务端接口 class BnCalculator : public BnInterface { public: // onTransact 函数处理来自客户端的请求 virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); }; } // namespace android #endif // ICALCULATOR_H
第二步:实现接口
接下来,我们需要实现这个接口:
// ICalculator.cpp #include "ICalculator.h" namespace android { // 实现元接口宏 IMPLEMENT_META_INTERFACE(Calculator, "android.calculator.ICalculator"); // 处理远程调用请求 status_t BnCalculator::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case CALCULATOR_ADD: { CHECK_INTERFACE(ICalculator, data, reply); int32_t a = data.readInt32(); int32_t b = data.readInt32(); int32_t result = add(a, b); reply->writeInt32(result); return NO_ERROR; } case CALCULATOR_SUBTRACT: { CHECK_INTERFACE(ICalculator, data, reply); int32_t a = data.readInt32(); int32_t b = data.readInt32(); int32_t result = subtract(a, b); reply->writeInt32(result); return NO_ERROR; } case CALCULATOR_MULTIPLY: { CHECK_INTERFACE(ICalculator, data, reply); int32_t a = data.readInt32(); int32_t b = data.readInt32(); int32_t result = multiply(a, b); reply->writeInt32(result); return NO_ERROR; } case CALCULATOR_DIVIDE: { CHECK_INTERFACE(ICalculator, data, reply); int32_t a = data.readInt32(); int32_t b = data.readInt32(); if (b == 0) { return BAD_VALUE; // 除数为零错误 } int32_t result = divide(a, b); reply->writeInt32(result); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } } // 客户端代理实现 class BpCalculator : public BpInterface { public: BpCalculator(const sp& impl) : BpInterface(impl) {} virtual int32_t add(int32_t a, int32_t b) { Parcel data, reply; data.writeInterfaceToken(ICalculator::getInterfaceDescriptor()); data.writeInt32(a); data.writeInt32(b); remote()->transact(CALCULATOR_ADD, data, &reply); return reply.readInt32(); } virtual int32_t subtract(int32_t a, int32_t b) { Parcel data, reply; data.writeInterfaceToken(ICalculator::getInterfaceDescriptor()); data.writeInt32(a); data.writeInt32(b); remote()->transact(CALCULATOR_SUBTRACT, data, &reply); return reply.readInt32(); } virtual int32_t multiply(int32_t a, int32_t b) { Parcel data, reply; data.writeInterfaceToken(ICalculator::getInterfaceDescriptor()); data.writeInt32(a); data.writeInt32(b); remote()->transact(CALCULATOR_MULTIPLY, data, &reply); return reply.readInt32(); } virtual int32_t divide(int32_t a, int32_t b) { Parcel data, reply; data.writeInterfaceToken(ICalculator::getInterfaceDescriptor()); data.writeInt32(a); data.writeInt32(b); status_t status = remote()->transact(CALCULATOR_DIVIDE, data, &reply); if (status != NO_ERROR) { return -1; // 错误处理 } return reply.readInt32(); } }; } // namespace android
第三步:实现服务端
服务端需要实现 ICalculator 接口,并提供一个服务:
(图片来源网络,侵删)
// CalculatorService.h #ifndef CALCULATOR_SERVICE_H #define CALCULATOR_SERVICE_H #include "ICalculator.h" namespace android { class CalculatorService : public BnCalculator { public: static void instantiate(); // 用于注册服务 // 实现ICalculator接口的方法 virtual int32_t add(int32_t a, int32_t b); virtual int32_t subtract(int32_t a, int32_t b); virtual int32_t multiply(int32_t a, int32_t b); virtual int32_t divide(int32_t a, int32_t b); }; } // namespace android #endif // CALCULATOR_SERVICE_H
// CalculatorService.cpp #include "CalculatorService.h" #include #include namespace android { void CalculatorService::instantiate() { sp sm = defaultServiceManager(); sm->addService(String16("calculator"), new CalculatorService()); ALOGI("Calculator service started"); } int32_t CalculatorService::add(int32_t a, int32_t b) { ALOGI("add() called with: a = %d, b = %d", a, b); return a + b; } int32_t CalculatorService::subtract(int32_t a, int32_t b) { ALOGI("subtract() called with: a = %d, b = %d", a, b); return a - b; } int32_t CalculatorService::multiply(int32_t a, int32_t b) { ALOGI("multiply() called with: a = %d, b = %d", a, b); return a * b; } int32_t CalculatorService::divide(int32_t a, int32_t b) { ALOGI("divide() called with: a = %d, b = %d", a, b); return a / b; } } // namespace android
第四步:服务端主程序
编写服务端主程序,用于启动服务:
// server_main.cpp #include #include #include #include "CalculatorService.h" using namespace android; int main() { sp proc(ProcessState::self()); // 实例化并注册服务 CalculatorService::instantiate(); // 启动线程池处理请求 ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return 0; }
第五步:客户端实现
客户端程序示例:
(图片来源网络,侵删)
// client_main.cpp #include #include #include #include "ICalculator.h" using namespace android; using namespace std; int main() { sp sm = defaultServiceManager(); // 获取计算器服务 sp binder = sm->getService(String16("calculator")); if (binder == nullptr) { ALOGE("Failed to get calculator service"); return -1; } // 创建代理对象 sp calculator = interface_cast(binder); // 使用计算器服务 int a = 10, b = 5; cout static { System.loadLibrary("nativebinderhelper"); } // 本地方法声明 public static native int addNumbers(int a, int b); public static native int subtractNumbers(int a, int b); } sp return -1; } sp sp return -1; } sp
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。