1.Service基础
(1)service的生命周期
(2)start---->stop调用:
(3)bind--->unbind调用:
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
flag:
@param flags Operation options for the binding. May be 0, * {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND}, * {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT}, * {@link #BIND_ALLOW_OOM_MANAGEMENT}, or * {@link #BIND_WAIVE_PRIORITY}.
问:当 flags 不等于 BIND_AUTO_CREATE 时,bindService还会自动启动service吗?
答:不会。
问:当 flags 不等于 BIND_AUTO_CREATE,调用bindService前service未启动。一段时间之后,service被start,此时系统还会尝试之前的bind动作吗?
答:会。
原文:https://blog.csdn.net/lxyyzm/article/details/54669334
所以当flag为0时,如果没有startService,只bindService,是不会启动并绑定服务的。
(3)先start后bind(flag = BIND_AUTO_CREATE):
先start后bind(flag = 0)和(flag = BIND_AUTO_CREATE)一样,点击start时,调用oncreate,onstratcommand。点击bind时,调用onbind。
(4)先bind(flag = BIND_AUTO_CREATE)后start
点击bind:调用oncreate,onbind。所以这个标记是会自动创建服务并绑定。
点击start:调用onstartcommand。
先bind(flag = 0)后start
点击bind:什么都不打印
点击start,调用如下,service被start,此时系统还会尝试之前的bind动作。
(5)当start和bind都调用后,怎么关闭:
先stop再unbind(bind的flag = 0):
点击stop后:
点击unbind后:什么都没有打印。
先stop再unbind(bind的flag = BIND_AUTO_CREATE):
点击stop:没有打印
点击unbind:
(6)先unbind(bind的flag = 0)再stop:
点击unbind,调用onunbind;
点击stop,调用ondestory。
先unbind(bind的flag = BIND_AUTO_CREATE)再stop和上面情况一样。按正常顺序,onunbind,ondestory执行。
总结:从(3)和(6)可以看出,当正常的start,bind,unbind, stop时,flag的值的两种情况是一样的,方法调用也是正常的。
从(4)和(5)可以看出,都是反方向的调用两个方法,想bind之前必须start服务,要么自己start(使用flag=BIND_AUTO_CREATE),要么手动调用start方法后,才能正常开启并绑定服务。
停止时。当flag=BIND_AUTO_CREATE,调stop没用,只有unbind时才会走ondestory销毁服务。当bind的flag = 0,点击stop会先调onunbind,再调ondestory。
2.activity传递数据给service
(1)intent方式
activity中:
intent = new Intent(ServiceActivity.this, MyService.class);
intent.putExtra("data", "ysl");
startService(intent);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
service中:
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind is invoke");
String data = intent.getStringExtra("data");
Log.d(TAG, "onBind is invoke--->"+data);
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand is invoke");
String data = intent.getStringExtra("data");
Log.d(TAG, "onStartCommand is invoke--->"+data);
return super.onStartCommand(intent, flags, startId);
}
不管是用start还是bind,都可以使用intent传递数据
(2)使用binder对象
在service中:
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind is invoke");
return new MyBinder();
}
public class MyBinder extends Binder{
public void setData(String data){
Toast.makeText(MyService.this, data, Toast.LENGTH_SHORT).show();
}
}
activity中:
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected is invoke");
MyBinder myBinder = (MyBinder) service;
myBinder.setData("bindService启动服务了");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected is invoke");
}
};
在serviceConnection接口中,第二个参数Ibinder,就是我们在service中的onBind方法返回的对象MyBinder。这种方式只适用于bindservice使用。
(3)接口回调
activity给service传递数据:
接口设置在activity中:
private OnActivityDataChangedListener onActivityDataChangedListener;
public interface OnActivityDataChangedListener {
void onActivityDataChanged(String string);
}
public void setOnActivityDataChangedListener(OnActivityDataChangedListener onActivityDataChangedListener) {
this.onActivityDataChangedListener = onActivityDataChangedListener;
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected is invoke");
myBinder.setActivity(ServiceActivity.this);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected is invoke");
}
};
//任意控件点击事件,触发数据变化
findViewById(R.id.startService).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onActivityDataChangedListener != null) {
onActivityDataChangedListener.onActivityDataChanged("哈哈哈,activity的数据变了。activity");
} else {
throw new IllegalArgumentException("activity must invoke setOnActivityDataChangedListener()");
}
}
});
service中:
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind is invoke");
return new MyBinder();
}
public class MyBinder extends Binder{
public void setActivity(Activity activity){
((ServiceActivity)activity).setOnActivityDataChangedListener(new ServiceActivity.OnActivityDataChangedListener() {
@Override
public void onActivityDataChanged(String string) {
Log.d(TAG, "onActivityDataChanged is invoke "+string);
}
});
}
}
mybinder中有个setactivity()方法,当连接建立后,把activity设置进去。然后实现activity的接口。当activity调用数据变化接口方法时,service中的实现方法就会自动触发,获取到数据变化。
service数据变化也可以通知到activity中,同理使用接口方式:
接口在service中:
public interface CallBack{
void dataCallBack(String data);
}
public void setDataCallBack(CallBack callBack){
this.callback = callBack;
}
private CallBack callback;
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind is invoke");
return new MyBinder();
}
public class MyBinder extends Binder{
public MyService getMyService(){
return MyService.this;
}
}
}
//这段就是触发接口的代码,可以在获取到数据或数据有变化时,来调用触发。
if (callback != null) {
callback.dataCallBack("哈哈哈,service的数据变了。service");
} else {
throw new IllegalArgumentException("activity must invoke setOnActivityDataChangedListener()");
}
activity中实现:
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected is invoke");
MyBinder myBinder = (MyBinder) service;
myBinder.getMyService().setDataCallBack(new CallBack() {
@Override
public void dataCallBack(String data) {
Log.d(TAG, "setDataCallBack is invoke "+data);
}
});
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected is invoke");
}
};
可以发现,接口回调方法可以在任意两个类中传递数据。前提是:获取方要能够拿到被获取方的对象,并调用被获取方的接口,实现接口中的方法即可。而被获取可以在获取方注册后,随时随地触发接口并传递数据出去。