最近做項目一直沒能理解清楚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(); } }
運行結果: