IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android开发艺术探索代码尝试----IPC之AIDL篇 -> 正文阅读

[移动开发]Android开发艺术探索代码尝试----IPC之AIDL篇

Android开发艺术探索的代码尝试----AIDL篇



前言

本次主要记录Android中IPC方式之一,AIDL的使用。本文内容没有涉及AIDL的源码内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、AIDL是什么?

AIDL是**IPC(进程间通信方式)**的一种。
AIDL偏向于底层,它的优点是支持并发,应用面广。但是代码的编写比较繁琐。

二、本次代码的实现目标

在这里插入图片描述

  1. 创建一个Activity作为进程1
  2. 创建一个Service作为进程2
  3. Service中有一个变量mode,作为我们的通信目标。
  4. 所以Activity需要获取和修改 mode(Activity向Service通信)
  5. Service需要通知Activity,mode已被修改。(Service向Activity通信)

三、实现步骤

基本配置

Activity

  1. 默认的Activity模板
  2. 3个Button:绑定服务、获取mode、改变mode

Service

  1. 默认的Service模板
  2. 配置一个mode变量作为通信目标

配置多进程环境

关键词:Android:process字段

在AndroidManiFest文件中修改Activity和Service的配置,添加Android:process字段,process的值表示进程名。

<application
        ...
        <service
            android:name=".Serivice.IPCService"
            android:enabled="true"
            android:exported="true"
            android:process=":secondProcess"/>
            
        <activity 
        	android:name=".MainActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        ...
    </application>

编写AIDL文件

一个接口需要对应一个AIDL文件。
故,我们需要两个接口。一个给Activity使用,一个给Service使用。

在编写完AIDL文件后,我们需要点击build,从而生成java文件。本质上我们是使用这个java文件。
AIDL文件的编写规范:

IMyAidlInterface.aidl

// IMyAidlInterface.aidl
package com.example.demo.AIDL;
import com.example.demo.AIDL.IAidlInterface_Listener;
// Declare any non-default types  here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void registerListener(IAidlInterface_Listener listener);//注册(获取)监听器
    void changeMode(int mode);//修改mode
    int getMode();//获取mode

IAidlInterface_Listener.aidl

// IAidlInterface_Listener.aidl
package com.example.demo.AIDL;

// Declare any non-default types here with import statements

interface IAidlInterface_Listener {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void onSecondProcessChanged();//通知Activity
}

在Service中实现get和change的AIDL接口

将AIDL接口中的Stub转为Service中的binder,并实现接口方法
Stub是AIDL接口的内部类,继承了IBinder
//IPCService.java
//用于初始化Service的方法,主要初始化了mBinder1,在Activity绑定这个Service时将mBinder返回给Activity
public void init(){
        Mode=0;
        mBinder1 = new IMyAidlInterface.Stub() {
            @Override
            public void registerListener(IAidlInterface_Listener listener) throws RemoteException {
                mListener = listener;//获取Activity传来的listener。
            }

            @Override
            public void changeMode(int mode) throws RemoteException {
                Mode=mode;
                mListener.onSecondProcessChanged();
                Log.d(TAG, "changeMode: mode ="+Mode);
            }

            @Override
            public int getMode() throws RemoteException {
                return Mode;
            }
        };
        mBinder2 = new mBinder();
    }

在Activity中获取AIDL接口的实例并实现Listener的AIDL接口

关键点:使用stub的asInterface()将IBinder转为AIDL接口实例,此时可以调用接口方法。

  1. 绑定Service后获取到Service传来的Binder,利用该Binder获取到AIDL的接口实例(具体如何获取见总结)。
  2. 实现Listener的AIDL接口,实例化Listener,通过Service的接口 传输 这个Listener。

服务绑定

//MainActivity.java
//本地的AIDL接口实例
private IMyAidlInterface iMyAidlInterface=null;
//用于绑定Service使用的ServiceConnection实例
private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);//Binder转换为接口实例
            try {
                mode = iMyAidlInterface.getMode();
                iMyAidlInterface.registerListener(mListener);注册监听器
                Log.d(TAG, "连接服务成功: 注册监听");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

监听器

private IAidlInterface_Listener mListener = new IAidlInterface_Listener.Stub() {
        @Override
        public void onSecondProcessChanged() throws RemoteException {
            Log.d(TAG, "onSecondProcessChanged: ");//由Service调用
        }
    };

通信测试

Activity
在这里插入图片描述
Log

  1. 点击Bind
    进程1
    在这里插入图片描述
    进程2
    在这里插入图片描述
  2. 获取及修改mode
    在这里插入图片描述

总结

代码尝试到此处,如果对IPC没有深入了解的话,想必会有如下几个疑问:

两个进程间如何传递对象?(本例中传递了监听器)

本质上并没有传递对象,两个进程间的对象不是同一个对象(hashcode不一致)。因为多进程可以看作是两个程序在运行,对于android而言,他会为每一个进程分配虚拟机和内存空间。
那么这个对象是如何传递的?—是依靠序列化和反序列化。
所以这里一个前提,两个进程的代码中需要有一样的aidl包结构,显而易见这是为了序列化和反序列化。

既然进程间传递的对象不是同一个对象,如何保证它能实现需要的功能?(本例中的监听器实例)

这个问题可以转化为----一个实例化的接口对象,在经过序列化和反序列化后还能不能调用重写的接口方法。
答案是,能。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-12 16:33:51  更:2022-05-12 16:34:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:49:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码