文档章节

Android高手进阶(一)AIDL跨进程调用

海阔天空玩世不恭
 海阔天空玩世不恭
发布于 2016/02/02 14:19
字数 1357
阅读 389
收藏 5

Android高手进阶(一)AIDL跨进程调用

什么是ADIL跨进程调用?

    由于Android是不允许两个进程共享内存空间的,所以如果当前你开发的应用需要调用其他应用的某个逻辑处理某个事情的时候,就需要用到AIDL跨进程调用。

AIDL能干什么?

    APP与APP之间的逻辑交互

AIDL开发的步骤?

    服务端

    一.新建一个AIDL文件


 

    二.定义接口方法

// IMyAidlInterface.aidl
package com.tcl.personalcloudaidljar;

import com.tcl.personalcloudaidljar.StudentModel;

// 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.
     */
    double doCalulate(double a,double b);
    double doMin(double a, double b);
    void setStudent(in StudentModel model);
    StudentModel getFinalStudent(inout StudentModel model);
    List<StudentModel> getStudentResult(inout List<StudentModel> model);
}

可以传的值有JAVA基本类型和List、Map,其他自定义类型的Model需要指明是in、out、inout之中的一种,分别表示输入、输出、和同时输入和输出。
如果是自定义类型的Model,需要序列化,实现Parcelable或者Serializable接口,建议实现Parcelable接口(效率更高)。

还需要定义一个Model类名一样的aidl接口,内容为

// Student.aidl
package com.tcl.personalcloudaidljar;

parcelable StudentModel;

 

Model类的具体实现见下图

package com.tcl.personalcloudaidljar;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by pcgu on 16-2-1.
 */
public class StudentModel implements Parcelable {
    private int id;
    private String name;
    private long md5;
    private boolean canShow;

    public StudentModel() {
    }

    private StudentModel(Parcel in) {
        readFromParcel(in);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public long getMd5() {
        return md5;
    }

    public void setMd5(long md5) {
        this.md5 = md5;
    }

    public boolean isCanShow() {
        return canShow;
    }

    public void setCanShow(boolean canShow) {
        this.canShow = canShow;
    }

    public static final Creator<StudentModel> CREATOR =
            new Creator<StudentModel>() {
                @Override
                public StudentModel createFromParcel(Parcel source) {
                    return new StudentModel(source);
                }

                @Override
                public StudentModel[] newArray(int size) {
                    return new StudentModel[size];
                }
            };

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
        dest.writeLong(md5);
        dest.writeByte((byte) (canShow ? 1 : 0));
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public void readFromParcel(Parcel in) {
        id = in.readInt();
        name = in.readString();
        md5 = in.readLong();
        canShow = in.readByte() != 0;
    }

}

所有自定义的Model类必须在aidl类中申明。

 

    三.实现service类

package com.tcl.personalcloudaidljar;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.util.List;

/**
 * Created by pcgu on 16-1-29.
 */
public class MyService extends Service {
    private static final String TAG = "TEST";

    private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
        @Override
        public double doCalulate(double a, double b) throws RemoteException {
            Log.e(TAG, "doCalulate a and b=" + a + "," + +b);
            return a + b;
        }

        @Override
        public double doMin(double a, double b) throws RemoteException {
            return a - b;
        }

        @Override
        public void setStudent(StudentModel model) throws RemoteException {
            Log.e(TAG, "setStudent id =" + model.getId() + " name=" + model.getName() +
                    " md5=" + model.getMd5() + " canShow=" + model.isCanShow());
        }

        @Override
        public StudentModel getFinalStudent(StudentModel model) throws RemoteException {
            Log.e(TAG, "getFinalStudent id =" + model.getId() + " name=" + model.getName() +
                    " md5=" + model.getMd5() + " canShow=" + model.isCanShow());
            model.setName("gupengcheng");
            return model;
        }

        @Override
        public List<StudentModel> getStudentResult(List<StudentModel> model) throws RemoteException {
            Log.e(TAG, "get Student Result =" + model.get(0).getName() +
                    " size ==" + model.size());
            StudentModel singleModel = new StudentModel();
            singleModel.setName("gugugu");
            singleModel.setCanShow(false);
            singleModel.setId(123);
            singleModel.setMd5(1234566);
            model.add(singleModel);
            return model;
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "MyService onCreate");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "MyService onDestroy");
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
        Log.e(TAG, "MyService onRebind");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "MyService onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "MyService onBind");
        return mBinder;
    }
}

service类中最重要的是实现IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub()抽象类,并且在onBind中返回这个mBinder。

    四.在manifest中申明改service并指定过滤条件

这里指定的过滤条件是action为com.tcl.personalcloudaidljar.aidl。

 

    客户端

    客户端也就是调用方,调用刚才的服务端的service中实现的抽象方法来完成某个逻辑。

 

    一.拷贝服务端的aidl包到服务端

这时候make project一次就会在如下目录中自动生成一个aidl实现类

 

    二.调用服务端的aidl接口的具体实现方法

    有两种使用方式,分别是activity中直接使用和封装成Jar包给第三方使用。

(1)直接使用

    bindService,然后通过AIDL类的对象调用service中的具体方法来达到跨进程调用的目的。需要注意的是调用之前必须bindService,在Activity onDestory的时候必须unbindService.

(2)封装成jar包,实现类如下

package com.tcl.personalcloudaidlclient;

import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.tcl.personalcloudaidljar.IMyAidlInterface;
import com.tcl.personalcloudaidljar.StudentModel;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by pcgu on 16-2-1.
 */
