aidl使用采坑记

什么是AIDL?

AIDL是 Android
Interface definition language
的缩写,它是一种Android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口

AIDL可以解决什么问题?

  • 可以实现多个应用程序共享同一个Service的功能,比如:IM服务可以提供给多个APP使用,先在推送基本都是采取这种方案
  • 可以跨进程调用服务里的方法

搭建了简单的Service框架

1.继承Service

public class PushService extends Service{

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

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

2.在AndroidManifest.xml里注册

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="name.quanke.aidldemo">

    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:name=".App"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <service
                android:name=".PushService"
                android:enabled="true"
                android:process=":push"
                android:exported="true">
        </service>
    </application>

</manifest>

建立AIDL

创建AIDL文件

编写AIDL文件
interface IHandler {
  void connect();
}

aidl生成后的样子

编写客户端 ServiceConnection
public class PushClient {
    private IHandler iHandler;
    private static PushClient instance = new PushClient();

    public static PushClient getInstance() {
        return instance;
    }

    public void init(Application app){
        Intent binderIntent = new Intent(app,PushService.class);
        app.bindService(binderIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iHandler = IHandler.Stub.asInterface(service);
            //连接成功调用
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //断开连接调用
        }
    };

    //通过AIDL远程调用
    public void connect(){
        try {
            iHandler.connect();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

写服务端实现connect方法
public class LibHandler extends IHandler.Stub{

    @Override
    public void connect() throws RemoteException {

    }

    @Override
    public IBinder asBinder() {
        return null;
    }
}

测试

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
    }

    private void init() {
      findViewById(R.id.aidl_test).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        PushClient.getInstance().connect();
    }
}

其实到这里我们就结束了。

接下来我们看看如果自定义传递的数据类型

传递自定义的类型

AIDL默认支持的类型包括Java基本类型(int、long、boolean等),和(String、List、Map、CharSequence),如果要传递自定义的类型需要实现android.os.Parcelable接口。

自定义Message实体:

public class Message implements Parcelable {
    private long id;
    private String content;

    public long getId() {
        return id;
    }

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

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "Message{" +
                "id=" + id +
                ", content='" + content + '\'' +
                '}';
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(this.id);
        dest.writeString(this.content);
    }

    protected Message(Parcel in) {
        this.id = in.readLong();
        this.content = in.readString();
    }

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

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

}

修改IHandler

interface IHandler {
  void connect();
  void sendMessage(Message message);
}

注意: 自定类型aidl文件名字、路径需要和自定义类名字、路径保持一致,

