代码改变世界

[原] android Service 跨进程通信

2011-09-29 22:31  雪夜&流星  阅读(2592)  评论(3编辑  收藏  举报

最近做项目一直没能理解清楚Service是如何跨进程通信的,既然是跨进程通信,那么也就意味着多个app可以通过一个Service服务进行数据的交互了。带着这些猜想,花了一天的时间终于把这个猜想实现了。关于Service的生命周期就不说了,网上一大堆。

本地Activity和Service之间的交互demo:

首先定义一个接口,用来进行数据之间的交互。

IService .java


package com.tanlon.localservice;

public interface IService {
long getCurrentTime();
}


接着完成Service类:

package com.tanlon.localservice;

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

public class LocalService extends Service{
//log标记
private static final String TAG="MyService";
//获取绑定接口
private MyBind myBind=new MyBind();

public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "localService onBind");
return myBind;
}

public void onCreate() {
// TODO Auto-generated method stub
Log.d(TAG, "localService onCreate");
super.onCreate();
}

public void onDestroy() {
// TODO Auto-generated method stub
Log.d(TAG, "localService onDestroy");
super.onDestroy();
}

public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
Log.d(TAG, "localService onStart");
super.onStart(intent, startId);
}

public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "localService onUnbind");
return super.onUnbind(intent);
}
//本地服务中的绑定
public class MyBind extends Binder implements IService{

public long getCurrentTime() {
// TODO Auto-generated method stub
return System.currentTimeMillis();
}

}

}

本地调用Service:

package com.tanlon.localservice;

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

public class LocalServiceActivity extends Activity {
private IService iService=null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button startServiceButton=(Button) findViewById(R.id.startServiceButton);
Button stopServiceButton=(Button) findViewById(R.id.stopServiceButton);
Button bindServiceButton=(Button) findViewById(R.id.bindServiceButton);
Button unbindServiceButton=(Button) findViewById(R.id.unbindServiceButton);
startServiceButton.setOnClickListener(onClickListener);
stopServiceButton.setOnClickListener(onClickListener);
bindServiceButton.setOnClickListener(onClickListener);
unbindServiceButton.setOnClickListener(onClickListener);
}

private OnClickListener onClickListener=new OnClickListener() {

public void onClick(View v) {
// TODO Auto-generated method stub
int id=v.getId();
switch (id) {
case R.id.startServiceButton://启动服务(这里用到getApplicationContext是为了提升应用等级,避免出现“android.app.ServiceConnectionLeaked”这样的错误)
startService(new Intent(getApplicationContext(), LocalService.class));
break;
case R.id.stopServiceButton://停止服务(这里用到getApplicationContext是为了提升应用等级,避免出现“android.app.ServiceConnectionLeaked”这样的错误)
stopService(new Intent(getApplicationContext(), LocalService.class));
break;
case R.id.bindServiceButton://绑定服务
bindservice();
break;
case R.id.unbindServiceButton://解绑定
unbindService(connection);
break;
default:
break;
}
}
};

//绑定服务
private void bindservice() {
// TODO Auto-generated method stub
//这里用到getApplicationContext是为了提升应用等级,避免出现“android.app.ServiceConnectionLeaked”这样的错误
Intent intent=new Intent(getApplicationContext(), LocalService.class);
this.bindService(intent, connection, BIND_AUTO_CREATE);
}

//连接服务接口
ServiceConnection connection=new ServiceConnection() {

public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
iService=null;
}

public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//获取连接的服务对象
iService=(IService) service;
//调用服务,获取服务中的接口方法
if(iService!=null)
Log.d("MyService", "iService bindService getCurrentTime"+iService.getCurrentTime());
}
};

protected void onDestroy() {
// TODO Auto-generated method stub
Log.d("MyService", "localServiceActivity onDestroy");
super.onDestroy();
}


}

最后在mainfest中注册服务:

<service android:name="com.tanlon.localservice.LocalService"></service>

运行效果:

运行结果:

 

跨进程通信:

