尊重原创,转载请注明出处:javascript:void(0)

使用场景

由于业务需求,可能我们在开发Android SDK项目的时候会遇到这样一种情况,就是当手机ROM中有多个应用需要调用同一个sdk。当然将我们的sdk每个应用放一个jar包不太合适,如何做到只用一份sdk供所有的应用调用呢?可以想到的方案是,我们将我们的sdk放到自己的apk中封装一下,然后让其他应用都调用同一个apk开放的接口。那么问题来了,如何调用外部应用的接口呢,这就涉及到我们今天讲的主题--使用AIDL的方式进行进程间的通信。

基本原理

什么是AIDL?
Android 进程通信之AIDL_Android进程间通信
简单说明一下,首先我们的了解一下Android中进程间通信的binder机制,其实就是client-server的形式,而binder就是其中的介质。在aidl的客户端我们通过AIDLService.Stub.asInterface获取到服务端service的代理,然后通过代理调用服务端对应的方法,代理会将参数序列化传递到binder驱动中,server端的service会去binder驱动中读取数据,读到是传给自己的参数就打包被序列化的数据,然后在server端执行。

简单示例:

client端:
package com.example.testaidlclient;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.testaidlserver.MyAIDLService;
import com.example.testaidlserver.ShopItem;

public class MainActivity extends Activity implements OnClickListener {
	
	private Button bind,get;
	private TextView tv_shopItem;
	private ShopItem shopItem;
	private MyAIDLService mRemoteService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        tv_shopItem = (TextView) findViewById(R.id.tv_shopItem);
        get = (Button) findViewById(R.id.getShopItem);
        bind = (Button) findViewById(R.id.bindRemoteService);
        bind.setOnClickListener(this);
        get.setOnClickListener(this);
    }

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.bindRemoteService:
			this.bindService(new Intent("com.example.remoteservice"), conn, Context.BIND_AUTO_CREATE);
			break;
			
		case R.id.getShopItem:
			if (mRemoteService != null) {
				try {
					shopItem = mRemoteService.getShopItem();
					tv_shopItem.setText("ShopItem:"+"id="+shopItem.getId()+"\nshopName="+shopItem.getName());
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
			break;

		default:
			break;
		}
	}
	
	private ServiceConnection conn = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mRemoteService = MyAIDLService.Stub.asInterface(service);
			try {
				mRemoteService.startDetailActivity();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
	};
    
}

服务端:
package com.example.testaidlserver;

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

/**
 * @author YULORE-USER
 */
public class RemoteService extends Service {
	public static String TAG = RemoteService.class.getSimpleName();

	@Override
	public IBinder onBind(Intent intent) {
		return mRemoteServiceBinder;
	}
	
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(TAG, "onStartCommand is called!");
		return super.onStartCommand(intent, flags, startId);
	};
	
	MyAIDLService.Stub mRemoteServiceBinder = new MyAIDLService.Stub(){

		@Override
		public void startDetailActivity() throws RemoteException {
			ComponentName cn = new ComponentName("com.example.testaidlserver", "com.example.testaidlserver.ShopDetailActivity");
			Intent intent = new Intent("com.example.testaidlserver.shopdetail");
			intent.setComponent(cn);
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			startActivity(intent);
		}

		@Override
		public ShopItem getShopItem() throws RemoteException {
			ShopItem item = new ShopItem();
			item.setId(100);
			item.setName("remote service");
			return item;
		}
		
	};

}

AIDL文件:
MyAIDLService.aidl
package com.example.testaidlserver;

import com.example.testaidlserver.ShopItem;
 
interface MyAIDLService {  
     void startDetailActivity();
     ShopItem getShopItem();
}
ShopItem.aidl
package com.example.testaidlserver; 

parcelable ShopItem;

ShopItem.java
package com.example.testaidlserver;

import android.os.Parcel;
import android.os.Parcelable;

public class ShopItem implements Parcelable{
	private String name;
	private int id;
	
	public ShopItem(){}
	
	public ShopItem(Parcel par){
		id = par.readInt();
		name = par.readString();
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public int getId() {
		return id;
	}
	
	public void setId(int id) {
		this.id = id;
	}
	
	@Override
	public int describeContents() {
		return 0;
	}
	
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeInt(id);
		dest.writeString(name);
	}
	
	public static final Parcelable.Creator<ShopItem> CREATOR = new Creator<ShopItem>() {
		
		@Override
		public ShopItem[] newArray(int size) {
			
			return new ShopItem[size];
		}
		
		@Override
		public ShopItem createFromParcel(Parcel source) {
			return new ShopItem(source);
		}
	};
	
}

具体测试客户端和服务端源码可点击这里下载:
服务端: javascript:void(0)
客户端: javascript:void(0)