一、Service的简介
首先,相信很多Android开发者都知道Service是android 系统中的四大组件之一,它跟Activity的级别差不多,但是它只能后台运行,并且可以和其他组件进行交互。service可以在很多场合的应用中使用,比如播放音乐的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如后台下载某些数据时,再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后台的。
二、 Service启动流程
Service总共有2种启动方式,分别是context.startService() 和 context.bindService()
其中context.startService() 的生命周期也就是启动流程为:
context.startService() -> onCreate() -> onStartCommand() -> Service running -> context.stopService() -> onDestroy() -> Service stop
在这里需要注意的是如果你的这个服务已经开启过一次。但是在你第二次起startService()前你并没有去注销这个服务,那么你这次以及在你注销前去启动这个服务都只会运行 onStartCommand()而不会onCreate()。
而context.bindService()的启动生命周期为:
context.bindService() -> onCreate() -> onBind() -> Service running -> onUnbind() -> onDestroy() -> Service stop
这种启动方式也就是常说的Activity与Service通信的启动方式了,通过这种注册的方式我们服务中的onBind()机会返回一个IBinder可过活动来操作服务了。实现他们之间的通信。**这里需要注意的是当Activity关闭时,这里的Service也会跟着关闭。运行onDestroy() **
在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
三、代码示例
这里我先将所有代码贴出然后进行拆分
Activity
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
Button startBtn,stopBtn,bindBtn,unbindBtn,intentService,toActivity2;
MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
myBinder=(MyService.MyBinder)iBinder;
myBinder.startOne();
myBinder.stopOne();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
public void init(){
startBtn=findViewById(R.id.startService);
stopBtn=findViewById(R.id.stopService);
bindBtn=findViewById(R.id.bindService);
unbindBtn=findViewById(R.id.unbindService);
intentService=findViewById(R.id.intentService);
toActivity2=findViewById(R.id.to_activity2);
bindBtn.setOnClickListener(this);
unbindBtn.setOnClickListener(this);
startBtn.setOnClickListener(this);
stopBtn.setOnClickListener(this);
intentService.setOnClickListener(this);
toActivity2.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.startService:
Intent startIntent=new Intent(this,MyService.class);
startService(startIntent);
break;
case R.id.stopService:
Intent stopIntent=new Intent(this,MyService.class);
stopService(stopIntent);
break;
case R.id.bindService:
Intent bindIntent=new Intent(this,MyService.class);
bindService(bindIntent,connection,BIND_AUTO_CREATE);
break;
case R.id.unbindService:
unbindService(connection);
break;
case R.id.intentService:
Intent intent=new Intent(this,MyIntentService.class);
startService(intent);
break;
case R.id.to_activity2:
Intent intent1=new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent1);
MainActivity.this.finish();
break;
}
}
}
Service
public class MyService extends Service {
private static final String TAG = "MyService";
MyBinder myBinder=new MyBinder();
class MyBinder extends Binder{
public void startOne(){
Log.d(TAG, "startOne: ");
}
public void stopOne(){
Log.d(TAG, "stopOne: ");
}
}
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
return myBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
Intent intent=new Intent(this,MainActivity.class);
PendingIntent pi=PendingIntent.getActivity(this,0,intent,0);
Notification notification=new NotificationCompat.Builder(this)
.setContentTitle("前台服务")
.setContentText("这是一条前台服务")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pi)
.build();
startForeground(1,notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
}
AndroidManifest.xml
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" />
<activity android:name=".Main2Activity"></activity>
然后我们的界面代码就不放上来了就是几个按钮
代码中可以看到我们在Service中的关键生命周期中都log了
我们先来看一下context.startService()的启动模式这里是通过Intent来对其进行操作
case R.id.startService:
Intent startIntent=new Intent(this,MyService.class);
startService(startIntent);
break;
case R.id.stopService:
Intent stopIntent=new Intent(this,MyService.class);
stopService(stopIntent);
break;
我们先点击开启服务然后点击停止服务看下log信息如下 正如我们所料
在上面我们还说过一个注意事项就是onCreate()方法在服务停止前只会运行一次。我们来验证一下。同时点击2下开启服务如下:
这里很容易可以看出onCreate()确实只运行了一次。接下来我们继续看context.bindService()的启动方式我们依然是按照上面的测试方法如下:
中间的第2、3条是我在ServiceConnection中写的调用返回的IBinder中的方法实现与服务的通信
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
myBinder=(MyService.MyBinder)iBinder;
myBinder.startOne();
myBinder.stopOne();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
好了我们服务的生命周期就将到这里了大家可以利用服务的生命周期在后台为所欲为了
源码地址gitHub