工作内容:
1.Service的生命周期(bindService,startService的区别)
2.Service与Activity之间的通讯方式
学习分享:
准备:定义服务类继承自Service,在manifests中注册如下:(注册在application中与activity并列)
自定义服务类
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import org.greenrobot.eventbus.EventBus;
public class MyService extends Service {
private MyBinder myBinder;
public boolean isGo = true;
private EventBus eventBus;
private int x= 0;
@Nullable
@Override
public IBinder onBind(Intent intent) {
LogD.d("onBind");
myBinder = new MyBinder();
return myBinder;
}
//Android 2.2之后已被摒弃,建议使用onStartCommand
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
LogD.d("onStart");
}
@Override
public void onCreate() {
super.onCreate();
LogD.d("onCreate");
eventBus =EventBus.getDefault();//初始化EventBus
Intent intent = new Intent(this,SecoundActivity.class);
PendingIntent pendIntent = PendingIntent.getActivity(this,0,intent,0);
Notification noti = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("前台服务通知")
.setContentText("点击跳转懂啊页面二")
.setContentIntent(pendIntent)
.build();
startForeground(1,noti);//创建前台Service(在通知栏显示)
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogD.d("onStartCommand");
/**
* 正常情况下我们会在这里开启一条子线程来执行任务
* 执行线程——Ui主线程
*/
new Thread(){
@Override
public void run() {
while (isGo){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
LogD.d("onStartCommand"+x++);
}
/**
* 在执行完之后这里使用了EventBus来将执行完毕的消息发送到Activity中
* 由此可想而知,也可以使用接口回调的方式来传递信息到Activity中,
* 但是要注意的是这里执行的是后台线程
*/
eventBus.post(new ServiceEvent("onStartCommand执行完毕"));
}
}.start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
LogD.d("onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
LogD.d("onDestroy");
isGo = false;
super.onDestroy();
}
class MyBinder extends Binder {
public void startDownload() {
LogD.d("执行Bindder类中的startDownload()");
/**
* 可以在这里开线程执行bandService的任务
* 执行线程——Ui主线程
*/
new Thread(){
@Override
public void run() {
super.run();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
LogD.d("startDownload:"+i);
}
eventBus.post(new ServiceEvent("startDownload执行完毕"));
}
}.start();
}
}
}
Activity.java代码
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button btnStart,btnStop,btnBind,btnUnBind;
private MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
btnStart = (Button) findViewById(R.id.button);
btnStop = (Button) findViewById(R.id.button2);
btnBind = (Button) findViewById(R.id.button3);
btnUnBind = (Button) findViewById(R.id.button4);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
btnBind.setOnClickListener(this);
btnUnBind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:
//点击事件——触发开启服务
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.button2:
//点击事件——触发停止服务
Intent startIntent1 = new Intent(this, MyService.class);
stopService(startIntent1);
break;
case R.id.button3:
//点击事件——触发绑定服务
Intent startIntent2 = new Intent(this, MyService.class);
bindService(startIntent2, connection, Service.BIND_AUTO_CREATE);
break;
case R.id.button4://【应当用一个标识符来确定是否存在已绑定服务】【不判断——连续解绑会出错】
//点击事件——取消绑定服务
if(connection!=null&&myBinder!=null){
Intent startIntent3 = new Intent(this, MyService.class);
unbindService(connection);
}else{
Toast.makeText(this,"已经不存在绑定",Toast.LENGTH_SHORT).show();
}
break;
}
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
//取消绑定时调用
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定时掉用
myBinder = (MyService.MyBinder) service;
myBinder.startDownload();
}
};
//接收Service中通过EventBus传过来的消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void showMsg(ServiceEvent event){
Toast.makeText(this,event.getMsg(),Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
一、Service的生命周期(bindService,startService的区别)
1.开启方式:startService
//点击事件——触发开启服务
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
.....
.....
//点击事件——触发停止服务
Intent startIntent1 = new Intent(this, MyService.class);
stopService(startIntent1);
注意:在onCreate之后重复点击开启Service,会重复执行onStartCommand,onStart方法,不会重复执行onCreate【注:onStart方法已被onStartCommand方法取代,不建议使用】
2.开启方式:bindService
private ServiceConnection connection = new ServiceConnection() {//绑定需传入ServiceConnection实现类
@Override
public void onServiceDisconnected(ComponentName name) {//取消绑定时调用
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {//绑定时调用
myBinder = (MyService.MyBinder) service;
myBinder.startDownload();
}
};
....
....
//点击事件——触发绑定服务
Intent startIntent2 = new Intent(this, MyService.class);
bindService(startIntent2, connection, Service.BIND_AUTO_CREATE);
....
....
//点击事件——取消绑定服务
if(connection!=null&&myBinder!=null){
Intent startIntent3 = new Intent(this, MyService.class);
unbindService(connection);
}else{
Toast.makeText(this,"已经不存在绑定",Toast.LENGTH_SHORT).show();
}
执行生命周期:
另外:
1.bindService和startService可以交叉使用,两者都使用,则需调用unbindService方法和stopService方法才会终止服务
2.无论开启多少次同一个Service,只需执行一次stopService/unbindService方法即可终止这个服务
3.我们应当在starService时就准备好在哪里stopService,在bindService时就准备好在那里unbindService
二、Service与Activity之间的通讯方式
1.在上方的bindService中可以发现我绑定之后会执行Bingdder类中的startDownload方法,这就实现了Activity中调用Service中的方法
2.我们也可以通过控制Service的生命周期的方式来实现简单的信息传递(本例中是控制Service的执行线程的isGo的值来终止其子线程继续执行)
3.可以在Service执行任务过程中通过EventBus.post()来将执行中的数据传送到Activity中(上面代码已经贴出)(EventBus需添加依赖/导包)
4.也可以使用回调的方式来将Service中执行任务的数据传送的Activity中(回调就不多说了,前面的章节有详细介绍)
执行效果:
执行线路1:【不调用stopService,即使退出app,服务也将继续执行】
点击执行startService——执行onCreate,onStartCommand(开始执行子线程[记数输出Log]),onStart;
点击执行stopService——执行onDestory(isGo=false),子线程接收到isGo=false之后终止执行——执行Activity中的showMsg方法;
执行线路2:【随着Activity生命周期结束而结束】
点击执行bindService——执行onCreate,onBind——执行Activity中的connection对象的onServiceConnected方法——执行Service中Binder子类的startDownload方法,执行子线程【应该用一个标识(boolean之类)来标识是否已在Activity中绑定了服务,不存在——不解绑,存在——解绑】
点击执行unbindService——执行onUnbind,onDestory
执行路线3:(请自行研究...)
点击执行startService
点击执行bindService点击执行stopService
点击执行unbindService
三、实现在前台进程执行Service
由于后台Service可能会因为内存不足被系统回收,就可以创建前台Service主要是将Service显示在通知栏中
代码在上面的Servie中已经存在了,并注释(需要先会Notification的使用),这里只是简单实现了一个跳转,点击通知栏条跳转到app中的页面2