• 【起航计划 033】2015 起航计划 Android APIDemo的魔鬼步伐 32 App->Service->Foreground Service Controller service使用,共享service,前台服务,onStartCommand


    Android系统也提供了一种称为“Service”的组件通常在后台运行。Activity 可以用来启动一个Service,Service启动后可以保持在后台一直运行,即使启动它的Activity退出或是切换到别的应用Service也能保持运行状态。

    Service 可以以两种形式存在:

    • Started 当一个如Activity使用startService()来启动一个Service,一旦Service启动后,就不受启动它的Activity控制, 可以在后台长期运行,通常这种Service在后台执行某个费时操作(如下载文件)不会向启动它的Activity返回结果。
    • Bound 为Activity或是其它程序部件使用bindService()来启动Service。Bound Service提供了一种Client/Service方法允许调用Service的Activity与Service进行交互:发送请求,取得结果,并 支持进程间通信。 一般Bound Service的生命周期和启动它的Activity相同,多个Activity可以同时绑定一个Service。 当所有Activity 都断开与Service之间的绑定时。Service自动结束。

    虽然Service可以有上述两种表现形式,这只是为了说明上的方便,实际上同一个Service可以同时以两种方式存在,只要实现两种方法所定义的接口函数就可以了。

    创建一个Service,首先需要定义一个Service的子类,然后根据需要重载Service定义的一些核心方法:

    • onStartCommand() 当一个Activity调用startService时,Android系统会调用Service的onStartCommand()方法, 前面说过使用startService启动的Service会在后台长期运行,不受启动它的Activity控制,因此应用程序有责任来停止 Service,Service也可以调用stopSelf来停止自身。
    • onBind() 当一个Activity 使用bindService()来绑定Service时Android系统会调用Service的onBind方法,onBind需要返回一个IBind 对象给调用者(Client)。Client然后可以使用IBind提供的方法来使用Service。
    • onCreate() Service第一次创建时被调用,和Activity的onCreate类似。
    • onDestroy() Service退出时调用。

    定义了Service类和实现相应方法后,和Activity一样,也需要在AndroidManifest.xml中定义这个Service:

    <manifest … ><application … >
    <service android:name=”.ExampleService” />< /application>
    < /manifest>

    和Activity一样,也可以为Service定义Intent Filter,如果你不想共享这个Service,可以将android:exported属性定义为false。

    通常情况下Service在后台运行,当Android也支持Service运行在前台,运行在前台的Service必须在屏幕顶端的Status Bar提供一个Notification以提示用户有Service在运行。比如提供个Media Player使用的Service运行在前台,而在标题栏显示当前曲目。

    本例Foreground Service Controller就显示了一个在前台运行的Service, 前台运行的Service可以通过调用startForeground()使Service在前台运行。stopForeground停止前台运行,但 Service本身不会停止。 startForeground,stopForeground是从2.0开始支持的,之前的版本采用setForeground。

    本例为了支持2.0之前和2.0之后的版本,采用了Reflection的方法来来查找当前版本是否含有startForeground和stopForeground,如果有则调用,没有则还是使用setForeground。

    如果找到的话,以下的变量用来存储startForeground和stopForeground方法。和本例Service不相关,就不详述了。 只要知道startForegroundCompat 和stopForegroundCompat的功能就是startForeground 和stopForeground就行了。

    private static final Class[] mStartForegroundSignature = new Class[] {
     int.class, Notification.class};
    private static final Class[] mStopForegroundSignature = new Class[] {
     boolean.class};
     
    private Method mStartForeground;
    private Method mStopForeground;
    private Object[] mStartForegroundArgs = new Object[2];
    private Object[] mStopForegroundArgs = new Object[1];

    下面来看看ForegroundService的代码:
    首先是必须作为Service的子类:

    public class ForegroundService extends Service

    因为是作为“Started” Service来设计的,因此需定义onStartCommand ,同样onStartCommand也是在Android 2.0之后添加的,2.0之前为onStart。本例为了支持所有版本,两个方法对实现了,对应2.0之后的版本,只会调用 onStartCommand,2.0之前的只会调用onStart:

    // This is the old onStart method that
    // will be called on the pre-2.0 platform.
    // On 2.0 or later we override onStartCommand() so this
    // method will not be called.
    @Override
    public void onStart(Intent intent, int startId) {
    handleCommand(intent);
    }
     
    @Override
    public int onStartCommand(Intent intent,
     int flags, int startId) {
    handleCommand(intent);
    // We want this service to
    //continue running until it is explicitly
    // stopped, so return sticky.
    return START_STICKY;
    }

    onStartCommand 可以有返回结果,这个返回值告诉Android系统当这个Service被Kill之后(比如当系统内存不足时)后续操作。START_STICKY 表示系统Kill这个Service之后,如果重新创建这个Service时在调用onStartCommand ,不会将最后的Intent作为参数传入,也就是说intent=null. START_REDELIVER_INTENT则会传入被杀前未处理的最后一个Intent。

    本Service不作为Bind Service ,因此通过一个空实现:

    @Override
    public IBinder onBind(Intent intent) {
      return null;
    }

     最后看看如何启动/停止这个Service, Controller 是作为这个Service的控制类来实现的,提供了前台启动,后台启动,和停止Service操作:

    private OnClickListener mForegroundListener
     = new OnClickListener() {
     public void onClick(View v) {
     Intent intent
     = new Intent(ForegroundService.ACTION_FOREGROUND);
     intent.setClass(Controller.this,
     ForegroundService.class);
     startService(intent);
     }
    };
     
    private OnClickListener mBackgroundListener
     = new OnClickListener() {
     public void onClick(View v) {
     Intent intent
     = new Intent(ForegroundService.ACTION_BACKGROUND);
     intent.setClass(Controller.this,
     ForegroundService.class);
     startService(intent);
     }
    };
     
    private OnClickListener mStopListener = new OnClickListener() {
     public void onClick(View v) {
     stopService(new Intent(Controller.this,
     ForegroundService.class));
     }
    };

     

  • 相关阅读:
    Objective-C 生成器模式 -- 简单实用和说明
    Objective-C 桥接模式 -- 简单实用和说明
    Objective-C 工厂模式(下) -- 抽象工厂模式
    Objective-C 工厂模式(上) -- 简单工厂模式
    Linux篇---Vi的使用
    【Spark篇】---SparkSQL中自定义UDF和UDAF,开窗函数的应用
    【Spark篇】---SparkStreaming算子操作transform和updateStateByKey
    【Spark篇】---SparkStream初始与应用
    【Spark篇】---SparkSQL on Hive的配置和使用
    【Spark篇】---Spark中Shuffle机制,SparkShuffle和SortShuffle
  • 原文地址:https://www.cnblogs.com/dongdong230/p/4326618.html
Copyright © 2020-2023  润新知