创建Binder简单项目(完整代码)
手把手带你实现一个基于AIDL的简单Binder项目,附上完整代码,容易复现
今天学习了Android Binder相关的内容,发现大部分博客聚焦于讲原理,少有文章详细讲解怎么写代码。本文主要提供一个简单的Binder的例程,手把手展示整个项目的创建流程,所有完整代码均提供复制粘贴,尽可能帮助Android新手复现成功。
在进行项目创建之前,建议最好简单了解一下Binder的流程,不需要太深入原理,因为学知识要由浅到深。在学习完Binder流程后,通过这个简单项目你可以加深理解,然后再去深入原理会更轻松。
废话有点多了,下面开始吧。
1、新建一个空项目,然后在main文件夹下new一个aidl,发现new不了。这个提示说明你需要在项目的构建配置中启用 AIDL 支持。在现代 Android 项目中,AIDL 默认是不启用的,需要手动配置。
2、在app/build.gradle中添加如下代码,表示支持aidl配置
3、现在重新在main下面新建一个aidl,我这边命名为ICalculator,自动生成文件如下
4、系统会自动生成一个basicType方法(用于测试基本数据类型传递),我把这个方法删除掉,不然后面Stub类中这个方法也需要被实现。在上面的aidl中定义Service中的调用接口,我这边以加法、减法函数为例
// ICalculator.aidl
package com.example.binderdemo;
// Declare any non-default types here with import statements
interface ICalculator {
// 定义加法方法
int add(int a, int b);
// 定义减法方法
int subtract(int a, int b);
}
5、点击菜单栏的Build->Make Project,让系统生成AIDL对应的Java文件。自动生成的Java文件在下图的路径中,发现真实的ICalculator非常复杂,而AIDL就是帮我们简化这个步骤的。
6、然后创建一个CalculatorService.java。在这里面创建Binder对象以及实现我们定义的AIDL接口中加法和减法的方法
//CalculatorService.java
package com.example.binderdemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
// 服务端Service,实现我们定义的AIDL接口
public class CalculatorService extends Service {
private static final String TAG = "BinderDemo";
// 创建Binder对象,实现AIDL接口定义的方法
private final ICalculator.Stub mBinder = new ICalculator.Stub() {
@Override
public int add(int a, int b) throws RemoteException {
// 打印当前处理请求的线程信息,验证Binder线程池
Log.d(TAG, "add() called in thread: " + Thread.currentThread().getName());
return a + b;
}
@Override
public int subtract(int a, int b) throws RemoteException {
// 打印当前处理请求的线程信息,验证Binder线程池
Log.d(TAG, "subtract() called in thread: " + Thread.currentThread().getName());
return a - b;
}
};
@Override
public void onCreate() {
super.onCreate();
// 打印服务所在进程ID
Log.d(TAG, "CalculatorService onCreate, PID: " + android.os.Process.myPid());
}
@Override
public IBinder onBind(Intent intent) {
// 返回Binder对象,供客户端绑定
return mBinder;
}
}
7、我这边把Service和Client放在同一个应用中,它们是在同一个进程中的,为了测试Binder的跨进程通信功能,在manifest文件中将CalculatorService配置为运行在独立线程
android:process="com.example.binderdemo.remote"
8、然后修改客户端的界面布局,activity_main.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"
android:padding="16dp"
android:gravity="center">
<EditText
android:id="@+id/et_num1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入第一个数字"
android:inputType="number" />
<EditText
android:id="@+id/et_num2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="输入第二个数字"
android:inputType="number" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button
android:id="@+id/btn_add"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="加" />
<Button
android:id="@+id/btn_subtract"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="减" />
</LinearLayout>
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textSize="18sp"
android:textAlignment="center"
android:text="结果将显示在这里" />
</LinearLayout>
9、最后,编写客户端MainActivity的代码如下,具体分析在代码注释中
package com.example.binderdemo;
import androidx.appcompat.app.AppCompatActivity;
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.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
// 客户端Activity,负责绑定服务并调用远程方法
public class MainActivity extends AppCompatActivity {
private static final String TAG = "BinderDemo";
// AIDL接口实例,用于调用远程方法
private ICalculator mCalculator;
// 界面元素
private EditText mNum1EditText;
private EditText mNum2EditText;
private TextView mResultTextView;
// 服务连接对象,用于绑定服务
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 绑定成功,获取AIDL接口实例
mCalculator = ICalculator.Stub.asInterface(service);
Log.d(TAG, "服务绑定成功");
}
@Override
public void onServiceDisconnected(ComponentName name) {
// 服务断开连接
mCalculator = null;
Log.d(TAG, "服务断开连接");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 打印客户端进程ID
Log.d(TAG, "MainActivity onCreate, PID: " + android.os.Process.myPid());
// 初始化界面元素
mNum1EditText = findViewById(R.id.et_num1);
mNum2EditText = findViewById(R.id.et_num2);
mResultTextView = findViewById(R.id.tv_result);
Button addButton = findViewById(R.id.btn_add);
Button subtractButton = findViewById(R.id.btn_subtract);
// 绑定服务
Intent intent = new Intent(this, CalculatorService.class);
bindService(intent, mConnection, BIND_AUTO_CREATE);
// 加法按钮点击事件
addButton.setOnClickListener(v -> calculate('+'));
// 减法按钮点击事件
subtractButton.setOnClickListener(v -> calculate('-'));
}
// 执行计算操作
private void calculate(char operation) {
// 检查是否已绑定服务
if (mCalculator == null) {
mResultTextView.setText("服务未连接");
return;
}
try {
// 获取输入的数字
int num1 = Integer.parseInt(mNum1EditText.getText().toString());
int num2 = Integer.parseInt(mNum2EditText.getText().toString());
int result = 0;
// 根据操作类型调用不同的远程方法
switch (operation) {
case '+':
result = mCalculator.add(num1, num2);
break;
case '-':
result = mCalculator.subtract(num1, num2);
break;
}
// 显示结果
mResultTextView.setText(String.valueOf(result));
} catch (NumberFormatException e) {
mResultTextView.setText("请输入有效的数字");
} catch (RemoteException e) {
mResultTextView.setText("远程调用失败");
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 解绑服务
unbindService(mConnection);
}
}
然后就可以运行了!!!如果我的文章帮助到你,就点点赞和收藏吧
更多推荐
所有评论(0)