公司产品之前IM这块存在很多问题,消息到达率低,加上协议上有些问题,丢消息频繁,所以需要重构IM,AIDL不能解决以上问题。好吧!那AIDL可以解决什么问题?什么是AIDL?

什么是AIDL?

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

AIDL可以解决什么问题?

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

Android Studio AIDL 实战

大部分文章介绍都是在eclipse下介绍的,现在 Android Studio 作为开发工具比较普及了,所以我在Android Studio 下介绍(其实区别不大)。

言归正传,我们需要使用Android Studio实现一个远程Service,并且建立AIDL进行通信。

搭建了简单的Service框架

1.继承Service

package name.quanke.aidldemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder; /**
*
* Created by http://quanke.name on 16/7/23.
*/
public class PushService extends Service {
public PushService() { } @Override
public IBinder onBind(Intent intent) {
return new LibHandler();
} @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

1.创建AIDL文件夹

1.创建AIDL文件夹

2.创建AIDL文件

2.创建AIDL文件

3.编写AIDL文件
// IHandler.aidl
package name.quanke.aidldemo; // Declare any non-default types here with import statements interface IHandler {
void connect();
}
4.AIDL文件 生成接口

4.AIDL文件 生成接口

生成后的样子

4.AIDL文件 生成后的样子

5.编写客户端 ServiceConnection
package name.quanke.aidldemo;

import android.app.Application;
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; /**
* Created by quanke on 16/7/23.
*/
public class PushManager { private static final String TAG = "PushManager.class";
private IHandler iHandler; private static PushManager ourInstance = new PushManager(); public static PushManager getInstance() {
return ourInstance;
} private PushManager() { } public void init(Application app){ Intent binderIntent = new Intent(app,PushService.class);
app.bindService(binderIntent, serviceConnection, Context.BIND_AUTO_CREATE);
} public void connect(){
try {
//通过AIDL远程调用
Log.d(TAG,"++start Remote++");
iHandler.connect();
} catch (RemoteException e) {
e.printStackTrace();
} } private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iHandler = IHandler.Stub.asInterface(service);
//连接成功调动
} @Override
public void onServiceDisconnected(ComponentName name) {
//断开连接调用
}
};
}
6.编写服务端实现connect方法
package name.quanke.aidldemo;

import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log; /**
*
* Created by quanke on 16/7/23.
*/
public class LibHandler extends IHandler.Stub{ @Override
public void connect() throws RemoteException {
Log.d("","connect()");
} @Override
public IBinder asBinder() {
return null;
}
}

以上实现了简单的连接,接下来我们实现传递自定义类型

传递自定义的类型

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

package name.quanke.aidldemo.model;

import android.os.Parcel;
import android.os.Parcelable; /**
*
* Created by quanke on 16/7/23.
*/
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);
} public Message() {
} 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

// IHandler.aidl
package name.quanke.aidldemo; // Declare any non-default types here with import statements import name.quanke.aidldemo.model.Message; interface IHandler {
void connect(); void sendMessage(Message message);
}

编译项目,报错

/Users/quanke/Dev/android/src/AIDLDemo/app/src/main/aidl/name/quanke/aidldemo/IHandler.aidl
Error:(6) couldn't find import for class name.quanke.aidldemo.model.Message
Error:Execution failed for task ':app:compileDebugAidl'.
> java.lang.RuntimeException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Users/quanke/Dev/android/tools/android-sdks/build-tools/23.0.3/aidl'' finished with non-zero exit value 1
Information:BUILD FAILED

因为自定义类型不仅要定义实现android.os.Parcelable接口的类,还得为该实现类定义一个aidl文件,如下:

自定义类aidl文件

// IHandler.aidl
package name.quanke.aidldemo.model; // Declare any non-default types here with import statements import name.quanke.aidldemo.model.Message; parcelable Message ;

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

编译项目,还是报错

parameter 1: 'Message message' can be an out parameter, so you must declare it as in, out or inout.

AIDL不是 Java。它是真的很接近,但它不是 Java。

Java 参数没有方向的概念,AIDL 参数有方向,参数可以从客户端传到服务端,再返回来。

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

void sendMessage(in Message message);

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

void sendMessage(out Message message);

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

