启动的时候
Intent i= new Intent(MainActivity.this, MyService.class);
i.putExtra("data",editText.getText().toString());
startService(i);
在MyService里面,因为之前是startService,与之对应的是onStartCommand,所以在这里面接受数据就好啦
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
data = intent.getStringExtra("data");
return super.onStartCommand(intent, flags, startId);
}
启动一次服务,输入文本,再次点击启动按钮
10-16 22:07:03.825 10312-10312/com.jackie.courseservice V/jackie﹕ 开始服务
10-16 22:07:03.830 10312-10312/com.jackie.courseservice V/jackie﹕ Service created
10-16 22:07:03.830 10312-10312/com.jackie.courseservice V/jackie﹕ Command started
10-16 22:07:03.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...默认信息
10-16 22:07:05.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:07.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:09.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:11.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:13.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:15.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:17.840 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:19.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...
10-16 22:07:20.630 10312-10312/com.jackie.courseservice V/jackie﹕ 开始服务
10-16 22:07:21.835 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...修改后再次启动
10-16 22:07:23.840 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...修改后再次启动
10-16 22:07:25.840 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...修改后再次启动
10-16 22:07:27.840 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...修改后再次启动
10-16 22:07:29.840 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...修改后再次启动
10-16 22:07:31.840 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...修改后再次启动
10-16 22:07:33.840 10312-10746/com.jackie.courseservice V/jackie﹕ 服务正在运行...修改后再次启动
10-16 22:07:33.920 10312-10312/com.jackie.courseservice V/jackie﹕ 停止服务
10-16 22:07:33.925 10312-10312/com.jackie.courseservice V/jackie﹕ Service destroyed
除了使用Intent进行通信,也可以通过Service中的Binder来通信,这里就需要将Activity和Service绑定(bind)在一起了
1、绑定服务
bindService(new Intent(MainActivity.this, MyService.class), this, BIND_AUTO_CREATE);
2、Service中设置一个成员变量data,来呈现两边数据的同步,并且,在Service创建后启动一个线程,不停地打印这个data,观察它的变化
public String data = "默认信息";
...
while (isRunning){
Log.v("jackie","服务正在运行..."+data);
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
3、关键:在Service里面自己写一个MyBinder,继承Binder,里面写一个方法,用来设置成员变量data的值,并且,在onBind(Intent intent)
方法里面返回这个自己定义的MyBinder
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
这个返回的自定义Binder就是Service和Activity沟通的桥梁
4、由于在为MainActivity绑定Service的时候,是将MainActivity作为一个ServiceConnection传参,所以在这个必须重写的方法里,IBinder service
其实就是之前返回的MyBinder
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//这里的binder用于接受onBinder返回的MyBinder
binder = (MyService.MyBinder) service;
}
5、通过这个binder,来在按钮点击事件里改变Service中data的值
binder.setData(editText.getText().toString());
这样就实现了在Activity里面改变Service中的成员变量,关键就在于这个binder
10-16 21:57:25.795 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...默认信息
10-16 21:57:27.795 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...默认信息
10-16 21:57:29.800 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...默认信息
10-16 21:57:31.795 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...默认信息
10-16 21:57:31.960 27876-27876/com.jackie.courseservice W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
10-16 21:57:33.800 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...默认信息
10-16 21:57:35.540 27876-27876/com.jackie.courseservice V/jackie﹕ 同步数据
10-16 21:57:35.795 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...我是绑定后修改的值
10-16 21:57:37.795 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...我是绑定后修改的值
10-16 21:57:39.795 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...我是绑定后修改的值
10-16 21:57:41.800 27876-5582/com.jackie.courseservice V/jackie﹕ 服务正在运行...我是绑定后修改的值
上面我们通过binder对Service里面的数据进行了访问操作,并且在LogCat里面打印了这个数据,那么如果不想看Log,直接把数据呈现在用户可以交互到的Activity岂不是更加方便吗,所以,这里可以尝试一下,如何侦听被绑定的 Service 的内部状态。
还是之前的打印线程,给一个count,每次加一
...
count++;
Log.v("jackie","服务正在运行..."+count);
...
在Activity里面弄一个显示区域显示这个count
这个实现的关键就是:回调机制 Callback,Service里面那个自己定义的MyBinder里面写一个获取当前Service的方法
public MyService getService() {
return MyService.this;
}
然后定义一个接口Callback,并且该Service要有一个Callback类型的成员变量
private Callback callback;
public static interface Callback {
public void onDataChange(String data);
}
然后线程打印的时候,循环里面有一句
count++;
if (callback != null) {
callback.onDataChange("服务正在运行..." + count);
}
在Activity中通过获取Callback并重写onDataChange方法就可以监听线程里面count的值了
由于其他线程是不可以改变UI线程的内容的,所以我们需要Handler来通知主线程改变TextView的内容
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MyService.MyBinder) service;
binder.getService().setCallback(new MyService.Callback() {
@Override
public void onDataChange(String data) {
Message msg = new Message();
Bundle b = new Bundle();
b.putString("data", data);
msg.setData(b);
handler.sendMessage(msg);
}
});
// Log.v("jackie", "Service Connected");
}
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
tvShow.setText(msg.getData().getString("data"));
}
};
po主要说一句,Callback太特么好用了!Activity可以为自己给绑定的Service的Callback重写自己需要的功能,然后MyService启动之后它的Callback执行的就是重写过的功能了。