Android 应用 A 通过 aidl 主动向应用 B 发送数据示例
通过在应用A中定义AIDL接口实现跨应用数据传输。这是Android标准的IPC通信方式,特别适合一对多的消息推送场景。以下是完整的实现方案:
一、应用A(服务端)实现步骤
1. 定义AIDL接口
创建IDataTransfer.aidl
文件:
// app/src/main/aidl/com/example/appa/IDataTransfer.aidl
package com.example.appa;
import com.example.appa.IDataListener;
interface IDataTransfer {
void registerListener(in IDataListener listener);
void unregisterListener(in IDataListener listener);
void sendData(in String message);
}
创建IDataListener.aidl
文件:
// app/src/main/aidl/com/example/appa/IDataListener.aidl
package com.example.appa;
interface IDataListener {
void onDataReceived(String data);
}
2. 实现Service
// DataTransferService.java
public class DataTransferService extends Service {
private final RemoteCallbackList<IDataListener> mListeners = new RemoteCallbackList<>();
private final IDataTransfer.Stub mBinder = new IDataTransfer.Stub() {
@Override
public void registerListener(IDataListener listener) {
mListeners.register(listener);
}
@Override
public void unregisterListener(IDataListener listener) {
mListeners.unregister(listener);
}
@Override
public void sendData(String message) {
final int N = mListeners.beginBroadcast();
for (int i = 0; i < N; i++) {
try {
mListeners.getBroadcastItem(i).onDataReceived(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mListeners.finishBroadcast();
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
3. 声明Service(AndroidManifest.xml)
不带权限校验
<service
android:name=".DataTransferService"
android:exported="true"">
<intent-filter>
<action android:name="com.example.appa.DATA_SERVICE"/>
</intent-filter>
</service>
带权限校验
<service
android:name=".DataTransferService"
android:exported="true"
android:permission="com.example.appa.PERMISSION">
<intent-filter>
<action android:name="com.example.appa.DATA_SERVICE"/>
</intent-filter>
</service>
<permission
android:name="com.example.appa.PERMISSION"
android:protectionLevel="normal"/>
4. 发送数据示例
// 在Activity/Fragment中
IDataTransfer mService;
ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IDataTransfer.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
void sendMessage(String msg) {
try {
mService.sendData(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
5. 开启aidl配置
在 app
模块的 bulid.gradle
文件添加如下代码:
android {
buildFeatures {
aidl true
}
}
二、应用B(客户端)实现步骤
1. 复制AIDL文件
将应用A的IDataTransfer.aidl
和IDataListener.aidl
文件(包路径保持一致)复制到客户端工程
2. 绑定服务并接收数据
public class ClientActivity extends AppCompatActivity {
private IDataTransfer mService;
private boolean mIsBound;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = IDataTransfer.Stub.asInterface(service);
try {
mService.registerListener(mListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
}
};
private IDataListener mListener = new IDataListener.Stub() {
@Override
public void onDataReceived(String data) {
runOnUiThread(() -> {
TextView tv = findViewById(R.id.tv_received);
tv.setText("Received: " + data);
});
}
};
void bindService() {
Intent intent = new Intent("com.example.appa.DATA_SERVICE");
intent.setPackage("com.example.appa");
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindService();
}
@Override
protected void onDestroy() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
super.onDestroy();
}
}
3. 添加权限声明(如果需要)
<uses-permission android:name="com.example.appa.PERMISSION"/>
4. Android 11 以上版本适配
在高版本Android设备上,需要在 AndroidManifest.xml 中声明 queries 元素,指定目标应用的包名或意图过滤器。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<queries>
<package android:name="com.example.appa" />
<intent>
<action android:name="com.example.appa.DATA_SERVICE" />
</intent>
</queries>
</manifest>
5. 开启aidl配置
在 app
模块的 bulid.gradle
文件添加如下代码:
android {
buildFeatures {
aidl true
}
}
三、高级配置建议
1. 数据传输优化
// 传递复杂数据时使用Parcelable
parcelable MyData;
interface IDataTransfer {
void sendComplexData(in MyData data);
}
2. 安全增强
// 服务端校验调用方签名
@Override
public IBinder onBind(Intent intent) {
if (!checkCallingSignature()) {
return null;
}
return mBinder;
}
private boolean checkCallingSignature() {
PackageManager pm = getPackageManager();
String packageName = getCallingPackage();
PackageInfo packageInfo = pm.getPackageInfo(packageName,
PackageManager.GET_SIGNATURES);
// 校验签名是否匹配
return true;
}
3. 多进程消息分发优化
// 使用CopyOnWriteArrayList处理并发
private final CopyOnWriteArrayList<IDataListener> mListenerList =
new CopyOnWriteArrayList<>();
void sendData(String message) {
for (IDataListener listener : mListenerList) {
try {
listener.onDataReceived(message);
} catch (RemoteException e) {
mListenerList.remove(listener);
}
}
}
四、工作原理示意图
[App A Service]
↑ 绑定
[App B] [App C] ... → 通过AIDL接口注册监听器
↓ 数据广播
App A调用sendData → 遍历所有监听器 → 触发各客户端的onDataReceived
五、常见问题解决
-
ClassCastException:
- 确保所有客户端使用完全相同的AIDL文件(包名+内容)
-
TransactionTooLargeException:
- 单次传输数据不要超过1MB
- 大数据建议分片传输或改用文件共享
-
服务绑定失败:
- 检查客户端是否声明了正确权限
- 确认服务端应用的签名与权限配置匹配
以上方案可实现安全可靠的跨应用实时通信,建议配合广播或ContentProvider实现离线消息的持久化存储。