void sendMessage(inout Message message);

总结

Android Studio Service AIDL 详解 就到这里,现在应该可以使用AIDL实现想要的功能了,实现简答的AIDL很简单,主要是在自定义类型的时候,有几个坑注意就好。

源码地址: https://github.com/quanke/AIDLDemo.git

【转载】Android Studio Service AIDL 详解的更多相关文章

  1. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  2. Android Studio gradle配置详解

    android gradle配置详解 AppExtension类及其属性 可能大部分人看到AppExtension类会感觉到非常的陌生,其实我们在app中的build.gradle中填写配置信息的时候 ...

  3. Android中Service 使用详解(LocalService + RemoteService)

    Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...

  4. [转载] Android随笔之——PackageManager详解

    本文转载自: http://www.cnblogs.com/travellife/p/3932823.html 参考:http://www.cnblogs.com/xingfuzzhd/p/33745 ...

  5. Android查缺补漏(IPC篇)-- 款进程通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  6. Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  7. ANDROID L——Material Design详解(UI控件)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...

  8. android ------- 开发者的 RxJava 详解

    在正文开始之前的最后,放上 GitHub 链接和引入依赖的 gradle 代码: Github: https://github.com/ReactiveX/RxJava https://github. ...

  9. Android开发之InstanceState详解

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

随机推荐

  1. SAP S4HANA TR传输之操作

    SAP S4HANA TR传输之操作 事务代码: STMS_IMPORT, 选中请求,点击漏斗按钮, 输入要传输的TR(可以多个),然后回车, 鼠标单击请求号,按F9, 然后传输, 点击按钮'是',系 ...

  2. Android 音视频技术之录音获取实时音量

    一.实时音量相关基础知识 说到获取音量,大家首先想到的应该就是分贝(dB),分贝是一个相对单位(是一个比值,是一个数值,是一个纯计数方法). 在音频领域dB度量的是声音的强度,其计算的公式如下: 在上 ...

  3. CodeForces - 5C(思维+括号匹配)

    题意 https://vjudge.net/problem/CodeForces-5C 给出一个括号序列,求出最长合法子串和它的数量. 合法的定义:这个序列中左右括号匹配. 思路 这个题和普通的括号匹 ...

  4. [WPF 自定义控件]自定义控件库系列文章

    Kino.Toolkit.Wpf Kino.Toolkit.Wpf是一组简单实用的WPF控件与工具,用于介绍自定义控件的入门.相关博客地址如下: 开始一个自定义控件库项目 介绍开始一个自定义控件库项目 ...

  5. JavaScript设计模式基础(二)

    JavaScript 设计模式基础(一) 原型模式 在以类为中心的面向对象编程语言中,类和对象的关系就像铸模和铸件的关系,对象总是从类中创建.而原型编程中,类不是必须的,对象未必从类中创建而来,可以拷 ...

  6. vmware vsphere client 虚拟机动态添加磁盘

    0x00 事件 为了在虚拟机添加了磁盘之后,不重启机器加载新磁盘. 如上图,添加了一块 10G 的磁盘之后. 在虚拟机中是看不到新添加的磁盘: 0x01 解决 运行如下命令,通过重新扫描 SCSI ( ...

  7. SQL Server解惑——为什么你的查询结果超出了查询时间范围

    废话少说,直接上SQL代码(有兴趣的测试验证一下),下面这个查询语句为什么将2008-11-27的记录查询出来了呢?这个是同事遇到的一个问题,个人设计了一个例子. USE AdventureWorks ...

  8. spring boot 加入mail邮件支持

    一.添加依赖 <!-- 邮件整合 --> <dependency> <groupId>org.springframework.boot</groupId> ...

  9. 12.2 中的Data Guard Standby 密码文件自动同步 (Doc ID 2307365.1)

    Data Guard Standby Automatic Password file Synchronization in 12.2 (Doc ID 2307365.1) APPLIES TO: Or ...

  10. 12c新特性 在线操作数据文件

    我们都知道,oracle pre-12c之前,若是想要把一个数据文件改名或者迁移, 必须在归档模式下先把这个数据文件offline之后, 然后进行OS上的copy或者rename 操作, 最后在sql ...