 编译一下,发现报了个错

意思是必须定义Message的方向,AIDL
参数有方向。(学习了)

如果sendMessage方法的message参数是纯粹的输入参数—这意味着是从客户端到服务器的数据,你需要在AIDL声明:

void sendMessage(in Message message);

如果sendMessage方法的message参数是纯粹的输出-这意味着它的数据是通过从服务器到客户端,使用:

void sendMessage(out Message message);

如果sendMessage方法的message参数是输入也是输出-客户端的值在服务可能会修改,使用:

void sendMessage(inout Message message);

我们这里是客户端范围服务端的数据,所以用in

interface IHandler {
  void connect();
  void sendMessage(in Message message);
}

好了,aidl的用法就到这里了,aidl主要是用在跨进程间通信和数据交换,平时开发中也用的比较少,通过这个例子加深了对他的用法,后面有什么好的坑,我会发出了的,谢谢大家。最后做个链接 

https://github.com/xiangzhihong/aidl

时间: 2024-10-03 13:21:33

aidl使用采坑记的相关文章

【踩坑记】从HybridApp到ReactNative

前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. HybridApp最早好像是国外的PhoneGap,然后国内有AppCan.Dcloud.APICloud等等.我当时接触的是APICloud,相比于其他平台,APICloud最大的特点是它的混合程度比较高! 要知道,Webapp最大的问题就是性能问题始终无法和原生App相比,由此才发展出来Hybrid

Docker踩坑记

看最近Docker这么火,也跟着用用.结果从一个坑出来又掉另一个坑去了. FATA[0000] Error response from daemon: client and server don't have same version (client : 1.16, server: 1.15) 1 [root@aliyun ~]# docker info 2 FATA[0000] Error response from daemon: client and server don't have s

总结!一个产品新手的踩坑记

本文讲的是总结!一个产品新手的踩坑记, 加入产品大家庭正好三个月了,在大佬们面前不敢造次,于是,觉得可以拿出来分享的,便是在这段春夏交替之光里,亲脚踩的一些坑,以及在坑里获得的一些小发现.所幸的是,在老大和运营设计开发同学们的帮助下,目前还没有摔成骨折,还望日后能留全尸. 踩坑装备 没点装备怎么敢出门打怪.需求讨论会上记录好被提出的需求.其内容.提出者,为之后踩坑.填坑做好准备.对方攻击double没关系,首先血要厚.(实践证明,这些装备在日后我明确需求以及设计完成后自我检查的过程中帮了大忙).

Java web 开发填坑记 2 -如何正确的创建一个Java Web 项目

转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72566261 本文出自[赵彦军的博客] Java web 开发填坑记 1-如何正确的下载 eclipse Java web 开发填坑记 2-如何正确的创建一个Java Web 项目 在我们正确的下载了 Eclipse 之后,我们来创建第一个 Java web 项目.在创建 Java web 项目之前,我们需要做一些准备工作. 项目工作 1. 安装 jdk , 并且配置 Java

Java web 开发填坑记 1 -如何正确的下载 eclipse

转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72561763 本文出自[赵彦军的博客] Java web 开发填坑记 1 -如何正确的下载 eclipse Java web 开发填坑记 2 -如何正确的创建一个Java Web 项目 Java web 开发填坑记-如何正确的下载 eclipse 最近在做 Java web 相关的开发,遇到的很多问题,也填了很多坑,就来做一下总结. 首先遇到的第一个问题就是,如何正确的下载 Ec

缓存爬坑记 如何解决缓存雪崩

缓存爬坑记 如何解决缓存雪崩 http://www.iqiyi.com/w_19rwgvwz4d.html

Android Studio踩坑记

拾起Android项目,需要使用Goolgle Play Services.顺应潮流换了Android Studio,开启了踩坑之旅. 尝试直接将Eclipse项目导入AS,结果根本没法用啊.正确的方法应该是升级ADT,在Eclipse下导出build.gradle然后再导入.但是升级的时间还不如直接新建项目把资源拷进去,同时也能了解一下AS默认的项目结构. 第一个遇到的问题是新建的项目没有assert和lib目录.java和res等资源都在src/main目录下,于是我将assets和libs

Spark踩坑记:共享变量

前言 前面总结的几篇spark踩坑博文中,我总结了自己在使用spark过程当中踩过的一些坑和经验.我们知道Spark是多机器集群部署的,分为Driver/Master/Worker,Master负责资源调度,Worker是不同的运算节点,由Master统一调度. 而Driver是我们提交Spark程序的节点,并且所有的reduce类型的操作都会汇总到Driver节点进行整合.节点之间会将map/reduce等操作函数传递一个独立副本到每一个节点,这些变量也会复制到每台机器上,而节点之间的运算是相

Logtail技术分享(二) : 多租户隔离技术+双十一实战效果

日益增长的数据采集需求 上一篇中我们分享了日志采集中基于Polling+Notify组合的日志保序采集技术,Logtail基于Polling+Notify的组合方案以及日志轮转队列等相关技术实现了单一配置下的日志保序.高效.可靠采集问题. 然而日志采集并不仅仅是单一用户/应用需要完成的工作,例如一个典型的服务器上需要采集的日志数据有:资源类Metric数据.系统监控日志.Nginx访问数据.中间件请求数据.安全审计日志.各类应用中各个不同组件的日志等等:如果应用docker话,保守估计一个doc