第一步:建立服务端(ServiceServer) :配置aidl接口

package com.tanlon.server;

interface IService {
long getCurrentTime();
void setValue(in String from,in int value);
String getValue();
}

配置服务类

package com.tanlon.server;

import com.tanlon.server.IService.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service{
//log标记
private static final String TAG="MyService";

private String str;

private IService.Stub bind=new Stub() {

public long getCurrentTime() throws RemoteException {
// TODO Auto-generated method stub
return System.currentTimeMillis();
}

public void setValue(String from, int value) throws RemoteException {
// TODO Auto-generated method stub
str="value from-------"+from+" and value is-------"+value;
Log.d(TAG, "ServiceServer setValue from-------"+from+" value is-------"+value);
}

public String getValue() throws RemoteException {
// TODO Auto-generated method stub
return str;
}
};

public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "ServiceServer onBind");
return bind;
}

public void onCreate() {
// TODO Auto-generated method stub
Log.d(TAG, "ServiceServer onCreate");
super.onCreate();
}

public void onDestroy() {
// TODO Auto-generated method stub
Log.d(TAG, "ServiceServer onDestroy");
super.onDestroy();
}

public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
Log.d(TAG, "ServiceServer onStart");
super.onStart(intent, startId);
}

public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "ServiceServer onUnbind");
return super.onUnbind(intent);
}

}

第二步:配置客户端1(ServiceClientOne):用来和服务端、其他的客户端交互数据(此处主要通过Service来设置值,其他的进程则通过Service来取这里设置的值)。

先将服务端的com.tanlon.server包以及其下的IService.aidl一起拷到客户端下面来。

接着就是客户端连接Service的代码:

package com.tanlon.client;

import java.text.SimpleDateFormat;
import com.tanlon.server.IService;
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;

public class ServiceClientActivity extends Activity {
private IService iService=null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//绑定服务,获取远程服务
bindService(new Intent(IService.class.getName()), connection, BIND_AUTO_CREATE);
}
//连接服务
private ServiceConnection connection=new ServiceConnection() {

public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
iService=null;
}

public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//获取绑定的接口
iService=IService.Stub.asInterface(service);
try {
if(iService!=null){
//调用远程服务中的方法
long date=iService.getCurrentTime();
Log.d("MyService", "IService getCurrentTime------"+getDate(date));
//为交互进程间的交互设置值
iService.setValue(ServiceClientActivity.class.getName(), 10);
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

};
//将long型系统时间转换成当前时间
private String getDate(long date){
SimpleDateFormat formatter;
formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
String ctime = formatter.format(date);
return ctime;
}

protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(connection);
super.onDestroy();
}


}


第三步:配置客户端2(ClientDemo):通过Service来获取
客户端1设置的值。

先将服务端的com.tanlon.server包以及其下的IService.aidl一起拷到客户端下面来。

接着就是客户端连接Service的代码:

package com.tanlon.clientdemo;

import java.text.SimpleDateFormat;

import com.tanlon.server.IService;

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;

public class ClientDemoActivity extends Activity {
private IService iService=null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bindService(new Intent(IService.class.getName()), connection, BIND_AUTO_CREATE);
}
//连接服务
private ServiceConnection connection=new ServiceConnection() {

public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
iService=null;
}

public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//获取绑定的接口
iService=IService.Stub.asInterface(service);
try {
if(iService!=null){
//调用远程服务中的方法
long date=iService.getCurrentTime();
Log.d("MyService", "IService getCurrentTime------"+getDate(date));
//获取进程间的交互值
String str=iService.getValue();
Log.d("MyService", "IService getValue------"+str);
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

};
//将long型系统时间转换成当前时间
private String getDate(long date){
SimpleDateFormat formatter;
formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
String ctime = formatter.format(date);
return ctime;
}

protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(connection);
super.onDestroy();
}
}

运行结果:

 

 

 

 

注:不知道如何上传压缩包,各位如果需要的话,给我留言,我的QQ:745228153。