栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

文章目录
  • Android开发艺术探索的代码尝试----AIDL篇
  • 前言
  • 一、AIDL是什么?
    • AIDL是**IPC(进程间通信方式)**的一种。 AIDL偏向于底层,它的优点是支持并发,应用面广。但是代码的编写比较繁琐。
  • 二、本次代码的实现目标
  • 三、实现步骤
    • 基本配置
      • Activity
      • Service
    • 配置多进程环境
    • 编写AIDL文件
    • 在Service中实现get和change的AIDL接口
    • 在Activity中获取AIDL接口的实例并实现Listener的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的值表示进程名。


            
        
            
                
                
            
        
        ...
    

编写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 {
    
    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 {
    
    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包结构,显而易见这是为了序列化和反序列化。

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/874641.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号