什么是
Service
Service
是一个长期运行在后台
没有用户界面的Android组件。
在Android中后台是相对UI前台而言的
,后台不是子线程。
Service
跟Thread
没有任何关系
Service
是运行在主线程中的,若直接在Service里面做耗时操作很容易造成ANR「Application Not Responding」,故在Service
中不能直接做耗时操作,要想做耗时操作只能在Service
中创建的子线程中进行。
- Android中有两种Service
- Service
//AndroidManifest文件中注册service
1.1 Service 是单向的 不受控的
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(MainActivity.this, MyService.class);
//启动Service
startService(intent);
}
//这个Service 是单向的 不受控的
// Context.startService(...)之后,Service的 onCreate()和onStartCommand(...)会得到执行。
//之后Service会一直处于运行状态,但具体运行的是什么逻辑,Context就控制不了了。
// 这就好比Activity通知了服务一下:『喂,哥们你可以干活去了』,然后服务就去忙自己的事情了,
// 但Activity并不知道Service到底去做什么了,以及完成的如何。
// Service去干活怎么干不受Context控制,
// Service与Context没任何交流
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
//会在Service第一次创建时调用
// 若多次调用Context.startService(...) 此方法只会执行一次
@Override
public void onCreate() {
super.onCreate();
}
//每次启动Service时调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//new MyAsyncTask().execute();
//创建并开启子线程进行耗时任务
new Thread(new Runnable() {
@Override
public void run() {
//耗时操作。。。
Log.i("创建并开启子线程进行耗时任务", "run");
//耗时操作处理完毕后 不一定要停掉Service 否则会造成内存泄漏
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
//会在Service销毁时调用
@Override
public void onDestroy() {
super.onDestroy();
}
}
public class MyAsyncTask extends AsyncTask {
//在后台任务开始执行之前调用,用于进行一些界面上的初始化操作。(初始化工作)
@Override
protected void onPreExecute() {
//显示进度对话框。。。
super.onPreExecute();
}
/**
* 这个方法中的代码都会在子线程中运行,在这里处理所有的耗时操作任务。
* 这个方法中不可进行UI操作,可调用publishProgress(Progress...)来完成UI更新。
* retun 返回任务的执行结果
*/
@Override
protected Boolean doInBackground(Void... voids) {
//耗时操作
return true;
}
/**
* 调用publishProgress(...)方法后,onProgressUpdate这个方法就被调用,在这个方法中可以对UI进行操作
*/
@Override
protected void onProgressUpdate(Integer... values) {
//更新UI 如进度条。。。
super.onProgressUpdate(values);
}
/**
* 当后台线程任务执行完毕并通过return进行返回时,
* 这个方法就会被调用。在这个方法中根据传参(任务执行的结果)
* 进行相应的UI及逻辑操作。
*/
@Override
protected void onPostExecute(Boolean aBoolean) {
//关闭进度对话框 。。。
//此处 停止service
super.onPostExecute(aBoolean);
}
}
1.2 Service 是双向的 可控的
public class MyService2 extends Service {
private static final String TAG = "MyService2";
//Context通过Binder对Service进行控制
private DownloadBinder downloadBinder = new DownloadBinder();
@Override
public IBinder onBind(Intent intent) {
return downloadBinder;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
class DownloadBinder extends Binder {
public void startDownload() {
Log.i(TAG, "startDownload...");
}
public int getProgress() {
Log.i(TAG, "getProgress...");
return 0;
}
}
}
//MainActivity中
private MyService2.DownloadBinder downloadBinder;
private ServiceConnection serviceConnection;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService2.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName name) {
downloadBinder.stopDownload();
}
};
Intent intent = new Intent(MainActivity.this, MyService2.class);
//绑定Service BIND_AUTO_CREATE ---> 绑定之后自动创建Service
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
//解绑
unbindService(serviceConnection);
}
注意: 若同时调用了bindService(intent, serviceConnection, BIND_AUTO_CREATE)和startService(intent),相应就要同时stopService(intent)和unbindService(serviceConnection)
- IntentService(增强版的Service,集开启线程,以及任务完成后停止service于一身)
//用法和普通的Service一样 startService(...) 或 bindService(...)
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
//这个方法已经在子线程,无需担心ANR
//Serive任务完成后会自动停止服务
@Override
protected void onHandleIntent(Intent intent) {
//耗时操作
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
}
使用场景
-
前台保活
- 使用服务的原因:普通服务(后台服务)的优先级低,系统出现内存不足时,很容易回收掉正在后台运行的服务。「比如后台运行播放音乐,用着用着音乐服务没了」。若想让服务一直保持运行状态,而不会由于系统内存不中的原因导致被回收,就可以考虑使用前台服务。
-
普通服务与前台服务的区别
- 一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏可以看到更加详细的信息,类似于通知的效果。
//只需要修改一下MyService类中的onCreate方法
@Override
public void onCreate() {
super.onCreate();
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("this is content title")
.setContentText("this is content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentIntent(pi)
.build();
startForeground(1, notification);
}
原理
参考:
https://developer.android.google.cn/guide/components/services#Foreground