最近做项目一直没能理解清楚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(); } }
运行结果: