关于服务的参考资料
- service 标签元素 https://developer.android.com/guide/topics/manifest/service-element.html
- API 指南 服务讲解 https://developer.android.com/guide/components/services.html
- 绑定服务 https://developer.android.com/guide/components/bound-services.html
- AIDL https://developer.android.com/guide/components/aidl.html
- Building Accessibility Services https://developer.android.com/guide/topics/ui/accessibility/services.html
- 培训 Best Practices for Background Jobs https://developer.android.com/training/best-background.html
- 扩展 进程和线程 https://developer.android.com/guide/components/processes-and-threads.html
什么是服务
简而言之,服务是可以不依赖于界面而在后台长期运行的组件,即便用户切换到了其他应用也丝毫不受影响。其他组件可绑定到服务,与之交互,甚至进程间通信(IPC)。
服务分类
服务按启动的方式可分为启动服务(startService())和绑定服务(bindService())。
服务按用户是否可意识到可分为前台服务(startForeground())和后台服务。
- 所谓后台服务也只是用户看不见而已,其默认也仍然运行在程序所在进程的主线程(UI 线程)中,所以执行复杂的操作还是要自己开线程。
- 所谓前台服务,是让用户能够感知,也可以在其中开辟新的线程。
在前台运行服务
其实前台服务也看不见,你能看见的只有界面(Activity)和通知,只是用户可以感知到。
前台服务被认为是用户主动意识到的一种服务,因此在内存不足时,系统也不会考虑将其终止。 前台服务必须为状态栏提供通知,状态栏位于“正在进行”标题下方,这意味着除非服务停止或从前台删除,否则不能清除通知。
例如,应该将播放音乐的服务设置为在前台运行,这是因为用户能够听见有音乐在播放,用户可明确意识到其操作。 状态栏中的通知可能表示正在播放的歌曲,并允许用户启动 Activity 来与音乐播放器进行交互。
在清单文件中注册服务
服务是四大组件之一,所以需要在清单文件中注册:
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
语法:
<service android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:isolatedProcess=["true" | "false"]
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
. . .
</service>
属性解释:
-
android:enabled 指定系统是否可实例化该service,默认true。<application> 的 enabled属性,用于指定其中的所有组件是否可用。这两个enabled属性必须全部为
true
才能保证service能被实例化。 -
android:exported 是否允许其他应用的组件启动该服务或与之交互。若为false,则只有同一个应用或者具有相同用户id的应用的组件可以启动或与之交互。默认值取决于服务是否有intent过滤器。没有过滤器则只能由明确的类名进行调用,也就意味着只能同一个app的组件调用(因为其他的应用不知道类名),这种情况下就是false。相反,若有了至少一个intent过滤器,则表明允许外部使用,这时是true。 也可以使用permission 属性来限制外部与之交互。
-
android:icon 制定图标来展示服务。必须设置包含图片的drawable资源文件;若未设置,则会被 <application> 的 icon属性替代。 服务的icon — 无论在这里设置或是<application> 的 icon 属性指定 — 都是服务的intent filters的默认图标。
-
android:isolatedProcess 若设置未true,服务会运行在独立的进程中,且不会有该服务的权限。与其通信的唯一方式是Service API(binding和starting)。
-
android:label 将服务的名字展示给用户。若未设置,会使用<application> 的 lable 标签进行替代。 服务label— 无论是在这里设置还是使用<application>
元素设置的 — 默认都是服务的所有intent filters的默认label(参见服务[ 的 label])。 label应当设置为字符串资源的引用,以便于本地化操作。若可以便宜行事的话,也可以直接指定原始字符串。 -
android:name 指定集成自 Service 的类名(eg."com.example.project.RoomService "),无默认,唯一必需指定的属性,必须是权限定名。为了速记,若首字符是英文逗号(eg. “.RoomService”),将会追加到<manifest>标签指定的包名后面。 一旦命名就不能轻易更改(除非设置Android:exported="false")。这里有篇博客说明了不可随意更改的内容: http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html
-
android:permission 启动或绑定服务所需要的权限名称。若startService()、bindService()、stopService()没有被授予该权限,这些方法就没有用并且 Intent 也不会传递给服务。 若未设置该值,默认是<application> 的 permission属性的值。若两者都没有设置,该服务就没有权限保护。 更多关于权限的资料,请查看介绍中的[Permissions]章节,以及[Security and Permissions]。
-
android:process 指定服务运行在哪个进程。正常情况下,所有应用组件都运行在应用自身所创建的进程中。拥有与应用包名一样的名字。<application>
的 process 属性可以为所有组件设置默认的进程名。但是组件可以使用自己的process属性对其进行覆盖,允许一个应用横跨多个进程。 若名字开头设置为冒号(’:’),则开启一个新的进程,并且应用私有,当需要该组件时就会创建并且在其所在进程运行。若进程名是小写字母开头,服务会运行在全局进程中,需要确保有权限这样做。可以让不同应用中的组件共享一个进程,减少资源占用。
Service 的生命周期
来自官网的服务的生命周期图:https://developer.android.com/guide/components/services.html#Lifecycle
![](https://img.haomeiwen.com/i278588/cfcd40cdd3224962.png)
onCreate()
首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。如果服务已在运行,则不会调用此方法。
onStartCommand()
每次调用 startService(Intent) 方法的时候都会回调 onStartCommand() 方法,可通过 Intent 传递所需的数据进来,系统也会为自动分配一个 startId。注意不可直接调用该方法。
onBind()
当另一个组件想通过调用 bindService() 与服务绑定(例如执行 RPC)时,系统将调用此方法。在此方法的实现中,您必须通过返回 IBinder 提供一个接口,供客户端用来与服务进行通信。请务必实现此方法,但如果您并不希望允许绑定,则应返回 null。
onDestroy()
当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的监听器、接收器等。 这是服务接收的最后一个调用。
网友评论