Service 的使用
startService 的使用
bindService的使用
IntentService
通过binder介质调用Service中的方法
下面是按钮,点击之后会用不同的方式绑定Service
1.startService—用Intent实现Activity向Service的传值
①先创建一个自定义Service继承Service 实现onBind方法,但是在startService中用不到这个方法所以先返回null
public class MyService1 extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {//创建Service,多次start的时候,也只会创建一次
super.onCreate();
//Thread.currentThread()得到当前的线程
// 得到线程的名字(如果名字里面有main说明是在主线程),得到ID
Log.e("TAG","onCreate"+Thread.currentThread().getName()+"id:"+Thread.currentThread().getId());
}
//连接服务后想要进行什么操作一般写在这里
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("TAG","onStartCommand");
//intent是从Activiy里面传过来的intent,所以可以传值
Log.e("TAG",intent.getStringExtra("name")) ;
//通常有三中返回值:START_STICKY(服务被异常终止时重新启动服务,没有stop服务)
//START_NOT_STICKY(服务被异常终止时,不重新启动服务)
//START_REDELIVER_INTENT(服务被异常终止时,重新传递intent)
return START_REDELIVER_INTENT ;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("TAG","onDestroy");
}
②在Mainfist中注册这个Service(只能这样注册)
<service android:name="com.xbl.service.MyService1"/>
③在Activty绑定这个后台服务,两个按钮,一个绑定服务,一个取消服务
case R.id.start_service_btn:// 打印出onCreat onBind onStartCommand
//即使关闭程序把后台清掉会依旧调用onCreat方法,说明Service会在后台中运行不会被杀死
Intent intent1=new Intent(MainActivity.this, MyService1.class);
//向服务传值
intent1.putExtra("name","张三丰");
startService(intent1);
break;
case R.id.stop_service_btn://onDestroy
//只有stop了Service才会被杀死,即使退出了程序服务也会自己创建出来
Intent intent2=new Intent(MainActivity.this, MyService1.class);
stopService(intent2);
break;
这个是startService的使用方法可以进行Activity向Service的传值,做一些简单的操作,无法向Activity传值,所以只能做一些简单的操作,在Service中是不能做耗时操作的,需要开启一个子线程在Service中
2.bindService–实现Service和Activty的相互通信
这个可以实现Service和Activity的互相通信,Activity可以调用Service的方法,也可以向Activity传值
①先创建一个自定义的Service继承Service,实现onBind方法,在这里onBind不能反回一个null了
public class MyBinder extends Binder{
//这是BInder自己定义的方法
public void println(){
Log.e("TAG2","我是Binder类里面的println方法");
}
//Actiity是不可以直接操作Service里面的对象的,所以通过Binder在这里得到MyService2对象
public MyService2 getService(){
return MyService2.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e("TAG2","onBind") ;
//将这个自定义的Binder对象返回
return new MyBinder();
}
//有绑定就要有解除绑定
@Override
public boolean onUnbind(Intent intent) {
Log.e("TAG2","onUnbind");
return super.onUnbind(intent);
}
//创建
@Override
public void onCreate() {
super.onCreate();
Log.e("TAG2","onCreate");
}
//startService时会调用的方法,bindService的时候不会调用到这个方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("TAG2","onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//销毁一个Service,他和解除绑定是两回事,一般解除绑定就会销毁服务了
@Override
public void onDestroy() {
super.onDestroy();
Log.e("TAG2","onDestroy");
}
//在Service中自定义一个方法,实现从Activity中直接调用这个方法
public void serviceName(){
Log.e("TAG2","我是MyService2,这是我的方法");
}
②同样这也需要在Mainfast中进行注册
<service android:name="com.xbl.service.MyService2"/>
有的注册的时候是需要加完整的包名和类名的,但是AS比较智能,可以直接联想出来这些东西
③在绑定服务和服务进行通信之前要现在Activity得到这个服务(Binder)的对象,得到从自定义Service中回调的Binder,需要实现一个接口
//实现一个接口,要实现接口所实现的方法
private ServiceConnection connection=new ServiceConnection() {
//绑定了服务
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("TAG2","onServiceConnected");
//将Service里面的Bind回调过来,将binder实例化
myBinder= (MyService2.MyBinder) service;
}
//这个方法很少会被调用到,没有绑定服务
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("TAG2","onServiceDisconnected");
}
};
④得到这个可操作的Binder之后就可以对Binder进行操作了
//绑定Binder
case R.id.bind_service://打印:onCreat onBind onServiceConnected 绑定两次三个方法只会执行一次
Intent intent3 =new Intent(MainActivity.this,MyService2.class);
//BIND_AUTO_CREATE如果没创建过BIND会自动创建
bindService(intent3,connection,BIND_AUTO_CREATE);
break;
case R.id.unbind_service://onUnbind onDestroy
unbindService(connection);
break;
//调用Binder中println()方法
case R.id.println_bind_service://打印那句话
myBinder.println();
break;
这样最后可以打印出那句话还有各种Service的声明周期函数
真正的实现Service和Acitivity之间的通信
应用;像我们平常的音乐播放器的播放音乐,暂停音乐的方法就可以在Service的Binder中写,直接在Activity中调用binder.play()方法什么的就可以了
3.IntentService:用队列的方式存储,排队处理,先来的先处理,等这个处理完再去处理其他的线程
①写一个自定义的IntentService类继承于IntentService,因为在Service中是无法写耗时操作的,必须要在里面写一个子线程,IntentService实现onHandleIntent方法,这个方法会启动一个子线程
public class IntentServiceDemo extends IntentService {
int count=0;
//重写构造方法,改成无参的
public IntentServiceDemo() {
super("");
}
//里面包含一个子线程,不用再写子线程了
@Override
protected void onHandleIntent(Intent intent) {
for(int i=1;i<=5;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("TAG3","i:"+i);
count++;
}
Log.e("TAG3","count:"+count);
}
@Override
public void onCreate() {
super.onCreate();
Log.e("TAG3","onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("TAG3","onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("TAG3","onDestroy");
}
}
②在Activity中调用此方法
case R.id.intent_service:
Intent intentService =new Intent(MainActivity.this, IntentServiceDemo.class);
//用startService去启动服务
startService(intentService);
break;
IntentService是用startService去调用的
因为是用队列的方式处理任务,所以先点击一次让i的值到3,在点击一次按钮start一次,这个时候IntentService会将上一次没有执行完的任务执行完,从4开始打印到5,然后再添加这次新的任务,从1开始打印
4.在Acticity中通过binder中介得到Service中的方法
Activity和Service一样,没办法去new 一个对象去调用方法,自己的方法只能自己使用,但是我们可以通过binder内部类获取Service里面的方法或者Service这个类,通过向Activity通信实现在Activity里面调用Service的方法
①在Service类里面写一个方法(打印输出)
//在Service中自定义一个方法,实现从Activity中直接调用这个方法
public void serviceName(){
Log.e("TAG2","我是MyService2,这是我的方法");
}
②在Service中的binder内部类中去实例化得到这个Service类,并且 return出来这个类
//里面的方法Activity可以调用
public class MyBinder extends Binder{
public void println(){
Log.e("TAG2","我是Binder类里面的println方法");
}
//Actiity是不可以直接操作Service里面的对象的,所以通过Binder在这里得到MyService2对象
public MyService2 getService(){
return MyService2.this;
}
}
③在Activiy中得到这个Service类(通过回调的方式,并没有实例化)
case R.id.get_service:
//在通过binder得到这个Service类之前一定要先绑定Binder
MyService2 myService2=myBinder.getService();
myService2.serviceName();
break;
这样就可以通过myBinder.getService();得到Service的实体类,也可以调用它的方法了