四大组件

Service相关知识

2019-07-31  本文已影响4人  wind_sky

一. 简介

Service 是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。Service可由其他应用组件启动,而且即使用户切换到其他应用,Service仍将在后台继续运行。 此外,组件可以绑定到Service,以与之进行交互,甚至是执行进程间通信 (IPC)。 例如,Service可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行。

二. 创建与使用

要创建服务,您必须创建 Service 的子类(或使用它的一个现有子类)。在实现中,您需要重写一些回调方法,以处理服务生命周期的某些关键方面并提供一种机制将组件绑定到服务(如适用)。 应重写的最重要的回调方法包括:

1. AndroidManifest文件中声明Service

Service是Android的组件,所以需要在manifest文件声明,添加<service>元素作为<application>的子元素。在 <service> 元素中,可以定义一些特性,如启动Service及其运行所在进程所需的权限。android:name 属性是唯一必需的属性,用于指定Service的类名。应用一旦发布,即不应更改此类名,如若不然,可能会存在因依赖显式 Intent 启动或绑定Service而破坏代码的风险。

为了确保应用的安全性,请始终使用显式 Intent 启动或绑定 Service,且不要为Service声明 Intent 过滤器。 启动哪个Service存在一定的不确定性,而如果对这种不确定性的考量非常有必要,则可为Service提供 Intent 过滤器并从 Intent 中排除相应的组件名称,但随后必须使用 setPackage() 方法设置 Intent 的软件包,这样可以充分消除目标Service的不确定性。

此外,还可以通过添加 android:exported 属性并将其设置为 "false",确保Service仅适用于当前的应用。这可以有效阻止其他应用启动我们的Service,即便在使用显式 Intent 时也如此。

2. 启动Service

在组件中启动Service有两种方式,一种是通过startService,另一种是bindService。

(1)startService

可以通过将 Intent(指定要启动的Service)传递给 startService(),从 Activity 或其他应用组件启动Service。Android 系统调用Service的 onStartCommand() 方法,并向其传递 Intent。(切勿直接调用 onStartCommand()。)

Intent intent = new Intent(this, HelloService.class);
startService(intent);

startService() 方法将立即返回,且 Android 系统调用Service的 onStartCommand() 方法。如果Service尚未运行,则系统会先调用 onCreate(),然后再调用 onStartCommand()

如果Service亦未提供绑定,则使用 startService() 传递的 Intent 是应用组件与Service之间唯一的通信模式。但是,如果希望Service返回结果,则启动服务的客户端可以为广播创建一个 PendingIntent (使用 getBroadcast()),并通过启动Service的 Intent 传递给Service。然后,Service就可以使用广播传递结果。

多个Service启动请求会导致多次对Service的 onStartCommand() 进行相应的调用。但是,要停止Service,只需一个Service停止请求(使用 stopSelf()stopService())即可。

(2)bindService

绑定Service允许应用组件通过调用 bindService() 与其绑定,以便创建长期连接(通常不允许组件通过调用 startService() 来启动它)。

如需与 Activity 和其他应用组件中的Service进行交互,或者需要通过进程间通信 (IPC) 向其他应用公开某些应用功能,则应创建绑定Service。

要创建绑定Service,必须实现 onBind() 回调方法以返回 IBinder,用于定义与Service通信的接口。然后,其他应用组件可以调用 bindService() 来检索该接口,并开始对Service调用方法。Service只用于与其绑定的应用组件,因此如果没有组件绑定到Service,则系统会销毁Service(不必像通过onStartCommand() 启动的Service那样来停止绑定Service)。

要创建绑定Service,首先必须定义指定客户端如何与Service通信的接口。 Service与客户端之间的这个接口必须是 IBinder 的实现,并且Service必须从 onBind()回调方法返回它。一旦客户端收到 IBinder,即可开始通过该接口与Service进行交互。

多个客户端可以同时绑定到Service。客户端完成与Service的交互后,会调用 unbindService() 取消绑定。一旦没有客户端绑定到该服务,系统就会销毁它。

3. Service生命周期

Service的生命周期要比Activity简单,但是也要密切关注如何创建和销毁Service,因为Service可以在用户没有意识到的情况下运行于后台。Service的生命周期由于启动方式的不同也有不同,下图展示了两种情况的生命周期


image.png

注:尽管startService是通过调用 stopSelf() 或 stopService() 来停止,但是该Service并无相应的回调(没有 onStop() 回调)。因此,除非Service绑定到客户端,否则在Service停止时,系统会将其销毁 ,onDestroy() 是接收到的唯一回调。

在实际使用过程中要根据需要实现生命周期的回调方法

public class ExampleService extends Service {
    int mStartMode;       // indicates how to behave if the service is killed
    IBinder mBinder;      // interface for clients that bind
    boolean mAllowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

关于onStartCommand方法的返回值,必须返回整型数。整型数是一个值,用于描述系统应该如何在服务终止的情况下继续运行服务(如上所述,IntentService 的默认实现将为您处理这种情况,不过您可以对其进行修改)。从 onStartCommand() 返回的值必须是以下常量之一:

上一篇下一篇

猜你喜欢

热点阅读