您的位置:首页 > 移动开发 > Android开发

Android应用:Service开发实例(一)之AIDL和远程调用

2015-08-14 09:17 731 查看
在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实现呢? 显然, Java中是不支持跨进程内存共享的。因此要传递对象, 需要把对象解析成操作系统能够理解的数据格式, 以达到跨界对象访问的目的。在JavaEE中,采用RMI通过序列化传递对象。在Android中, 则采用AIDL(Android Interface Definition Language:接口描述语言)方式实现。

AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。AIDL的IPC 机制和EJB所采用的CORBA很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应 的对象。由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员
来说是透明的。

下边通过一个简单的例子来说明两个应用之间怎么使用aidl来通信。

一、服务器端开发

新建一个应用。

1、新建一个AIDL接口文件IMyAidlInterface.aidl

package com.dlq.myservice;

interface IMyAidlInterface {
void ServiceTest();
}
这个AIDL在编译时会自动生成一个IMyAidlInterface.java文件

/*
* This file is auto-generated.  DO NOT MODIFY.
* Original file: G:\\Android\\AndroidStudioProjects\\MyService\\app\\src\\main\\aidl\\com\\dlq\\myservice\\IMyAidlInterface.aidl
*/
package com.dlq.myservice;
// Declare any non-default types here with import statements

public interface IMyAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.dlq.myservice.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.dlq.myservice.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.dlq.myservice.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.dlq.myservice.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.dlq.myservice.IMyAidlInterface))) {
return ((com.dlq.myservice.IMyAidlInterface)iin);
}
return new com.dlq.myservice.IMyAidlInterface.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_ServiceTest:
{
data.enforceInterface(DESCRIPTOR);
this.ServiceTest();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.dlq.myservice.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void ServiceTest() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_ServiceTest, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_ServiceTest = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void ServiceTest() throws android.os.RemoteException;
}


2、新建一个Service

package com.dlq.myservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service {
private static final String TAG = "MyService";

private MyServiceImpl mService;

public MyService() {
Log.d(TAG, "MyService");
}

@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "MyService onCreate");
//在onCreate中实例化一个service
mService = new MyServiceImpl();
}

@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d(TAG, "MyService onStart");
}

@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "MyService onBind");
//在onBind中返回这个service的实例
return mService;
}
//实现aidl文件生成的接口(IMyAidlInterface),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。
private class MyServiceImpl extends IMyAidlInterface.Stub
{
@Override
public void ServiceTest() throws RemoteException {
Log.d(TAG, "MyService ServiceTest");
}
}
}
3.在AndroidManifest.xml中添加服务

<service
android:name=".MyService"
android:enabled="true"
android:exported="true" >
</service>


二、客户端开发

新建另一个应用。

1、新建一个IMyAidlInterface.aidl文件,所在的包名必须和服务器端完全一致

2、在AndroidManifest.xml中添加服务

<service
android:name="com.dlq.myservice.IMyAidlInterface"
android:enabled="true"
android:exported="true" >
</service>
3、在Activity中的按钮中添加代码,通过bindservice启动服务
Intent intent = new Intent();
//这里通过包名和类名启动服务,也可以通过Action来启动
intent.setClassName("com.dlq.myservice","com.dlq.myservice.MyService");
//android5.0以后必须显示启动服务,intent中需要添加包名
intent.setPackage(getPackageName());

bindService(intent, con, BIND_AUTO_CREATE);
4、客户端绑定service时在ServiceConnection.onServiceConnected获取onBind返回的IBinder
对象

private IMyAidlInterface mService;
ServiceConnection con = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IMyAidlInterface.Stub.asInterface(service);
Log.d(TAG, "MyClient mService="+mService);
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};
5、在另一个按钮中调用Service中实现的接口
try {
mService.ServiceTest();
} catch (RemoteException e) {
e.printStackTrace();
}
6、使用unbindService解除绑定

this.unbindService(con);


三、运行效果

绑定服务

08-14 20:20:25.222    6831-6831/com.dlq.myservice D/MyService﹕ MyService
08-14 20:20:25.222    6831-6831/com.dlq.myservice D/MyService﹕ MyService onCreate
08-14 20:20:25.223    6831-6831/com.dlq.myservice D/MyService﹕ MyService onBind


调用服务接口
08-14 20:20:28.662    6831-6847/com.dlq.myservice D/MyService﹕ MyService ServiceTest
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: