当前位置: 首页 > news >正文

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.aidlIDataListener.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

五、常见问题解决

  1. ClassCastException

    • 确保所有客户端使用完全相同的AIDL文件(包名+内容)
  2. TransactionTooLargeException

    • 单次传输数据不要超过1MB
    • 大数据建议分片传输或改用文件共享
  3. 服务绑定失败

    • 检查客户端是否声明了正确权限
    • 确认服务端应用的签名与权限配置匹配

以上方案可实现安全可靠的跨应用实时通信,建议配合广播或ContentProvider实现离线消息的持久化存储。

相关文章:

  • 学习next.js的同时的一些英语单词记录
  • Rust编程语言入门教程(一)安装Rust
  • 啥是CTF?新手如何入门CTF?网络安全零基础入门到精通实战教程!
  • 大数据 高并发 解决方案 Moebius
  • [c语言日寄]指针进阶:函数指针数组——转换表
  • FFmpeg 源码编译安装
  • 基于微信小程序的民宿短租系统设计与实现(ssm论文源码调试讲解)
  • 【C】栈的应用
  • javaweb + AI day 02
  • 用deepseek学大模型08-长短时记忆网络 (LSTM)
  • Linux 新建用户和组命令全解析
  • linux查看程序占用的本地端口
  • 【Hugging Face系列篇】01初步介绍:“AI界的GitHub”
  • Java 基础面试
  • Vue_vue2/vue3无缝滚动效果
  • Discuz! X3.5 根目录权限设置
  • java每日精进 2.13 MySql迁移人大金仓
  • 【Java】泛型与集合篇 —— Set 接口
  • RT-Thread+STM32L475VET6实现红外遥控实验
  • 开题报告——基于Spring Boot的垃圾分类预约回收系统
  • 化学家、台湾地区“中研院”原学术副院长陈长谦逝世
  • 黄晨光任中科院空间应用工程与技术中心党委书记、副主任
  • 外交部:应美方请求举行贸易代表会谈,中方反对美滥施关税立场没有变化
  • 印度袭击巴基斯坦已致至少3人死亡
  • 文旅部:加强对景区索道、游船等设施设备安全隐患排查整治
  • 践行自由贸易主义理念,加快区域合作进程