public class PersonalCloudManager {
    private static final String TAG = "PersonalCloudManager";
    private IMyAidlInterface mIMyAidlInterface;
    private static boolean connected = false;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "client onServiceConnected");
            mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
            connected = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "client onServiceDisconnected");
            mIMyAidlInterface = null;
            connected = false;
        }
    };

    @TargetApi(4)
    public void bindAidlService(Context context) {
        Intent intent = new Intent();
        intent.setAction("com.tcl.personalcloudaidljar.aidl");
        intent.setPackage("com.tcl.personalcloudaidljar");
        context.bindService(intent, connection, Context.BIND_AUTO_CREATE);

    }

    public void unbindAidlService(Context context) {
        context.unbindService(connection);
    }

    public double doCalculate(double num1, double num2) {
        if (!connected) {
            return 0;
        }
        double result = 0;
        try {
            result = mIMyAidlInterface.doCalulate(num1, num2);
            Log.e(TAG, "client add result ==" + result);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return result;
    }

    public double doMin(double num1, double num2) {
        if (!connected) {
            return 0;
        }
        double result = 0;
        try {
            result = mIMyAidlInterface.doMin(num1, num2);
            Log.e(TAG, "client min result ==" + result);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return result;
    }

    public void setStudentModel(StudentModel model) {
        if (!connected) {
            return;
        }
        try {
            mIMyAidlInterface.setStudent(model);
            Log.e(TAG, "client set Student Model");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    public StudentModel getFinalStudentModel(StudentModel model) {
        if (!connected) {
            return model;
        }
        StudentModel finalStudentModel = new StudentModel();
        try {
            finalStudentModel = mIMyAidlInterface.getFinalStudent(model);
            Log.e(TAG, "client set final Student Model");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return finalStudentModel;
    }

    public List<StudentModel> getList(List<StudentModel> model) {
        if (!connected) {
            return model;
        }
        List<StudentModel> models = new ArrayList<>();
        try {
            models = mIMyAidlInterface.getStudentResult(model);
            Log.e(TAG, "client set final Student Model");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return models;
    }

    public boolean isServiceConnected() {
        return connected;
    }
}

    需要注意的是给第三方调用需要提供一个服务绑定成功与否的标志位,即connected这个参数,第三方才知道能否调用AIDL的实现方法,只有为True的时候才能调用。

    三.封装成Jar包的方法

    在app的build.gradle中添加

task makeJar(type: Copy) {
        delete 'build/libs/aidlsdk.jar'
        from('build/intermediates/bundles/release/')
        into('build/libs/')
        include('classes.jar')
        rename ('classes.jar', 'aidlsdk.jar')
    }

    makeJar.dependsOn(build)

用打包命令 ./gradlew makeJar 即可打包为红色标记的名字的jar包


    四.注意问题

    当aidl方法中参数为回调接口的时候,调用实现类需要用new ***Callback.stub()的方式

© 著作权归作者所有

海阔天空玩世不恭
粉丝 14
博文 63
码字总数 23998
作品 0
成都
程序员
私信 提问
Android高手进阶教程(二十五)之---Android 中的AIDL!!!

大家好,好久不见,今天要给大家分享的是android aidl的使用。在Android中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然,...

迷途d书童
2012/02/29
298
1
Android 进阶7:进程通信之 AIDL 的使用

读完本文你将了解: AIDL 是什么 AIDL 支持的数据类型 AIDL 如何编写 AIDL 实例 创建 AIDL 编写服务端代码 编写客户端代码 运行结果 总结 代码地址 Thanks 记得 2015 年实习面试,笔试题里就...

丁佳辉
02/18
0
0
Android 跨进程通信方法

由于android系统中应用程序之间不能共享内存。因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些。在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android...

天王盖地虎626
2018/12/24
0
0
【漫画技术】Android跨进程通信

类型 描述 用时 选题 silencezwm 0.5小时 写作时间 2017年10月25日 5.5小时 审稿 silencezwm、Mya婷婷 2小时 校对上线 silencezwm 1小时 Tips:4个环节,共计约9小时的精心打磨完成上线,同时...

silencezwm
2018/07/03
0
0
Android中实现跨进程通信(IPC)的方式(三)之观察者模式

Android中实现跨进程通信(IPC)的方式(三)之观察者模式 前言     在Android中实现跨进程通信(IPC)的几种方式(一)中介绍了什么是多进程,为什么需要多进程,多进程的优缺点等。这篇我们将...

huangandroid
2018/06/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

数据库

数据库架构 数据库架构可以分为存储文件系统和程序实例两大块,而程序实例根据不同的功能又可以分为如下小模块。 1550644570798 索引模块 常见的问题有: 为什么要使用索引 什么样的信息能成...

一只小青蛙
今天
5
0
PHP常用经典算法实现

<? //-------------------- // 基本数据结构算法 //-------------------- //二分查找(数组里查找某个元素) function bin_sch($array, $low, $high, $k){ if ( $low <= $high){ $mid = int......

半缘修道半缘君丶
昨天
5
0
GIL 已经被杀死了么?

本文原创并首发于公众号【Python猫】,未经授权,请勿转载。 原文地址:https://mp.weixin.qq.com/s/8KvQemz0SWq2hw-2aBPv2Q 花下猫语: Python 中最广为人诟病的一点,大概就是它的 GIL 了。...

豌豆花下猫
昨天
6
0
git commit message form

commit message一般包括3部分:Header、Body、Footer。 <type>(<scope>):<subject>blank line<body>blank line<footer> header是必需的,body、footer可以省略。 header中type、subject......

ninjaFrog
昨天
5
0
聊聊Elasticsearch的CircuitBreakerService

序 本文主要研究一下Elasticsearch的CircuitBreakerService CircuitBreakerService elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/indices/breaker/CircuitBreakerService.ja......

go4it
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部