Android Service不能再详细的教程

时间:2022-01-20 15:19:12

这篇包含了:

Service后台服务、前台服务、IntentService、跨进程服务、无障碍服务、系统服务 几乎所有Android Service相关的东西。

前言

作为四大组件之一的Service类,是面试和笔试的必备关卡,我把我所学到的东西总结了一遍,相信你看了之后你会对Service娓娓道来,在以后遇到Service的问题胸有成竹,废话不多说,开车啦

Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务。Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作

Service的运行不依赖于任何用户界面,即使程序被切换到后台或者用户打开另一个应用程序,Service仍然能够保持正常运行,这也正是Service的使用场景。当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行

后台服务

后台服务可交互性主要是体现在不同的启动服务方式,startService()和bindService()。bindService()可以返回一个代理对象,可调用Service中的方法和获取返回结果等操作,而startService()不行

不可交互的后台服务

不可交互的后台服务即是普通的Service,Service的生命周期很简单,分别为onCreate、onStartCommand、onDestroy这三个。当我们startService()的时候,首次创建Service会回调onCreate()方法,然后回调onStartCommand()方法,再次startService()的时候,就只会执行一次onStartCommand()。服务一旦开启后,我们就需要通过stopService()方法或者stopSelf()方法,就能把服务关闭,这时就会回调onDestroy()

一、创建服务类

创建一个服务非常简单,只要继承Service,并实现onBind()方法

Android Service不能再详细的教程

二、配置服务

Service也是四大组件之一,所以必须在manifests中配置

<service android:name=".Service.BackGroupService"/>

 

三、启动服务和停止服务

我们通过两个按钮分别演示启动服务和停止服务,通过startService()开启服务,通过stopService()停止服务

Android Service不能再详细的教程

当你开启服务后,还有一种方法可以关闭服务,在设置中,通过应用->找到自己应用->停止

Android Service不能再详细的教程

运行程序后,我们点击开始服务,然后一段时间后关闭服务。我们以Log信息来验证普通Service的生命周期:onCreate->onStartCommand->onDestroy

其中你会发现我们的子线程进行的耗时操作是一直存在的,而我们Service已经被关闭了,关闭该子线程的方法需要直接通过Home键关闭该应用程序

可交互的后台服务

可交互的后台服务是指前台页面可以调用后台服务的方法,可交互的后台服务实现步骤是和不可交互的后台服务实现步骤是一样的,区别在于启动的方式和获得Service的代理对象

一、创建服务类

和普通Service不同在于这里返回一个代理对象,返回给前台进行获取,即前台可以获取该代理对象执行后台服务的方法

Android Service不能再详细的教程

二、绑定服务和解除绑定服务

 

我们通过两个按钮分别演示绑定服务和解除绑定服务,通过bindService()开启服务,通过unbindService()停止服务

Android Service不能再详细的教程

这里和startService的区别在于多了一个ServiceConnection对象,该对象是用户绑定后台服务后,可获取后台服务代理对象的回调,我们可以通过该回调,拿到后台服务的代理对象,并调用后台服务定义的方法,也就实现了后台服务和前台的交互

最后别忘了在清单文件里面,注册服务才能运行。

三、运行代码

运行程序后,我们点击绑定服务,然后一段时间后解除绑定服务。我们以Log信息来验证Service的生命周期:onCreate->onBind->onUnBind->onDestroy,其中也可以看到我们调用后台服务的方法showToast和showList

15408-15408/com.handsome.boke2 E/Service: onCreate
15408-15408/com.handsome.boke2 E/Service: onBind
15408-15408/com.handsome.boke2 E/Service: showToast
15408-15408/com.handsome.boke2 E/Service: showList
15408-15408/com.handsome.boke2 E/Service: onUnbind
15408-15408/com.handsome.boke2 E/Service: onDestroy


混合性交互的后台服务

或许你会迷惑,startService和bindService之间有什么关系?其实简单的说两者之间是没有关联的,类似于你亲妈生了个双胞胎一样,只有纯粹的血缘关系。那么问题来了,这两个启动方式是否可以同时使用呢,答案是可以的

将上面两种启动方式结合起来就是混合性交互的后台服务了,即可以单独运行后台服务,也可以运行后台服务中提供的方法,其完整的生命周期是:onCreate->onStartCommand->onBind->onUnBind->onDestroy

前台服务

由于后台服务优先级相对比较低,当系统出现内存不足的情况下,它就有可能会被回收掉,所以前台服务就是来弥补这个缺点的,它可以一直保持运行状态而不被系统回收。例如:墨迹天气在状态栏中的天气预报

Android Service不能再详细的教程

一、创建服务类

前台服务创建很简单,其实就在Service的基础上创建一个Notification,然后使用Service的startForeground()方法即可启动为前台服务

Android Service不能再详细的教程

启动前台服务

 startService(new Intent(this, ForegroundService.class));

二、运行代码

我们可以看到状态栏确实增加了我们这条通知

Android Service不能再详细的教程

当我们将该程序退出并杀掉的时候,通过设置->应用->选择正在运行中的应用,我们可以发现,我们的程序退出杀掉了,而服务还在进行着

Android Service不能再详细的教程

IntentService

IntentService是专门用来解决Service中不能执行耗时操作这一问题的,创建一个IntentService也很简单,只要继承IntentService并覆写onHandlerIntent函数,在该函数中就可以执行耗时操作了

Android Service不能再详细的教程

AIDL跨进程服务

关于AIDL跨进程服务的使用和原理分析,可以见我另一篇博客:Android基础——初学者必知的AIDL在应用层上的Binder机制

AccessibilityService无障碍服务

关于AccessibilityService无障碍服务的使用和实例,可以见我另一篇博客:Android进阶——学习AccessibilityService实现微信抢红包插件

  • http://blog.csdn.net/qq_30379689/article/details/53242953

系统服务

系统服务提供了很多便捷服务,可以查询Wifi、网络状态、查询电量、查询音量、查询包名、查询Application信息等等等相关多的服务,具体大家可以自信查询文档,这里举例几个常见的服务

1. 判断Wifi是否开启

 WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
boolean enabled = wm.isWifiEnabled();

2. 获取系统最大音量

 AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
int max = am.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);

3. 获取当前音量

 AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
int current = am.getStreamMaxVolume(AudioManager.STREAM_RING);

4. 判断网络是否有连接

 ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
boolean isAvailable = info.isAvailable();