Android远程service aidl的用法
AIDL即android 接口定义语言,概念不多说,网上有太多的帖子介绍概念。本文只想说明一下aidl的用法。由于最近开发一个播放器的项目使用了aidl。aidl是解决进程间通信用的。在本例中就是Activity(即client端)与Service(即服务端)的通信。
首先,定义Aidl文件,如Service中暴露给Activity的接口可以定义在aidl文件中,反之也一样。本文中,Service给Activity使用接口文件是ServiceAidl.aidl而Activity给Service回调的接口在ActivityAidl.aidl文件中
package org.august.music;
import org.august.music.ActivityAidl;
interface ServiceAidl{
package org.august.music;
interface ActivityAidl{
void callActivity();
}
第二步,写Service。写一个MyService继承于Service类,并在onBind()方法中 返回ServiceAidl.Stub对象
具体看下面代码
package org.august.music;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
public static final String SERVICE_NAME = "org.august.music.start.MyService";
private static final String TAG = "MyService";
private ActivityAidl activityAidlCallBack;
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "onStart");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
Log.i(TAG, "onRebind");
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
return super.onUnbind(intent);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private ServiceAidl.Stub mBinder = new ServiceAidl.Stub() {
@Override
public void callService() throws RemoteException {
Log.i(TAG, "Call Service's method ****** callService()");
Toast.makeText(getApplicationContext(), "Call Service's method ****** callService()", 1000).show();
activityAidlCallBack.callActivity();
}
@Override
public void registActivityAidl(ActivityAidl activityAidl)
throws RemoteException {
activityAidlCallBack = activityAidl;
}
};
}
说明一下在ServiceAidl.Stub mBinder = new ServiceAidl.Stub(){}里面的callService() 和registActivityAidl(ActivityAidl activityAidl)方法就是在Activity将会被调用到的。而registActivityAidl(ActivityAidl )是在Activity中给Service的回调方法注册到Service中去,这样Service中就可以调用Activity的接口了
package org.august.music;
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.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private Button startBtn;
private Button stopBtn;
private Button callServiceBtn;
private ServiceAidl myService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
init();
}
private void init() {
startBtn = (Button)findViewById(R.id.start_service);
stopBtn = (Button)findViewById(R.id.stop_service);
callServiceBtn = (Button)findViewById(R.id.call_service_method);
startBtn.setOnClickListener(btnListener);
stopBtn.setOnClickListener(btnListener);
callServiceBtn.setOnClickListener(btnListener);
}
private View.OnClickListener btnListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.start_service:
startService();
break;
case R.id.stop_service:
stopService();
break;
case R.id.call_service_method:
if(myService == null){
Toast.makeText(getApplicationContext(), "Service 为空", 1000).show();
return;
}
try {
myService.callService();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
};
private void startService() {
Intent intent = new Intent();
intent.setAction(MyService.SERVICE_NAME);
bindService(intent, serviceConn, Context.BIND_AUTO_CREATE);
startService(intent);
Log.i(TAG, "********startService()");
}
private void stopService() {
}
private ServiceConnection serviceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
myService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = ServiceAidl.Stub.asInterface(service);
try {
myService.registActivityAidl(activityAidl);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
private ActivityAidl activityAidl = new ActivityAidl.Stub() {
@Override
public void callActivity() throws RemoteException {
Log.i(TAG, "callActivity()");
Toast.makeText(getApplicationContext(), "call activity", 1000).show();
}
};
}
在activity中有三个按钮分别为 start service ; stop service ;callService
各个按钮的动作顾名思义啦。在Activity中会看到在ServiceConnection中 会拿到ServiceAidl (myService)的实例
并且将activityAidl的引用注册到了myService中
这个程序跑起来的顺序是,启动Activity后,并start service后 点击callServiceBtn,就会调用MyService中实现的callService()接口,而在callService中又调用了activityAidl即Activity的回调callActivity()的
这样就模拟了 Activity 与Service两个进程间的通信,即相互调用了对方的对象。