关于Service常驻内存不被清理的解决方法.

2019-03-02 01:05|来源: 网路

  众所周知, Service是跑后台的. 但是有些Rom厂商把一键清理做的真是太好用了, 以至于一键清理变成了一种习惯, Service已经变的不再是Service了. 那为什么像诸如360, 微信, QQ...却可以傍山傍水.哦, 用错词了. 大家懂的. .

  言归正传, android的系统进程分为五个等级, Foreground Process(前台进程), Visible Process(可见进程), Service Process(服务进程), Background Process(后台进程), Empty Process(空进程), Service的进程处于第三个位置. 系统的回收会从低到高依次回收, 所以我们必须提高Service的等级, 仔细看Service的API会发现这么个方法.

看官方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必须在自启动管理里允许, 否则下文一切都是扯淡.

网上还有说通过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 , 讨论有技术, 没技术的. 


转自:http://www.cnblogs.com/fangyucun/p/3533731

相关问答

更多
  • MySql增删查改乱码的解决方法集合 解决MySql数据乱码: 1 写过滤器设置编码格式(格式和JSP页面的编码一样),或则在请求里面写request.setCharacterEncoding("编码方式"); 2 如果是查询出数据乱码,在链接的URL上加上编码格式(你这里加了,没问题); 3 修改my.ini文件里面的 default-character-set= 您要的编码格式 (一共有两处,你查找一下 改为一样的编码格式) 3 如果是写入到数据库之后是乱码(前提是已经写了过滤器处理编码),修改my.i ...
  • 跨服务器查询语句时 不能用with (nolock) 只能用nolock 同一个服务器查询时 则with (nolock)和nolock都可以用。 比如 select * from [IP].a.dbo.table1 with (nolock) 这样会提示用错误。 select * from a.dbo.table1 with (nolock) 这样就可以。 要提升SQL的查询效能,一般来说大家会以建立索引(index)为第一考虑。其实除了index的建立之外,当我们在下SQL Command时,在语法中加 ...
  • POI的诞生解决了Excel的解析难题(POI即“讨厌的电子表格”),但如果用不好POI,也会导致程序出现一些BUG,例如内存溢出,假空行,公式等等问题。下面介绍一种解决POI读取Excel内存溢出的问题。 POI读取Excel有两种模式,一种是用户模式,一种是SAX模式,将xlsx格式的文档转换成CVS格式后再进行处理用户模式相信大家都很清楚,也是POI常用的方式,用户模式API接口丰富,我们可以很容易的使用POI的API读取Excel,但用户模式消耗的内存很大,当遇到很多sheet、大数据网格、假空行、 ...
  • when()不是你的类MyClass的一部分的方法。 它是班级Mockito的一部分: Mockito.when(test.getUniqueId()).thenReturn(43); 或者,使用静态导入: import static org.mockito.Mockito.*; ... when(test.getUniqueId()).thenReturn(43); The method when() is not part of your class MyClass. It's part of ...
  • 您可以先调用inherited并检查属性是否仍然设置: destructor TMemCorrectedDictionary.Destroy; begin inherited; Values.Free; Keys.Free; end; 顺便说一句: Free并不关心要释放的实例是否nil ,所以如果(但仅限于) inherited Destroy将属性设置为nil ,这将起作用。 You could call inherited first and check if the propertie ...
  • 方法setDateListener(DateListener dl)无法解析。 它是公共的,我在类DatePickerFragment.java的对象上使用它,其中包含方法。 当您将引用分配给超类型时会发生这种情况。 DatePickerFragment是一个DialogFragment ,相反, DialogFragment不是DatePickerFragment The method setDateListener(DateListener dl) cannot be resolved. It is p ...
  • 不幸的是,没有简单的方法可以做到这一点。 你所拥有的是糟糕的代码,并且必须像所有其他不良代码一样纠正错误的代码:修复它并用好的代码替换它。 这里没有适用的创可贴; 创可贴是调用Dispose()的Form的终结器,它永远不会发生。 如果对象没有资格进行收集,那么ANTS Memory Profiler将向您显示对其进行引用的内容。 Unfortunately, there is no easy way to do this. What you have is bad code, and that bad c ...
  • 您的选项1和2似乎在做同样的事情(测试应该确认这一点) 我认为GoTo构造是流程的中断 - 如果(当)它变得更复杂,它将更难调试 你是对的 - 复制代码永远不会有帮助,但我会简化代码 Dim offsetVal As String For Each cel In WorkCenterFields cel.Validation.Delete offsetVal = cel.Offset(0, -1).Value2 If Len(offsetVal) > 0 Then ...
  • 使用渐变检查点将有助于内存限制。 Using gradient checkpointing will help with memory limits.