继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android Studio Service AIDL 详解

陪伴而非守候
关注TA
已关注
手记 350
粉丝 62
获赞 285

原文链接

公司产品之前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文件夹

1.创建AIDL文件夹

2.创建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文件 生成接口

生成后的样子

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文件

自定义类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

有什么问题欢迎留言。

如果喜欢请关注我,赞我,来抚平我虚荣的心


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP