快捷搜索:

Android应用开发入门(五十)AIDL接口通过绑定Se

媒介

前面解说了Service的一些基础内容。然则对付绑定办事通报数据,只局限于本地办事,无法应用办事进行跨进程间的交互。假如必要用到跨进程交互的话,必要用到一个新的技巧-AIDL, 本文就针对AIDL若何通报内置类型数据进行解说。对付Service不认识的同伙,可以先看看之前的文章:http://www.fengfly.com/plus/view-214081-1.htmlhttp://www.fengfly.com/plus/view-214082-1.html、http://www.fengfly.com/plus/view-214084-1.html。

本文内容如下:

什么是ADIL?

若何定义AIDL?

ADIL做了什么?

应用ADIL通报系统基础数据

什么是AIDL?

先往返首一下,Android在本地的Service中若何与其它组件进行交互的,首先Service必须实现其onBind()措施,然后在onBind措施通报一个IBinder接口的实现,而在其它组件中应用bindService()绑定一个办事,再经由过程此中的参数ServiceConnection工具获取到Service中定义的IBinder接口的实现。那么与Service进行数据交互,着实便是通报一个IBinder,经由过程这个IBinder进行交互。

而现在就碰着一个问题,在同一个进程中,是可以获取到这个Service类的,也就可以得到这个Service中定义的IBinder,然则假如在不合的利用中,即远程办事,若何获取IBinder呢?仅仅是在不合的利用定义一相同的类是没有用的,以是Android为我们供给了AIDL说话,它必要先定义一个远程调用接口,然后为该接口供给一个实现类,经由过程共享这个远程调用接口来达到进程间数据交互的目的,而这个接口的代码是有很多共性的,并且编写历程相称逝世板乏味,以是Android开拓者为我们供给了ADIL来简化通讯接口的开拓。

AIDL(Android Interface Definition Language)是Android远程调用接口的定义说话。它有它自己的一套语律例范,然则和Java类似,这并不难理解,具体的这个会后面先容。而当你定义好一个AIDL接口之后,你会发明在gen/目录下,多出一个与定义的AIDL包名相同,文件名相同的一个Java类,这个类是编译器根据定义的AIDL接口自动天生的代码,察看之后发明着实它也是承袭了Binder类(Binder是IBinder的实现类),以是它可以经由过程ServiceConnection进行数据通报。Service只必要裸露这个AIDL接口给客户端,让客户端也定义它,这样两个利用进程就可以通讯了。

若何定义AIDL?

AIDL的语法与Java接口的语法异常相似,然则存在一些差异:

AIDL定义接口的源代码后缀必须以.aidl结尾。

AIDL一样要指定AIDL接口的包信息package *。

AIDL接口无需指定public、private、protected等感化域,可以理解为便是public。

AIDL默认环境下只能通报基础类型、String、List、Map、CharSequence。

假如必要通报其他类型的工具,必要import工具的包名,并必要对工具进行特殊处置惩罚(之后会先容)。

例如:

package com.example.aidlservicedemo.domain;

interface IDog{

String getName();int getAge();

}

ADIL做了什么?

当你声明完一个AIDL接口的时刻,你会发明在项目的gen/目录下,对应包中存在一个同名的Java文件,这个文件是Android帮我们自动天生的,里面有很多代码,这里只讲一下必要留意的。查看自动天生的这个Java文件代码,会发明它定义了一个名为Stub的静态抽象类,这个Stub承袭了Binder,实现了AIDL接口,当然此中也实现了AIDL接口的两个措施,粗略看一下会发明它对数据做了一个序列化和反序列化的操作。正由于AIDL对数据进行了序列化和反序列化,以是才可以在进程间通报。

应用ADIL通报系统基础数据

定义好AIDL接口之后,就必要经由过程办事把接口裸露给客户端,这里Service.onBind()通报的便是这个Stub静态抽象类的实现类,其他没什么特其余。

下面经由过程一个Demo来演示ADIL若何通报数据的,在示例中,给出两个利用,分手实现Server与调用客户端,应用的AIDL接口便是上面给出的AIDL示例代码,这里不再重复定义。

AIDL办事:BaseTypeService.java

package com.example.aidlservicedemo;

import java.util.Random;

