android配置应用开机启动,运行时不被kill
创始人
2025-05-30 00:46:27
0

前言

在android系统开发过程中,我们有时候需要配置我们的某个应用,在开机后自动启动,并在设备低内存时不被kill。

如何实现

我们可以配置应用的AndroidManifest.xml

    

配置peristent属性。

persist应用启动流程

ActivityManagerService.java

    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {traceLog.traceBegin("PhaseActivityManagerReady");...// Only start up encryption-aware persistent apps; once user is// unlocked we'll come back around and start unaware apps//启动persist应用,在启动launcher之前startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);     ...   if (bootingSystemUser) {//启动lunchermAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");}..}

继续看startPersistentApps 函数

    void startPersistentApps(int matchFlags) {if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;synchronized (this) {try {final List apps = AppGlobals.getPackageManager().getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();for (ApplicationInfo app : apps) {if (!"android".equals(app.packageName)) {addAppLocked(app, null, false, null /* ABI override */);}}} catch (RemoteException ex) {}}}

startPersistentApps 函数中,遍历当前系统中persistent属性的app,非android进程时执行addApplocked;

    @GuardedBy("this")final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,String abiOverride) {return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,false /* mountExtStorageFull */, abiOverride);}// TODO: Move to ProcessList?@GuardedBy("this")final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) {ProcessRecord app;if (!isolated) {app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,info.uid, true);} else {app = null;}if (app == null) {app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,new HostingRecord("added application",customProcess != null ? customProcess : info.processName));mProcessList.updateLruProcessLocked(app, false, null);updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);}// This package really, really can not be stopped.try {AppGlobals.getPackageManager().setPackageStoppedState(info.packageName, false, UserHandle.getUserId(app.uid));} catch (RemoteException e) {} catch (IllegalArgumentException e) {Slog.w(TAG, "Failed trying to unstop package "+ info.packageName + ": " + e);}if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {app.setPersistent(true);app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;}if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);mProcessList.startProcessLocked(app, new HostingRecord("added application",customProcess != null ? customProcess : app.processName),disableHiddenApiChecks, mountExtStorageFull, abiOverride);}return app;}

addAppLocked 启动persistent应用,并配置maxAdj = PERSISTENT_PROC_ADJ = -800;
同时将app,添加到mPersistentStartingProcesses 列表中
-800 表示进程属于高优先级,当系统资源紧张时,lowmemorykiller机制回收应用时会跳过persistent进程。

重启机制

虽然我们设置了persistent 应用的adj = -800,但是并不能保证100%不会被kill,例如通过adb kill pids kill。
google 对persistent应用做了重启机制。
重启机制
android在进程启动后调用到attachApplicationLocked时会创建一个进程死亡监听器AppDeathRecipient
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @GuardedBy("this")private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {......final String processName = app.processName;try {//app死亡监听器AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);app.deathRecipient = adr;} catch (RemoteException e) {app.resetPackageList(mProcessStats);mProcessList.startProcessLocked(app,new HostingRecord("link fail", processName));return false;}......}	private final class AppDeathRecipient implements IBinder.DeathRecipient {final ProcessRecord mApp;final int mPid;final IApplicationThread mAppThread;AppDeathRecipient(ProcessRecord app, int pid,IApplicationThread thread) {if (DEBUG_ALL) Slog.v(TAG, "New death recipient " + this+ " for thread " + thread.asBinder());mApp = app;mPid = pid;mAppThread = thread;}@Overridepublic void binderDied() {//当应用死亡后,调用binderDiedif (DEBUG_ALL) Slog.v(TAG, "Death received in " + this+ " for thread " + mAppThread.asBinder());synchronized(ActivityManagerService.this) {appDiedLocked(mApp, mPid, mAppThread, true);}}}	// 	appDiedLocked@GuardedBy("this")final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,boolean fromBinderDied) {......if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,"Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());//处理app diedhandleAppDiedLocked(app, false, true);		......}//hadlerAppDiedLocked@GuardedBy("this")final void handleAppDiedLocked(ProcessRecord app,boolean restarting, boolean allowRestart) {int pid = app.pid;//boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,false /*replacingPid*/);if (!kept && !restarting) {removeLruProcessLocked(app);if (pid > 0) {ProcessList.remove(pid);}}if (mProfileData.getProfileProc() == app) {clearProfilerLocked();}mAtmInternal.handleAppDied(app.getWindowProcessController(), restarting, () -> {Slog.w(TAG, "Crash of app " + app.processName+ " running instrumentation " + app.getActiveInstrumentation().mClass);Bundle info = new Bundle();info.putString("shortMsg", "Process crashed.");finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);});}

appDiedLocked()最终会执行到cleanUpApplicationRecordLocked(),我们可以看一下这个方法做了什么

    @GuardedBy("this")final boolean cleanUpApplicationRecordLocked(ProcessRecord app,boolean restarting, boolean allowRestart, int index, boolean replacingPid) {......} else if (!app.removed) {// This app is persistent, so we need to keep its record around.// If it is not already on the pending app list, add it there// and start a new process for it.// app是mPersistentStartingProcesses 列表中的应用时,restart = trueif (mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);restart = true;}}//restart  = true app应用重启      if (restart && !app.isolated) {// We have components that still need to be running in the// process, so re-launch it.if (index < 0) {ProcessList.remove(app.pid);}mProcessList.addProcessNameLocked(app);app.pendingStart = false;mProcessList.startProcessLocked(app,new HostingRecord("restart", app.processName));return true;

我们看到发现是persistent应用时,设置restart = true,并调用重启。

相关内容

热门资讯

热血怎么升级快? 热血怎么升级快?热血怎么升级快?有钱最容易可以雇人练或者干脆买个号,没钱的话自己开个法师练的相对快1...
弋阳:法治温暖人心 “典”亮美...   5月29日,江西省上饶市弋阳县局开展了民法典宣传活动。  气象工作人员为公众发放民法典宣传资料,...
五粮液:禁酒令对公司影响,董秘... 投资者提问:您好,5月中旬出的禁酒令,各地也有一些公务用酒的禁酒令。我想请问一下,对贵公司影响大不大...
我想要一个学习团队的名称中文的... 我想要一个学习团队的名称中文的,适合我们初中生的,比较有新意的,我们团队是四女二男。非主流的不要,最...
超大现代(00682):中正天... 超大现代(00682)发布公告,开元信德会计师事务所有限公司(开元信德)已辞任公司核数师,自2025...
土木工程都包括哪些专业 土木工程都包括哪些专业本身就是一个专业,我就是学这个的,这个领域很广泛,通常包括:房屋结构、监理、工...
当“端午”遇上“六一”,汉森制... 转自:汉森制药      传统文化润童心浓情端午叶飘香当 “屈原” 遇上 “哪吒与敖丙”当 “雄黄酒...
河北内丘:魅力科技 创新科普 中新网河北新闻5月30日电 (李铁锤 苏丹丹 刘媛媛)30日,河北省邢台市内丘县第二中学举办“科普进...
西宁湟源:民生工程暖民心 技能... 中新网青海新闻5月30日电(冯亚楠)近年来,西宁市湟源县财政局精准把握职能定位,充分发挥以工代赈资金...
穿越火线这个游戏怎么样? 穿越火线这个游戏怎么样?…这款游戏痕不错,画面逼真,比一般的射击游戏好玩…算是CS的以更逼真效果的改...
中国石油大学(北京)开展“每天... 中国教育报-中国教育新闻网讯(记者 焦以璇)“同学们,这个动作一定要注意手臂伸直,感受腹部的发力。”...
北京市海淀区北部新区实验幼儿园... 中国教育报-中国教育新闻网讯(实习生 赵一琳)5月28日,北京市海淀区北部新区实验幼儿园天阅园内欢声...
华工科技:海外市场方面,公司已... 每经AI快讯,有投资者在投资者互动平台提问:关于800G在北美头部客户的测试问题,实际情况到底怎样?...
品药膳、制香囊、赏民俗……端午... 01:45冯正梅 孔维琴 余云换 封面新闻记者 罗石芊在四川凉山州会东县,端午节是一年中颇为热闹的节...
芯联集成:拓展高端消费领域客户... 投资者提问:请问贵司在家电领域的芯片收入,今年的进展如何?董秘回答(芯联集成SH688469):尊敬...
旅游业是不是新兴的行业 旅游业... 中国经济周刊-经济网讯(邹锡兰)累计接待游客万人次,比去年同期增长%;社会旅游总收入4.62亿元,比...
迎端午佳节,上海公安机关强化社... 转自:上观新闻5月31日至6月2日端午小长假期间,上海市公安局将细化完善勤务部署,强化社会面整体防控...
2019年旅游业成为全球最大的... 从旅游消费发展阶段来看,2008年,我国人均GDP达到3,美元,这意味着我国旅游业从2008年开始进...
邱金凯同志逝世 邱金凯同志遗像 新华社发  新华社北京5月30日电 副大军区职退休干部、原北京军区副司令员邱金凯同志...