3.Service

作者: gadfly_only | 来源:发表于2016-08-03 16:52 被阅读130次

    Android Service中显示Dialog

    1.启动方式

    Service有两种启动方式,分别通过startService方法和bindService方法启动

    • startService通过这种方法启动的Service,在启动它的应用退出后,仍然会继续运行,除非服务自身调用stopSelf()或者外部接口调用stopService()方法才能停止服务;当服务停止时,系统会销毁服务
    • bindService通过这种方法启动的Service,是与启动他的应用绑定在一起的,即应用退出时,该服务也退出;如果要停止服务,需要调用unBindService()方法> 通过startService启动的服务可以被绑定,即通过bindService()方法与Activity绑定。此时如果需要关闭Service,需要先调用方法unBindService()然后stopService(),否则Service是不会被关闭的

    2.生命周期

    Paste_Image.png
    通过StartService()启动

    不论调用几次startService(),Service中onCreate()方法只调用一次,但是每次都会调用onStartCommand()
    当调用stopService() / stopSelf()时,如果此时Service未与任何组件绑定,会直接调用onDestroy()方法销毁服务

    通过onBindService()绑定

    不论调用几次bindService(),Service中onCreate()方法只调用一次,但是每次都会调用onBind()
    当调用unBindService()时,系统会回调一个onUnbind()回调方法,然后再销毁服务

    先通过onStartService()启动,再通过onBindService()绑定

    不论调用几次startService(),Service中onCreate()方法只调用一次,但是每次都会调用onStartCommand()
    当终止Service时,需要先unbindService(),再stopService()。如果先调用stopService()将不会停止Service

    附加参数

    onStartCommand() 提供一个返回值,告诉系统在onStartCommand()方法调用结束后Service被kill时如何重启Service。返回值有如下几种

    • START_STICKY 如果Service被kill,那么系统会在随后试图重新启动Service,但是不会继续使用前次传入的Intent对象
    • START_NOT_STICKY 如果Service被kill,系统不会试图重新启动Service
    • START_REDELIVER_INTENT 类似于START_STICKY,但是会重新传入Intent对象
    • START_STICKY_COMPATIBILITY START_STICKY的兼容版本,当START_STICKY不好使时可以试一下这个参数

    Foreground Service

    使用Foreground Service,使Service在内存回收中获得更高优先级,比后台Service更不容易被系统kill通过在Service的onStartCommand()回调方法中调用startForeground()方法,可以让Service在前台运行通过调用stopForeground()方法,可以让Service停止前台运行,但是Service本身不会被停止

    保证service不被杀掉

    1.onStartCommand方法,返回START_STICKY

    //onStartCommand方法,返回START_STICKY
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        flags = START_STICKY;  
        return super.onStartCommand(intent, flags, startId);  
    }
    

    **【结论】 **手动返回START_STICKY,亲测当service因内存不足被kill,当内存又有的时候,service又被重新创建,比较不错,但是不能保证任何情况下都被重建,比如进程被干掉了....

    2.提升service优先级

    在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。

    <service  
        android:name="com.dbjtech.acbxt.waiqin.UploadService"  
        android:enabled="true" >  
        <intent-filter android:priority="1000" >  
            <action android:name="com.dbjtech.myservice" />  
        </intent-filter>  
    </service> 
    

    【结论】目前看来,priority这个属性貌似只适用于broadcast,对于Service来说可能无效

    3. Android开发之如何保证Service不被杀掉(broadcast+system/app)

    服务不被杀死分3种来讨论
    1.系统根据资源分配情况杀死服务
    2.用户通过 settings
    -> Apps
    -> Running
    -> Stop
    方式杀死服务
    3.用户通过 settings
    -> Apps
    -> Downloaded
    -> Force Stop
    方式杀死服务

    第一种情况:
    用户不干预,完全靠系统来控制,办法有很多。比如 onStartCommand() 方法的返回值设为 START_STICKY
    ,服务就会在资源紧张的时候被杀掉,然后在资源足够的时候再恢复。当然也可设置为前台服务,使其有高的优先级,在资源紧张的时候也不会被杀掉。

    第二种情况:
    用户干预,主动杀掉运行中的服务。这个过程杀死服务会通过服务的生命周期,也就是会调用 onDestory() 方法,这时候一个方案就是在 onDestory() 中发送广播开启自己。这样杀死服务后会立即启动。如下:

     @Override
        public void onCreate() { // TODO Auto-generated method stub 
            super.onCreate();
            mBR = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    Intent a = new Intent(ServiceA.this, ServiceA.class);
                    startService(a);
                }
            };
            mIF = new IntentFilter();
            mIF.addAction("listener");
            registerReceiver(mBR, mIF);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Intent intent = new Intent();
            intent.setAction("listener");
            sendBroadcast(intent);
            unregisterReceiver(mBR);
        }
    

    当然,从理论上来讲这个方案是可行的,实验一下也可以。但有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没接收到广播就销毁了(这是我对实验结果的猜想,具体执行步骤暂时还不了解)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B,服务B监听A的广播来启动A。经过实验,这个方案可行,并且用360杀掉后几秒后服务也还是能自启的。到这里再说一句,如果不是某些功能需要的服务,不建议这么做,会降低用户体验。
    第三种情况:
    强制关闭就没有办法。这个好像是从包的level去关的,并不走完整的生命周期。所以在服务里加代码是无法被调用的。处理这个情况的唯一方法是屏蔽掉 force stop
    和 uninstall
    按钮,让其不可用。方法自己去找吧。当然有些手机自带的清理功能就是从这个地方清理的,比如华为的清理。所以第三种情况我也没有什么更好的办法了。

    相关文章

      网友评论

          本文标题:3.Service

          本文链接:https://www.haomeiwen.com/subject/pxmgjttx.html