公司产品之前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.aidlpackage name.quanke.aidldemo;// Declare any non-default types here with import statementsinterface 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.aidlpackage name.quanke.aidldemo;// Declare any non-default types here with import statementsimport 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.aidlError:(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 statementsimport 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
有什么问题欢迎留言。
如果喜欢请关注我,赞我,来抚平我虚荣的心
共同学习,写下你的评论
评论加载中...
作者其他优质文章