import com.example.aidlservicedemo.domain.IDog.Stub;

import android.app.Service;

import android.content.Intent;import android.os.IBinder;

import android.os.RemoteException;import android.util.Log;

public class BaseTypeService extends Service {

private final String TAG="main";private DogBinder binder=null;

private String[] names=new String[]{"小白","旺财","小黑"};private int[] ages=new int[]{1,2,3};

/**

* Stub的实现类,Stub内部实现了Binder* 内部实现AIDL定义的措施

*/public class DogBinder extends Stub{

@Override

public String getName() throws RemoteException {Random random=new Random();

int nextInt = random.nextInt(2);return names[nextInt];

}

@Overridepublic int getAge() throws RemoteException {

Random random=new Random();int nextInt = random.nextInt(2);

return ages[nextInt];}

}

@Overridepublic void onCreate() {

super.onCreate();// 实例化Binder工具

binder=new DogBinder();Log.i(TAG, "创建办事成功");

}

@Overridepublic IBinder onBind(Intent intent) {

Log.i(TAG, "绑定办事成功");// 返回Binder工具

return binder;}

}

客户端调用办事获取数据:

package com.example.aidlClientdemo;

import com.example.aidlservicedemo.domain.IDog;

import android.app.Activity;import android.content.ComponentName;

import android.content.Intent;import android.content.ServiceConnection;

import android.os.Bundle;import android.os.IBinder;

import android.view.View;import android.view.View.OnClickListener;

import android.widget.Button;import android.widget.Toast;

public class BaseTypeActivity extends Activity {

private Button btn_startService, btn_endService,btn_getServiceData;private IDog dogService;

@Override

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);

setContentView(R.layout.activity_service);

btn_startService = (Button) findViewById(R.id.btn_startService);btn_endService = (Button) findViewById(R.id.btn_endService);

btn_getServiceData = (Button) findViewById(R.id.btn_getServiceData);

btn_startService.setOnClickListener(click);btn_endService.setOnClickListener(click);

btn_getServiceData.setOnClickListener(click);}

private View.OnClickListener click = new OnClickListener() {

@Override

public void onClick(View v) {switch (v.getId()) {

case R.id.btn_startService:startService();

break;case R.id.btn_endService:

endService();break;

case R.id.btn_getServiceData:getServiceDate();

break;}

}};

/** 获取数据

*/private void getServiceDate() {

try {if(dogService!=null){

StringBuilder sBuilder=new StringBuilder();sBuilder.append("name:"+dogService.getName());

sBuilder.append("\nage:"+dogService.getAge());Toast.makeText(BaseTypeActivity.this, sBuilder.toString(), Toast.LENGTH_SHORT).show();

}else

{Toast.makeText(BaseTypeActivity.this, "请先绑定办事", Toast.LENGTH_SHORT).show();

}} catch (Exception e) {

e.printStackTrace();}

}

private ServiceConnection connBase=new ServiceConnection() {

@Overridepublic void onServiceDisconnected(ComponentName name) {

dogService=null;}

@Override

public void onServiceConnected(ComponentName name, IBinder service) {// IDog.Stub.asInterface,获取接口

dogService=IDog.Stub.asInterface(service);}

};

/奸淫 开始办事

*/private void startService(){

Intent intent=new Intent();intent.setAction("cn.bgxt.Service.BASE_TYPE_SERVICE");

bindService(intent, connBase, BIND_AUTO_CREATE);Toast.makeText(BaseTypeActivity.this, "开始绑定办事", Toast.LENGTH_SHORT).show();

}/**

* 竣事办事*/

private void endService(){if(connBase!=null)

{unbindService(connBase);

// 打仗绑定的时刻必要收受接收dogService连接资本// 在源码中漏了,这是后来加上的

dogService=null;Toast.makeText(BaseTypeActivity.this, "办事解除绑定", Toast.LENGTH_SHORT).show();

}}

}

效果展示:先运行办事利用,再运行客户端利用。

源码下载

总结

本文只先容了AIDL的基础布局,以及若何经由过程AIDL接口通报一个系统内置类型的数据。下一篇将先容一下AIDL的高档利用,若何通报一个自定义工具。

您可能还会对下面的文章感兴趣: