New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[问答] Android应用中,如何保证服务常驻内存? #49

Open
jasonross opened this Issue Mar 12, 2015 · 46 comments

Comments

Projects
None yet
@jasonross

jasonross commented Mar 12, 2015

No description provided.

@Trinea Trinea added the help wanted label Mar 12, 2015

@stackvoid

This comment has been minimized.

stackvoid commented Mar 12, 2015

不可避免,当系统内存非常紧张并且轮到 Service 进程被杀的时候,这时候在非 root 的 Android 手机/平板 都是无力回天的;一般来说系统杀掉 Service,过 5-10 秒会再次启动 Service(如果有应急机制)。

其实问题的实质就是:系统重启 Service 后,如何保持与重启前一样?

设置 onStartCommand() 的返回值(这里牵扯到 Service 的启动方式)。

onStartCommand() 有其中两个返回值:

START_STICKY:kill 后会被重启,但重启后调用 onStartCommand(Intent,int,int),但是传进来的 Intent这个参数为 null,

START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。

当然还有一种流氓的做法来提升 Service 的优先级:使用startForeground(),但是下拉菜单会显示。

@zshu

This comment has been minimized.

zshu commented Mar 12, 2015

很想知道WX的那个常驻服务是怎么实现的,怎么杀都杀不死?
自己写得常驻服务使用,强制关闭服务后会自动重启服务,但是使用某些第三方清理程序后,就不会再重启了。
另外贴一个服务相关的帖子.希望给你带来帮助。
http://www.cnblogs.com/newcj/archive/2011/05/30/2061370.html

@grumoon

This comment has been minimized.

grumoon commented Mar 12, 2015

如果只是Andorid自身机制,因为内存紧张导致service杀掉,可以采用onStartCommand()设置返回值方式
但如果是被 清理内存软件 杀掉,上面的方式都是失效了。

例如:微信,qq这种的,能看到有两个进程,但是不知道怎么实现的不被杀死,期待有人给出答案或者实现思路。

@stackvoid

This comment has been minimized.

stackvoid commented Mar 12, 2015

楼上,如果是因为系统内存紧张而把此 Service 杀死,同样也是不执行 onDestory的,所以您说的第二条是行不通的。

@shcalm

This comment has been minimized.

shcalm commented Mar 12, 2015

说个道听途说的,,各个清理内存软件有个白名单.....

@grumoon

This comment has been minimized.

grumoon commented Mar 12, 2015

@stackvoid 谢谢,已经改了
不知道有没有方式应对这种清理内存软件造成的service被杀死?

@jcb316733855

This comment has been minimized.

jcb316733855 commented Mar 12, 2015

返回START_STICKY
另外可以将Service与UI部分的进程分离开,Service本身后台运行OOM_ADJ值是蛮低的,不会被LowMemoryKiller干掉。

@chriszeng87

This comment has been minimized.

chriszeng87 commented Mar 12, 2015

@shcalm 从哪听的。。。靠谱不。。。

@jasonross

This comment has been minimized.

jasonross commented Mar 12, 2015

@chriszeng87 MIUI默认不清除QQ和微信的吧,这种应用不小心清了,会被小白骂的

@pcqpcq

This comment has been minimized.

pcqpcq commented Mar 13, 2015

从用户角度讲,常驻后台这个事情我非!常!强!烈!的建议大家不要去做。无奈国内的环境才会想要这样干。

update: DELETED

@Halin-Lee

This comment has been minimized.

Halin-Lee commented Mar 13, 2015

@NiaNingXue

This comment has been minimized.

NiaNingXue commented Mar 13, 2015

楼上的楼上正解。360之类的就是fork出c进程,多进程守护。死循环在那检查是否还存活,简直丧心病狂。手机能不耗电嘛!哎

@shawnlinboy

This comment has been minimized.

shawnlinboy commented Mar 15, 2015

其实还有一个很 hack 的方法,就是在服务的 onCreate 里面设置 startForeground(FOREGROUND_ID, new Notification.Builder(this).build());用通知的方式来实现。这个时候其实相当于 app 是没有退出的。

但是这样有个不好的地方就是在原生 Android 会在顶栏提示“XXX正在运行”

@wangsg

This comment has been minimized.

wangsg commented Mar 16, 2015

fork出来子进程 那位楼主说得对

