Android服务Service-AIDL(三)

来源:互联网 发布:linux网卡怎么激活 编辑:程序博客网 时间:2024/06/07 01:14

1)概述

本章是接着上篇没有写完的Bound式服务写的,上篇地址Android服务Service(二)。在此,重新回顾下AIDL基本概念,AIDL(Android Interface Definition Language)安卓接口描述语言,它专门用来处理进程通信,不像Messenger那样,它适合用来处理并发请求,如果你想service能够同时处理多个请求,那么就可以直接用AIDL。小小提下,Messenger底层也是AIDL,只不过系统为我们做了一层封装,方便我们调用。

2)AIDL

下面结合官方文档样例,具体介绍下怎么使用AIDL实现IPC进程通信,

2.1)AIDL接口文件的创建

我们看下图

这里写图片描述

AS中提供了AIDL文件的创建,但是我们也可以自己创建一个文件,改下后缀就行了。
我们看下生成的AIDL文件,和我实现的接口

这里写图片描述

我们可以看见在src/main下自动生成了一个aidl文件夹,这和eclipse不同,创建的AIDL文件就放在aidl文件夹里面了

到这里先了解下,AIDL支持的数据类型:

  • 基本数据类型(int, long, char, boolean, 等)

  • String和CharSequence

  • List 只支持ArrayList,里面的每个元素必须都能够被AIDL支持

  • Map 只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value

  • Parcelable 所有实现了Parcelable接口的对象

  • AIDL 所有的AIDL接口本身也可以在AIDL文件中使用

注意:
1.你必须显示import所有自定义的Parcelable对象,不管它们是否和当前AIDL文件在同一个包 内。
2.AIDL文件中用到的自定义的Parcelable类型,必须新建一个同名的AIDL文件
3.所有的非基本数据类型参数,必须标上方向:in(输入),out(输出)或者inout(输入输出)

把服务端aidl文件夹copy到client模块中

此时重新在Build->Rebuild Project下项目看下AIDL生成的Java类

这里写图片描述

生成的Java文件里面的内容还是有点复杂的,先不看了。

2.2)远程服务端的实现

定义好AIDL接口之后,接下来就需要在服务端实现这个接口

package com.chen.service.service;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import com.chen.service.IRemoteService;public class RemoteService extends Service {    private IRemoteService.Stub mBinder = new IRemoteService.Stub(){        @Override        public int getPid() throws RemoteException {            return 123;        }        @Override        public String basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {              return "我是服务端AIDL"+anInt+"-"+aLong+"-"+aBoolean+"-"+aFloat+"-"+aDouble+"-"+aString;        }    };    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }}<!--process:运行在独立进程中--><!--exported:是否支持其它应用调用当前组件。--><!--Android系统是否可以实例化应用的组件。如果为true可以,如果为    false不可以。如果为true时,每个组件的enabled属性决定了此组件    是否可用。如果为false,他重写了组件指定值,所有的组件将不还用。默认为true。--><service    android:name=".service.RemoteService"    android:enabled="true"    android:exported="true"    android:process=":remote"    ></service>

2.3)客户端的实现

package com.chen.demo;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.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Toast;import com.chen.service.IRemoteService;public class MainActivity extends AppCompatActivity {    private IRemoteService mBinder;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    @Override    protected void onStart() {        super.onStart();        Intent intent = new Intent();        intent.setAction("android.chen.xiao.service");        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);    }    public void getPid(View view){        try {            int pid = mBinder.getPid();            Toast.makeText(this, "----->>>>>"+pid, Toast.LENGTH_SHORT).show();        } catch (RemoteException e) {            e.printStackTrace();        }    }    public void basicTypes(View view){        try {            String result = mBinder.basicTypes(1, 2L, true, 10.3f, 11, "AIDL");            Toast.makeText(this, "----->>>>>"+result, Toast.LENGTH_SHORT).show();        } catch (RemoteException e) {            e.printStackTrace();        }    }    @Override    protected void onStop() {        super.onStop();        unbindService(mConnection);    }    private ServiceConnection mConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            mBinder = IRemoteService.Stub.asInterface(iBinder);        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };}

运行结果

这里写图片描述

这里写图片描述

我们可以看到此时客户端已经成功调用了远程服务端的方法,并打印出正确的值。

3) 传递一个自定义对象

当你想要在客户端和服务器之间传递一个对象时,你必须实现Parcelable接口,才能实现进程通信

为了创建一个自定义对象,你必须做以下几件事:

  • 1)实现Parcelable接口

  • 2 )实现writeToParcelable,保存当前状态并写入Parcel

  • 3 ) 添加一个静态的实现了 Parcelable.Creator接口的字段

  • 4 )创建一个和自定义对象同名的.aidl文件,

通常我们一般是用工具来序列化Parcelable,看图:

这里写图片描述

就是第一个,点击Install,重启as就可以使用,看下怎么用

这里写图片描述

这是生成的代码

package com.chen.service;import android.os.Parcel;import android.os.Parcelable;/** * Created by chenxiaokang on 2016/12/1. */public class Rect implements Parcelable{    public int left;    public int top;    public int right;    public int bottom;    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeInt(this.left);        dest.writeInt(this.top);        dest.writeInt(this.right);        dest.writeInt(this.bottom);    }    public Rect() {    }    protected Rect(Parcel in) {        this.left = in.readInt();        this.top = in.readInt();        this.right = in.readInt();        this.bottom = in.readInt();    }    public static final Creator<Rect> CREATOR = new Creator<Rect>() {        @Override        public Rect createFromParcel(Parcel source) {            return new Rect(source);        }        @Override        public Rect[] newArray(int size) {            return new Rect[size];        }    };}

4 )最后

AIDL使用介绍差不多就这些了,服务的所有基本用法这三篇已经介绍得差不多了,其实这只是最基本的用法,很多深入的东西都没介绍,太菜了~~~~,以后nb了再深入总结。

5 ) 扩展学习

1)AIDL官方文档
2)http://www.open-open.com/lib/view/open1454895889776.html
3)http://blog.csdn.net/small_love/article/details/6534956
4)《Android开发艺术探索》IPC通信,这一章AIDL使用介绍的还是比较深入的,这里就不介绍了,同时其他IPC通信方式也值得学习,有时间总结下。

0 0
原创粉丝点击