【原创】Android aidl实现两个apk之间远程调用Service

Aidl,android平台的IPC方式之一,基于系统的Ibinder机制。
网上大多数例子都是在一个apk下来测试调用service,现在我在两个project下面来调用。
一个是server project,一个是client project
首先我们建立的是server project,这里面要实现aidl文件和一个service,activity只是用来启动service的,当然,你也可以通过发广播的形式来启动service。
首先看IAidlService.aidl文件:
package com.ds.server;
interface IAidlService {  
    int getType(); 
}  


这样在eclipse里面自动编译的时候会在gen下面生成IAidlService.java文件(灯下我们的client project要用)。
然后新建一个service,这个service里面has a IAidlService的stub对象,service具体代码如下:
package com.ds.server;

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

public class AidlService extends Service {

	private IAidlService.Stub mBinder = new IAidlService.Stub() {

		@Override
		public int getType() throws RemoteException {
			// TODO Auto-generated method stub
			return 5;
		}
	};

	private void Log(String str) { 
		Log.d("AidlService", "------ " + str + "------");
	}

	@Override
	public void onCreate() {
		Log("service create");   
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log("service start id=" + startId);
	}

	@Override
	public IBinder onBind(Intent t) {
		Log("service on bind");
		return mBinder;
	}

	@Override
	public void onDestroy() {
		Log("service on destroy");
		super.onDestroy();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		Log("service on unbind");
		return super.onUnbind(intent);
	}

	public void onRebind(Intent intent) {
		Log("service on rebind");
		super.onRebind(intent);
	}

}

这里一定要实现onBind方法,并返回一个IAidlService.Stub对象。
再去AndroidManifest.xml注册这个service:
<service
            android:name=".AidlService"
            android:enabled="true"
            android:process=":remote" >
            <intent-filter>
                <action android:name="com.ds.server.IAidlService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>


android:enabled="true"
android:process=":remote"这两个标签可有可无。
只要注册了这个service就行。
好了,到此,服务端已经完成。

-------------------华丽的分割线-----------------------------------------

下面我们开始client project。
client project比较简单,需要注意的地方是,首先需要把server project中gen文件夹中aidl生成的那个IAidlService.java类以及包都拷贝到我们的client project中。
(注意: client project的包名为com.ds.client;另外一个包名com.ds.server以及这个server包下面的IAidlService.java类都是从server project的gen文件夹拷贝过来的,至于gen文件夹的其他文件就不需要拷贝过来。)。
好了,这样的话,client project只要从activity去远程调用service就好了,实现代码如下:
package com.ds.client;

import com.ds.server.IAidlService;

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.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AidlClientActivity extends Activity {

	IAidlService iservice; 

	private ServiceConnection connection = new ServiceConnection() {

		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			// 从远程service中获得AIDL实例化对象
			iservice = IAidlService.Stub.asInterface(service);
			Log.i("Client","Bind Success:" + iservice);
		}  

		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			iservice = null;
			Log.i("Client","onServiceDisconnected");
		}
	};  
  
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {  
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		final TextView tv = (TextView) findViewById(R.id.tv);
		Button bt = (Button) findViewById(R.id.bt);
		bt.setOnClickListener(new OnClickListener() {
			

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				Intent service = new Intent(IAidlService.class.getName());
				bindService(service, connection, BIND_AUTO_CREATE);
				if (iservice != null) {  
					try {
						tv.setText("" + iservice.getType());
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				}

			}

		});

	}
}


注意几点:
1,import com.ds.server.IAidlService;使用的是我们拷贝过来的IAidlService.java类
2,需要一个ServiceConnection对象
3,通过Intent service = new Intent(IAidlService.class.getName());
bindService(service, connection, BIND_AUTO_CREATE);来bind service。这样就可以调用aidl中定义的接口来获取service中的值了。

唉,由于在使用中没有注意拷贝server project中gen文件夹下面的包和IAidlService.java,老是出现Unable to start service Intent这样的错误。搞了好久。
附件是源码。注意使用的时候,先要运行server project,启动服务,然后再运行client project。

参考资料: http://www.cnblogs.com/TerryBlog/archive/2010/08/24/1807605.html

你可能感兴趣的:(android)