@liuchenx

This comment has been minimized.

liuchenx commented Mar 21, 2015

@pcqpcq 这个方法我用过 不过在miui上还是会被杀掉 ,请问下你试过吗

@stackvoid

This comment has been minimized.

stackvoid commented Mar 27, 2015

Dear all,

大家有没有考虑过一个问题,如果系统被 root 了,Service拿到 root 权限并且运行在单进程中,此时我将此 Service 权限无限提升,甚至提升到比 init 进程还高,此时 Service 岂不是永生了(除非掉电)..........

@pcqpcq

This comment has been minimized.

pcqpcq commented Mar 27, 2015

@liuchenx 我这里提到的只是核心的实现,要兼容以及稳定还需要其他额外的事情,我没写出来是不想这个做法太多人用。你可以再研究下,有办法兼容的~

@yanbober

This comment has been minimized.

yanbober commented Apr 2, 2015

不建议这么做,只会坑自己和设备性能

@zmywly8866

This comment has been minimized.

@qianzui

This comment has been minimized.

qianzui commented Apr 13, 2015

startForeground第一个参数传入0的话就不会在通知栏显示啦

@shcalm

This comment has been minimized.

shcalm commented Apr 28, 2015

android 5.0用fork的方法不起作用..因为5.0的代码会把processgroup全部停掉.
一像素的那个还没实验过....

@t12x3456

This comment has been minimized.

t12x3456 commented May 26, 2015

@pcqpcq Android 5.0上采用fork的方式是无法起作用的,当父进程被杀死的时候,对应fork出来的子进程会被系统主动调用waitpid将其停止并回收.这修改应该是google觉得之前不作限制的话太流氓了,会影响整个android的运行环境. 可以看得出来,从android4.4开始,会对权限的把控越来越严格,让android系统生态越来越健康

@pcqpcq

This comment has been minimized.

pcqpcq commented May 26, 2015

@shcalm @t12x3456 好的,谢谢分享! 😄

@hexiaochun

This comment has been minimized.

hexiaochun commented Jul 7, 2015

鹅厂的一像素是怎么做到的,有人能给个思路么

@leirenbaobao

This comment has been minimized.

leirenbaobao commented Jul 20, 2015

是不是宽和高都是1sp?

@dotcool

This comment has been minimized.

dotcool commented Jul 24, 2015

求给思路,一像素。。。(欢迎来这里 : E家课堂 http://www.ejiakt.com)

@jovezhougang

This comment has been minimized.

jovezhougang commented Jul 26, 2015

先在手机都带一键杀死功能,引导加入白名单吧

@onceyoung

This comment has been minimized.

onceyoung commented Aug 19, 2015

目前我也在做这方面的研究,除了fork子进程,还有其他办法吗?根据楼上的说法,好像5.0也没法用了。

@Qixingchen

This comment has been minimized.

Qixingchen commented Aug 19, 2015

​做前台服务,优先级和前台应用一个级别​

2015-08-19 15:20 GMT+08:00 onceyoung notifications@github.com:

目前我也在做这方面的研究,除了fork子进程,还有其他办法吗?根据楼上的说法,好像5.0也没法用了。


Reply to this email directly or view it on GitHub
#49 (comment)
.

@onceyoung

This comment has been minimized.

onceyoung commented Aug 19, 2015

做前台只能提高服务优先级吧,但被那些垃圾清理之类的软件杀掉的时候,好像并不能解决。

@Qixingchen

This comment has been minimized.

Qixingchen commented Aug 19, 2015

引导加白名单
Root想要杀你的时候,你是没有办法的。

2015-08-19 15:36 GMT+08:00 onceyoung notifications@github.com:

做前台只能提高服务优先级吧,但被那些垃圾清理之类的软件杀掉的时候,好像并不能解决。


Reply to this email directly or view it on GitHub
#49 (comment)
.

@onceyoung

This comment has been minimized.

onceyoung commented Aug 19, 2015

那也就是说,微信在某些清理软件的白名单里了?不过我发现,杀微信的时候,微信的服务会出现“正在重新启动”这样的情况,说明还是杀掉了,不过自己重启了。

@Qixingchen

This comment has been minimized.

Qixingchen commented Aug 19, 2015

微信在基本所有的国内清理软件的白名单里。

当你的应用不能用时,用户会说“什么破手机,连XX都不能用”的话,你的应用久在白名单里了。

服务因内存低被清理后,内存空余时就会自动恢复。

2015-08-19 15:46 GMT+08:00 onceyoung notifications@github.com:

那也就是说,微信在某些清理软件的白名单里了?不过我发现,杀微信的时候,微信的服务会出现“正在重新启动”这样的情况,说明还是杀掉了,不过自己重启了。


Reply to this email directly or view it on GitHub
#49 (comment)
.

@myronlee

This comment has been minimized.

myronlee commented Sep 15, 2015

在系统的限制下,从两个方面考虑,一是提升进程优先级,保证不被轻易的 kill 掉,二是当系统资源短缺不得不 kill 掉我的进程时,期待系统资源充足的时候,重新启动我的服务。
后者,通过在 onStartCommand返回不同的值现实不同的策略,如果想要系统重新启动服务,使用START_STICKY 或者 START_REDELIVER_INTENT。
前者可以通过 startForeground将进程设置为前台进程,除非在系统内存非常缺,否则此进程不会被 kill。还可以通过把 Service 放在单独进程执行,这样占用的内存更少,系统不会盯上它(在系统内存吃紧的情况下会去会砍掉内存占用较多的进程)。

@moyenvlang

This comment has been minimized.

moyenvlang commented Dec 7, 2015

加入白名单了就不会被kill掉了吗?

@xiaoxiaoqingyi

This comment has been minimized.

xiaoxiaoqingyi commented Dec 8, 2015

这个问题也困扰了我很久,确实,加入各大安全应用商白名单,是一个解决办法,至于NDK开发,也许还是一条探索的路。像魅族系统,它能直接把 极光推送直接kill掉,不能重启。试问,我们要做社交应用的,不能常驻后台,将会是一个大问题。

@ghost

This comment has been minimized.

ghost commented Dec 16, 2015

在5.0以上,可以使用NotificationListenerService,这样的话在有Notification发出的时候,app都可以收到,不过因为能够接触到所有其他的应用的通知,比较敏感

@goodbranch

This comment has been minimized.

goodbranch commented Mar 8, 2016

@a23qws 能否详细说下

@ghost

This comment has been minimized.

ghost commented Mar 8, 2016

@aoqianglin
NotificationListenerService,继承自这个类的服务,系统会将此服务作为系统服务的一部分,所以不会被杀死,具体你看看文档就好了,文档是最清楚的

@goodbranch

This comment has been minimized.

goodbranch commented Mar 9, 2016

@a23qws 这种方式可行性不高,有360手机助手在除了华为上,其他5.0上下都杀不死的原理的建议吗

@goodbranch

This comment has been minimized.

goodbranch commented Mar 9, 2016

@onceyoung 你写一个demo把包名改成微信,什么也不做也杀不死,这就是一个微信已经强大到没人去杀他了

@ghost

This comment has been minimized.

ghost commented Mar 9, 2016

@aoqianglin
如果你没有尝试过这个方案,就先去试一下。

@goodbranch

This comment has been minimized.

goodbranch commented Mar 10, 2016

@a23qws 试了,要进入系统权限页面获取权限才行,难道可以破解这个权限?

@thinking1001

This comment has been minimized.

thinking1001 commented May 18, 2016

最近在做桌面小控件含时钟,想解决被内存清理杀死的问题。
我观察了墨迹天气,进程都被杀死了,不知道为啥桌面的插件时钟居然没停止。

@ghost

This comment has been minimized.

ghost commented May 20, 2016

关于widget的存活,我没有深入研究。如果你有发现,告诉我们

Sent from Nylas N1, the extensible, open source
mail client.

On 5月 18 2016, at 2:21 下午, thinking1001 <notifications@github.com>
wrote:

最近在做桌面小控件含时钟,想解决被内存清理杀死的问题。
我观察了墨迹天气,进程都被杀死了,不知道为啥桌面的插件时钟居然没停止。


You are receiving this because you were mentioned.
Reply to this email directly or [view it on GitHub](https://github.com
//issues/49#issuecomment-219935477)![](https://githu
b.com/notifications/beacon/AEimvOgcJU53a_KnXhES2X0q3hl5Wk6Wks5qCq_ygaJpZM4DtaM
I.gif)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment