首页 > 代码库 > android开发系列之aidl

android开发系列之aidl

      aidl在android开发中的主要作用就是跨进程通讯来着,说到进程相比很多人都是非常熟悉了,但是为什么会有跨进程通讯这个概念呢?原来在android系统中,有这么一套安全机制,为了各个Apk数据的独立性、安全性,它们彼此之间是不能直接进行数据的访问的。所以为了实现多个APK之间的数据、方法、代码复用,我们通常采用的做法就是定义好AIDL接口,这样就能够既保护现有代码的逻辑性、同时又能够兼顾好封装性,各个团队之间只需要沟通好AIDL接口定义就可以了。

      下面让我们直接进入主题吧,在进行AIDL定义的时候,通常会将公用的代码逻辑单独封装到一个独立的APK中,这个APK我们不妨成为服务器Server。当定义好Server断逻辑之后,就可以供其他第三方代码调用了,这个第三方Apk我们不妨成为Client。但是Server和Client方,必须同时保证AIDL文件名称相同,同时又在相同的包名下面。只有同时满足这两点的话,才能利用AIDL进行通讯。

      假如有一套公用的计算方法,在多个第三方APK中都需要调用。所以定义两个android project,一个服务端程序AidlServer,一个客户端测试程序TestClient。其中服务端、客户端的AIDL接口文件都位于包“com.example.aidl下面”,定义好ICal.aidl文件,代码如下:

package com.example.aidl;

interface ICal{
    double doCal(double x,double y);
}

 在定义书写aidl文件代码的时候,语法规则跟java一致,切记不要忘记引入package或者少写了分号。当定义好aidl文件之后,并且没有错误的情况下,按住ctrl+s键保存编译,会发现项目的gen文件夹下面会自动生成一个同名的java文件。如果到这一步正确的生成了java文件的话,那么说明服务端,客户端的AIDL接口部分已经定义完成,那么接下来怎么将服务端的接口暴露给客户端调用呢?答案是通过service,我们先来看一下service端的CalService代码:

package com.example.service;

import com.example.aidl.ICal;

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

public class CalService extends Service {

	private static final String TAG = CalService.class.getName();

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	@Override
	public void onCreate() {
		Log.d(TAG,"onCreate action");
		super.onCreate();
	}

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

	@Override
	public void onDestroy() {
		Log.d(TAG, "onDestroy");
		super.onDestroy();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		Log.d(TAG, "onUnbind");
		return super.onUnbind(intent);
	}
	
	private final ICal.Stub mBinder=new ICal.Stub() {
		
		@Override
		public double doCal(double x, double y) throws RemoteException {
			CalUtils calUtils=new CalUtils();
			double result=calUtils.add(x, y);
			return result;
		}
	};
	
}

 通过CalService可以很好的暴露CalUtils公用类里面的计算方法,CalUtils代码如下:

package com.example.service;

public class CalUtils{

      public double add(double x,double y){
            return x+y;
      }
}

 最后还需要在AndroidManifest.xml文件里面注册CalService,代码如下:

<service 
      android:name="com.example.service.CalService">
     <intent-filter>
         <action android:name="com.example.service.CalService"/>
     </intent-filter>
</service>

      到这里,服务器端的代码逻辑就完了,下面开始Client的测试代码编写。首先定义好一个计算xml页面,里面放置两个EditText、一个TextView、一个Button、一个TextView,这块的xml代码就不放出来了,稍后demo里面有。主要来看看后台的Activity代码,如下:

package com.example.mytestpro;

import com.example.aidl.ICal;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class CalActivity extends Activity implements OnClickListener {

	private static final String TAG=CalActivity.class.getName();
	
	private EditText etX,etY;
	private Button btnCal;
	private TextView tvInfo;
	private ICal mService;
	
	private ServiceConnection mServiceConnection=new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			Log.d(TAG, "do Disconnected action");
			mService=null;
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			Log.d(TAG, "do Connected action");
			mService=ICal.Stub.asInterface(service);
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_calctivity);
		
		initView();
		setClick();
		startBindServiceAction();
	}
	
	private void startBindServiceAction(){
		Bundle args=new Bundle();
		Intent intent=new Intent("com.example.service.CalService");
		intent.setPackage("com.example.aidlserver");
		intent.putExtras(args);
		bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
	}
	
	private void initView(){
		etX=(EditText)findViewById(R.id.etX);
		etY=(EditText)findViewById(R.id.etY);
		btnCal=(Button)findViewById(R.id.btnCal);
		tvInfo=(TextView)findViewById(R.id.tvInfo);
	}
	
	private void setClick(){
		btnCal.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btnCal:
			excuteCalAction();
			break;

		default:
			break;
		}
	}
	
	private void excuteCalAction(){
		try {
			double x=Double.parseDouble(etX.getText().toString());
			double y=Double.parseDouble(etY.getText().toString());
			String result="result:"+mService.doCal(x, y);
			tvInfo.setText(result);
			tvInfo.setTextColor(Color.RED);
		} catch (Exception e) {
			Log.d(TAG, e.getMessage());
		}
	}
}

       有兴趣的读者,可点击下载服务端demo、客户端demo。

android开发系列之aidl