Android中Service和Activity之间的通信
启动Service并传递数据进去:
Android中通过Intent来启动服务会传递一个Intent过去。
可以在Intent中通过putExtra()携带数据
Intent startIntent = new Intent(MainActivity.this, MyService.class); startIntent.putExtra("data", etData.getText().toString()); startService(startIntent);
在Service的onStartCommand中得到的Intent中获取这个传递过去的数据
@Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("Service.onStartCommand()"); data = intent.getStringExtra("data"); return super.onStartCommand(intent, flags, startId); }
绑定Sevice并传递数据进去:
当通过绑定启动服务的时候可以用另一种方式把Activity中的数据传递到Service中。
首先在Service中定义一个Binder类,继承自系统的Binder类,然后在onBind中返回这个类的一个实例。
public class MyBinder extends android.os.Binder{ public void setData(String data){ MyService.this.data = data; } public MyService getService(){ return MyService.this; } } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. System.out.println("Service.onBind()"); return new MyBinder(); }
这个类的实例就会在Activity中onServiceConnected中的第二个参数返回,因此也就可以在Activity中用一个实例变量保存它,并调用里面的函数。
private MyService.MyBinder myBinder; @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { myBinder = (MyService.MyBinder)iBinder; } @Override public void onClick(View view) { ... case R.id.btnSyncData: if (myBinder != null) myBinder.setData(etData.getText().toString()); }
通过这种方式就可以把Activity中的数据传递给Service,这种方法要比直接用Intent传递要高效。
把Service中的数据传递出来:
还是利用刚刚在Sercie中创建的Binder类,用它返回一个Service的实例:
public class MyBinder extends android.os.Binder{ public void setData(String data){ MyService.this.data = data; } public MyService getService(){ return MyService.this; } }
同时在Service中定义一个钩子函数,用来给Activity取得Service的内部数据:
private CallBack callBack; public CallBack getCallBack() { return callBack; } public void setCallBack(CallBack callBack) { this.callBack = callBack; } public interface CallBack{ void callBackFunc(String str); }
通过这种方法Service就可以调用这个CallBack方法:
if(callBack != null) callBack.callBackFunc(str);
在Activity中得到了这个Service的实例以后就可以给它设置一个CallBack实例,这样每次Service调用这个函数就可以把这个数据发送出来:
@Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { myBinder = (MyService.MyBinder)iBinder; myBinder.getService().setCallBack(new MyService.CallBack() { @Override public void callBackFunc(String str) { Message message = new Message(); Bundle b = new Bundle(); b.putString("data", str); message.setData(b); handler.sendMessage(message); } }); }
可以用它来更新UI:
private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { tvOut.setText(msg.getData().getString("data")); } };