您的位置:首页 > 大数据 > 人工智能

使用AIDL实现进程通信

2014-04-23 14:36 288 查看
使用AIDL和远程服务实现进程通信

在Android中,每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实现呢?显然,java中是不支持垮进程内存共享的。因此要传递对象,需要把对象解析成操作系统能够理解的数据格式,以达到垮界对象访问的目的。在java ee中,采用RMI通过序列化传递对象。在android中,采用AIDL(Android Interface Definition Language:j接口定义语言)方式实现。

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

一、服务端的实现:

1、写一个AIDL文件:

package cn.license.android;

interface StudentRemote {
	String QueryStudent(int studentNo);
}


2、开发工具自动生成一个接口:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: C:\\Users\\Administrator\\workspace\\StudentRemoteService\\src\\cn\\license\\android\\StudentRemote.aidl
 */
package cn.license.android;
public interface StudentRemote extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements cn.license.android.StudentRemote
{
private static final java.lang.String DESCRIPTOR = "cn.license.android.StudentRemote";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an cn.license.android.StudentRemote interface,
 * generating a proxy if needed.
 */
public static cn.license.android.StudentRemote asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof cn.license.android.StudentRemote))) {
return ((cn.license.android.StudentRemote)iin);
}
return new cn.license.android.StudentRemote.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_QueryStudent:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
java.lang.String _result = this.QueryStudent(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements cn.license.android.StudentRemote
{
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 java.lang.String QueryStudent(int studentNo) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(studentNo);
mRemote.transact(Stub.TRANSACTION_QueryStudent, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_QueryStudent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public java.lang.String QueryStudent(int studentNo) throws android.os.RemoteException;
}


3、service的代码:

public class StudentRemoteService extends Service {
	
	private String[] students={"name1","name 2","name 3"};
	
	private IBinder binder = new StudentRemoteBinder();
	
	@Override
	public IBinder onBind(Intent intent) {
		return binder;
	}
	
	private String QueryStudentName(int studentNo){
		if(studentNo>0 && studentNo<=students.length){
			return students[studentNo-1];
		}
		return null;
	}
//继承开发工具自动生成的接口里面的一个类
	private final class StudentRemoteBinder extends StudentRemote.Stub{

		@Override
		public String QueryStudent(int studentNo) throws RemoteException {
			return QueryStudentName(studentNo);
		}
		
	}

}


4、配置service的action:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.license.android"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <service android:name=".StudentRemoteService">
            <intent-filter>
                <action android:name="cn.license.studentQuery"/>
            </intent-filter>
        </service>
    </application>

</manifest>


这里遇到一个问题,笔者写错了manifest 的 package,然后安装到设备上,后来改正确路劲了,还是报这个错误:java lang runtimeexception unable to instantiate service。直至在设备上删除这个服务,再安装它,重新启动设备,这个错误才消失。

二、客户端的实现

1、把服务端的aidl 文件(包括路劲)复制到 客户端;

2、客户端的代码实现:

public class MainActivity extends Activity {
	
	private ServiceConnection conn = new StudentServiceConnection();
	//private IStudentBinder studentService;
	private StudentRemote studentRemote;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//显示意图
		//Intent service = new Intent(this,StudentService.class);
		
		//隐式意图,此处用来激活远程服务
		Intent service = new Intent("cn.license.studentQuery");
		bindService(service, conn, BIND_AUTO_CREATE);
	}
	
	
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		unbindService(conn);
	}

	public void query(View v){
		EditText studentNoText = (EditText)this.findViewById(R.id.studentNo);
		int studentNo = Integer.valueOf(studentNoText.getText().toString());
		String studentName="";
		try {
			studentName = studentRemote.QueryStudent(studentNo);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//studentService.QueryName(studentNo);
		TextView studentNameText = (TextView) this.findViewById(R.id.studentName);
		studentNameText.setText(studentName);
	}
	
	private class StudentServiceConnection implements ServiceConnection{

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			//本地
			//studentService = (IStudentBinder)service;
			
			//远程 aidl
			studentRemote = StudentRemote.Stub.asInterface(service);
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			//studentService=null;
			studentRemote = null;
		}
		
	}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: