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

Android中使用AIDL实现进程通信

前言

关于使用AIDL实现两个APP(跨进程)通信,我们通常把两个APP分别叫做服务端和客户端。本文不讲原理,只给最简易的案例。

一、服务端APP实现

1. 在src/main/aidl目录下新建一个.aidl文件,然后在.aidl文件中定义需要开放的接口,如下:在这里插入图片描述

package com.test.aidl;

import com.test.aidl.ActionCallback;

interface OpenData {

    void cycleData(String linData);

    boolean handshake(int cmdNumber);

    void listenerData(ActionCallback actionCallback);

}
package com.test.aidl;

interface ActionCallback {

    void callback(String jsonData);

}

2. 点击工具栏Bulid模块中的Make Project时,会在build目录下生成编译文件,如下所示:

在这里插入图片描述
值得注意的是,编译出来的文件中,默认增加了一个stub内部类,这个stub类是Binder的子类,如下所示:
在这里插入图片描述

3.定义一个Service,然后把上一步的Stub类实例化,把Stub的对象return给Service的onBind方法,如下所示:

package com.test.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.test.aidl.ActionCallback;
import com.test.aidl.OpenData;

public class ListenerService extends Service {

    private static final int NOTIFICATION_ID = 1;
    private final OpenData.Stub binder = new OpenData.Stub() {
        @Override
        public void cycleData(String linData) throws RemoteException {
            Log.e("MyAidlData", "------------------cycleData---------------------");
            Log.e("MyAidlData", "Data=" + linData);
        }

        @Override
        public boolean handshake(int cmdNumber) throws RemoteException {
            Log.e("MyAidlData", "------------------handshake---------------------");
            Log.e("MyAidlData", "Data=" + cmdNumber);
            return true;
        }

        @Override
        public void listenerData(ActionCallback actionCallback) throws RemoteException {
            Log.e("MyAidlData", "------------------listenerData---------------------");
            if (actionCallback == null) {
                Log.e("MyAidlData", "Data=无效监听");
                try {
                    actionCallback.callback("无效监听");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            } else {
                Log.e("MyAidlData", "Data=监听成功");
                try {
                    actionCallback.callback("监听成功");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }


}

注意:Service需要再AndroidManifest.xml中注册,并增加相关属性的申明,如下:

<service
  android:name="com.test.server.ListenerService"
  android:exported="true"><!--条件测试7————必须为true-->

  <!--隐式启动:当有匹配<intent-filter>的意图发送时,系统可能会根据定义的过滤规则选择合适的服务进行启动。这种方式依赖于是否有其他组件发送了符合过滤条件的意图。-->
  <intent-filter>
      <!--条件测试6————必须要与客户端的action一致-->
      <action android:name="AAaaBB"/>
  </intent-filter>
</service>

二、客户端APP实现

1. 在src/main/aidl目录下新建一个.aidl文件,然后在.aidl文件中定义需要开放的接口代码,如下:

特别注意:这里的【.aidl文件内容】和【文件路径】必须和服务端APP完全一致。

在这里插入图片描述

2. 在客户端APP的AndroidManifest.xml文件中增加必须的权限:

<!--条件测试3————必须-->
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />

3. 封装一个AIDL客户端管理类,如下:

package com.test.client;

import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.test.aidl.ActionCallback;
import com.test.aidl.OpenData;

public class AIDLClient {

    private AIDLClient() {
    }

    private static class Holder{
        public static final AIDLClient INSTANCE=new AIDLClient();
    }

    public static AIDLClient getInstance(){
        return Holder.INSTANCE;
    }

    private OpenData openData;
    private ServiceConnection connection;

    /**
     * 1.初始化服务连接
     */
    public void initConnection(){
        connection = new ServiceConnection() {
            public void onServiceConnected(ComponentName className, IBinder service) {
                openData = OpenData.Stub.asInterface(service);
                Log.d("初始化链接", "连接成功");
            }

            public void onServiceDisconnected(ComponentName className) {
                openData = null;
                Log.d("初始化链接", "连接断开");
            }
        };
    }

    /**
     * 2.获取链接
     * @return
     */
    public ServiceConnection getConnection() {
        return connection;
    }

    //Tx (分享出去的数据)___________________________________________________________________
    public boolean sendCycleData(String cycleData){
        try {
            if (openData!=null){
                openData.cycleData(cycleData);
                return true;
            }else {
                return false;
            }
        } catch (RemoteException e) {
            Log.e("AIDL链接异常",e.toString());
            return false;
        }
    }

    public boolean sendHandShake(int number){
        try {
            if (openData!=null){
                openData.handshake(number);
                return true;
            }else {
                return false;
            }
        } catch (RemoteException e) {
            Log.e("AIDL链接异常",e.toString());
            return false;
        }
    }

    //Rx (接收服务端发来的数据————回调方式实现)______________________________________________________

    public boolean registerListener(){
        try {
            if (openData!=null){
                //这里new MyCall()后期可以把MyCall也变成单例可能更适合(看需求)
                openData.listenerData(new MyCall());
                return true;
            }else {
                return false;
            }
        } catch (RemoteException e) {
            Log.e("AIDL链接异常",e.toString());
            return false;
        }
    }

    private class MyCall extends ActionCallback.Stub{
        @Override
        public void callback(String jsonData) throws RemoteException {
            Log.e("绑定服务","回调数据="+jsonData);
        }
    }

}

4. 把客户端绑定到服务端去,并发送数据,代码如下:

package com.test.client;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //第一步:初始化
        AIDLClient.getInstance().initConnection();

        //第二步:绑定服务
        Intent intent = new Intent();
        intent.setAction("AAaaBB");//条件测试6————必须与服务端指定的service的name一致
        intent.setPackage("com.test.aidltest1");//这个包名必须写服务端APP的包名
        boolean re=bindService(intent, AIDLClient.getInstance().getConnection(), Context.BIND_AUTO_CREATE);
        Log.e("绑定服务",re ? "成功":"失败");

        //第三步:发送数据
        findViewById(R.id.startSend1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AIDLClient.getInstance().sendCycleData("哈哈哈哈");
            }
        });

        findViewById(R.id.startSend2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AIDLClient.getInstance().sendHandShake(666);
            }
        });

        findViewById(R.id.startSend3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AIDLClient.getInstance().registerListener();
            }
        });

    }
}

有问题,评论区见!


http://www.kler.cn/a/457625.html

相关文章:

  • 【记录】Angr|Angr 标准库函数替换怎么看哪些库函数被Angr支持?
  • [CTF/网络安全] 攻防世界 simple_php 解题详析
  • 数字PWM直流调速系统设计(论文+源码)
  • Spring 核心技术解析【纯干货版】- IV:Spring 切面编程模块 Spring-Aop 模块精讲
  • 注入少量可学习的向量参数: 注入适配器IA3
  • 生态碳汇涡度相关监测与通量数据分析实践技术应用
  • ArrayList和LinkedList的区别、优缺点与使用场景
  • 生产力利器,Mac 系统优选,keychron K10Max 三模键盘体验分享
  • QT-------认识QT
  • 呼叫中心中间件免费体验测试和freeswitch部署方案
  • Linux CPU调度算法
  • 领克Z20结合AI技术,革新自动驾驶辅助系统
  • 无需配置设备,借助GitHub快速编译项目并直接运行!
  • 更新本地 specs 仓库时,出现 SSL 证书验证失败错误 临时解决方案
  • GSM PDU解码在Linux下的C语言实现
  • [oeasy]python055_python编程_容易出现的问题_函数名的重新赋值_print_int
  • ARM64 CSEL条件 B条件一览
  • 【畅购商城】详情页模块之评论
  • STM32完全学习——使用定时器1精确延时
  • Docker离线安装简易指南
  • 0基础跟德姆(dom)一起学AI 自然语言处理06-文本数据增强
  • DAY4 登陆界面补充对话框
  • 【机器学习】深度学习(DNN)
  • 【JavaEE进阶】Spring传递请求参数
  • 总结TCP/IP四层模型
  • 机器学习基础-神经网络与深度学习