众所周知, Service是跑后台的. 但是有些Rom厂商把一键清理做的真是太好用了, 以至于一键清理变成了一种习惯, Service已经变的不再是Service了. 那为什么像诸如360, 微信, QQ...却可以傍山傍水.哦, 用错词了. 大家懂的. .
言归正传, android的系统进程分为五个等级, Foreground Process(前台进程), Visible Process(可见进程), Service Process(服务进程), Background Process(后台进程), Empty Process(空进程), Service的进程处于第三个位置. 系统的回收会从低到高依次回收, 所以我们必须提高Service的等级, 仔细看Service的API会发现这么个方法.
public final void startForeground (int id, Notification notification)
这个方法是从API 5开始的, 又说费话了. 但是用了之后会发现通知栏会弹出个通知, 不弹通知人家让你传Notification干嘛, 哦, 好吧, 我又NC了. 这就很好的解释了360和LBE这些软件的那个通知了. 那QQ,微信为什么没有呢. 方法是死的, 人是活的.
我们可以这样.
private void startForegroundCompat() { try { if (Build.VERSION.SDK_INT < 18) { Log.v(TAG, "startForgroundCompat"); startForeground(1120, new Notification()); } } catch (Exception e) { if (DEBUG) Log.e(TAG, "", e); } }
为什么要低于版本18呢, 那你这句就问的就是废话了. 有Bug呗, 开个玩笑, 在版本18以及以上, 会弹出个默认的通知, so, 要低于版本18.
那有人可能又想, 那我们写成这样呢.
startForeground(1120, null);
当然也不行了, 要是行还new个空的干嘛, 这样会报错滴.
如果这样做之后, 你会发现一键清理对你的Service是完全不起作用的(再也没有那该死的正在重新启动了, 你这么吊, 你经理知道吗, 啊. 啊). 你可以哈哈大笑了, 总算解决了个残留很久的问题了. 但是别高兴太早, 一切都是有条件的. 实现以上效果必须系统同意你开机启动(开机启动? 跟着有毛关系? 唉....且看下文), 测试机型MIUI V5, 我也不知道它的那个自启动管理怎么做的, 我去了开机启动的权限以及广播, 它那里还是会显示, 只有点允许才OK, so, 如果你的用户大多是MIUI系统的话, 要想在那里面自动允许, 只能商务了, 要不你也可以像360那样, 整个引导界面, 让用户操作.
网上还有说通过startCommand的返回值让Service是否重新启动, 我觉着这样很不好.
第一, 用户清理这是一对多的关系,也许用户并不想清理你的程序呢(当然这概率有点小. 你又不是微信, 人家是拿到船票的人, 跟你我屌丝能一样吗), 所以这样做的必要是有的. 好像跟上面的问题没多大关系啊.
其二, 我想清理, 结果你还重新启动, 哇靠, 这什么APP, 这么流氓, 关键我都定位到你那个详情了, 点停止你还启, 点停止你还启...比如那个类微信...(当然也可以清理, 等它重新启动的时候再停止一次, 就See Bye了)
最后, 咱最终还是本着决定权在用户手里的原则, 你要是真的让我走, 我绝不死机白咧, 但是我得知道, 你真的指的是我, 走, 也要走的唯一!
按常理的话, 题目的解释到这里就完成了.
但是我这人吧, 就喜欢多做一点点. 永远超出别人的预期. 吼哈....
有的人会想, 那我API18以后怎么办, 我, 我, 我也不知道撒...
但是我可以保证的是, 只要用户不删你的APP, 你的服务就可以一直是活动的.
<receiver android:name=".NotifyReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.TIME_SET" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.DATE_CHANGED" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.TIMEZONE_CHANGED" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <action android:name="android.intent.action.PACKAGE_REPLACED" /> <data android:scheme="package" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.MEDIA_BAD_REMOVAL" /> <action android:name="android.intent.action.MEDIA_EJECT" /> <action android:name="android.intent.action.MEDIA_MOUNTED" /> <action android:name="android.intent.action.MEDIA_REMOVED" /> <action android:name="android.intent.action.MEDIA_SCANNER_FINISHED" /> <action android:name="android.intent.action.MEDIA_SCANNER_STARTED" /> <action android:name="android.intent.action.MEDIA_SHARED" /> <action android:name="android.intent.action.MEDIA_UNMOUNTED" /> <data android:scheme="file" /> </intent-filter> </receiver>
你注册这么个广播接收器, 在里面启动你的Service(当然启动的时候最好判断下是否启动), 除非用户不操作手机, 不安装, 不卸载, 网络环境一直不变化. 否则, 嘿嘿
What, 我这是在扇自己的脸吗. 我只是说有这么个方案, 当然不太建议大家去这么做, 简直太流氓了, 反正我是这么做了. 需求让人迷失自己!!! 迷失 Noooooooo, 程序员是没有自己的.
最后欢迎大家来到群:215621863 , 讨论有技术, 没技术的.