电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Android關(guān)鍵字persistent詳細(xì)分析

瀏覽:102日期:2022-09-19 18:14:45
Android關(guān)鍵字persistent原理分析​

在Android程序開(kāi)發(fā)時(shí)我們會(huì)接觸到一些系統(tǒng)為了某些功能而定義的關(guān)鍵屬性,例如在AndroidManifest.xml文件中

經(jīng)常看到的persistent、process等,下面是自己對(duì)persistent關(guān)鍵字的分析,直奔主題。

persistent屬性作用

該屬性的定義在frameworks/base/core/res/res/values/attrs_manifest.xml中,其定義如下:

<attr name='persistent' format='boolean' />

通過(guò)官方注釋我知道該屬性用于是否讓你的應(yīng)用一直處于運(yùn)行狀態(tài)(通常說(shuō)的常駐內(nèi)存)。設(shè)置 該屬性為true的app具有如下特點(diǎn):

在系統(tǒng)啟動(dòng)的時(shí)候會(huì)被系統(tǒng)啟動(dòng)起來(lái) 在該app被強(qiáng)制殺掉后系統(tǒng)會(huì)重新啟動(dòng)該app,這種情況只針對(duì)系統(tǒng)內(nèi)置app,第三方安裝的app不會(huì)被重啟 使用

persistent屬性是用于application標(biāo)簽上的,用法為:

AndroidManifest.xml

<application android:persistent='true|false'></application>

persistent的值默認(rèn)為false

二、原理分析

通過(guò)第一點(diǎn)對(duì)persistent的功能說(shuō)明后我們通過(guò)源碼來(lái)分析一下它的工作原理

1、persistent屬性的解析

該屬性的解析主要在app被安裝或者系統(tǒng)啟動(dòng)的時(shí)候發(fā)生

解析代碼:

frameworks/base/core/java/com/android/content/pm/PackageParser.java

private boolean parseBaseApplication(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException {final ApplicationInfo ai = owner.applicationInfo; //....................... if ((flags&PARSE_IS_SYSTEM) != 0) { if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_persistent, false)) { ai.flags |= ApplicationInfo.FLAG_PERSISTENT; } }//.............}

在解析完包信息之后系統(tǒng)會(huì)將解析好的所有包信息存放到PKMS中的mPackages的map中,而ApplicationInfo的flag中有一個(gè)bit位用于保存該app是否是persistent的。這里只是把保存persistent的flag設(shè)置為FLAG_PERSISTENT。在AndroidManifest設(shè)置了persistent為true的app是否能夠在被異常殺死后能夠得到重啟的權(quán)力需要取決于該app對(duì)應(yīng)的ProcessRecord的persistent屬性,該屬性只有在你的app既在AndroidManifest中配置了persistent=“true”,又是系統(tǒng)內(nèi)置app時(shí)才會(huì)被設(shè)置為true。

2、系統(tǒng)啟動(dòng)時(shí)啟動(dòng)persistent為true的app

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

在系統(tǒng)啟動(dòng)時(shí)ActivityManagerService的systemReady()方法會(huì)將所有在AndroidManifest設(shè)置了persistent為true的app拉起來(lái)

public void systemReady(final Runnable goingCallback) {......synchronized (this) { // Only start up encryption-aware persistent apps; once user is // unlocked we’ll come back around and start unaware apps startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE); // Start up initial activity. mBooting = true; // Enable home activity for system user, so that the system can always boot if (UserManager.isSplitSystemUser()) { ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class); try { AppGlobals.getPackageManager().setComponentEnabledSetting(cName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, UserHandle.USER_SYSTEM); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } }......}

systemReady中調(diào)用了startPersistentApps() 方法

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

在startPersistentApps方法中首先是調(diào)用PackageManageServices的getPersistentApplications方法獲取到所有在AndroidManifest設(shè)置了persistent為true的app,然后調(diào)用addAppLocked方法去啟動(dòng)他們。這樣在AndroidManifest設(shè)置了persistent為true的app就隨著系統(tǒng)的啟動(dòng)而啟動(dòng)了。

下面看一下getPersistentApplications方法,該方法調(diào)用了PKMS中的getPersistentApplicationsInternal方法。

該方法會(huì)遍歷mPackages中的所有app,并找到其中在AndroidManifest設(shè)置了persistent為true的應(yīng)用。從代碼中可以看到,persistent為true并且是系統(tǒng)app的話一定會(huì)被選中,但是如果是第三方安裝的應(yīng)用的話只能在非“安全模式”下才會(huì)被選中。

之后調(diào)用addAppLocked方法啟動(dòng)app:

final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated, String abiOverride) { ProcessRecord app; //傳遞進(jìn)來(lái)的isolated=false,所有一定會(huì)調(diào)用getProcessRecordLocked方法,但是由于是第一次啟動(dòng),所有返回的app = null if (!isolated) { app = getProcessRecordLocked(info.processName, info.uid, true); } else { app = null; } if (app == null) { //為新的app創(chuàng)建新的ProcessRecord對(duì)象 app = newProcessRecordLocked(info, null, isolated, 0); updateLruProcessLocked(app, false, null); updateOomAdjLocked(); } // This package really, really can not be stopped. try { //由于是開(kāi)機(jī)第一次啟動(dòng),所以新的app的啟動(dòng)狀態(tài)是將要被啟動(dòng)狀態(tài),所以 //該app的停止?fàn)顟B(tài)stoped被設(shè)置為false 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); } //在這里對(duì)persistent的app進(jìn)行過(guò)濾,只有既是系統(tǒng)app,persistent為true的app才會(huì)在 //異常死亡之后被重啟 if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { app.persistent = true; app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ; } //如果該app已經(jīng)啟動(dòng)了,則不用處理,否則調(diào)用startProcessLocked方法啟動(dòng)app。 //由于啟動(dòng)app是異步進(jìn)行的,會(huì)將正在啟動(dòng)而還沒(méi)有啟動(dòng)完成的app添加到 //mPersistentStartingProcesses列表中。當(dāng)啟動(dòng)完成后 再移除 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); //啟動(dòng)該app startProcessLocked(app, 'added application', app.processName, abiOverride, null /* entryPoint */, null /* entryPointArgs */); } return app; }}

接下來(lái)調(diào)用startProcessLocked方法啟動(dòng)app進(jìn)程,在app啟動(dòng)完成后會(huì)在ActivityThread中調(diào)用AMS的attachApplication,將該app從mPersistentStartingProcesses中移除,并注冊(cè)一個(gè)死亡訃告監(jiān)聽(tīng)器AppDeathRecipient,用于在app異常被殺后的處理工作。

3、app被異常結(jié)束后系統(tǒng)重新啟動(dòng)persistent為true的app

進(jìn)程啟動(dòng)時(shí)為app注冊(cè)了一個(gè)死亡訃告,當(dāng)該app被殺掉之后會(huì)調(diào)用AppDeathRecipient的binderDied方法,該方法會(huì)調(diào)用appDiedLocked方法進(jìn)行善后處理,系統(tǒng)在進(jìn)程死掉之后會(huì)對(duì)死掉的進(jìn)程進(jìn)行清理和資源回收,但是在這個(gè)過(guò)程中如果你的app是persistent的話會(huì)被重啟:

binderDied

| |——appDiedLocked | |——handleAppDiedLocked | |——cleanUpApplicationRecordLocked

在cleanUpApplicationRecordLocked中對(duì)persistent為true的app進(jìn)行重啟

private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart, int index, boolean replacingPid) {............... //非persistent的app被殺死后就被清理掉 if (!app.persistent || app.isolated) { if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 'Removing non-persistent process during cleanup: ' + app); if (!replacingPid) { removeProcessNameLocked(app.processName, app.uid, app); } if (mHeavyWeightProcess == app) { mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG, mHeavyWeightProcess.userId, 0)); mHeavyWeightProcess = null; } } 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是persistent的,需要對(duì)其進(jìn)行重啟,并把它添加到正在啟動(dòng)的列表中,并 //設(shè)置restart=true if (mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); restart = true; } }....//經(jīng)過(guò)上面的過(guò)濾,會(huì)調(diào)用這個(gè)分支條件重啟persistent為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); } addProcessNameLocked(app); startProcessLocked(app, 'restart', app.processName); return true; } else if (app.pid > 0 && app.pid != MY_PID) { // Goodbye! boolean removed; synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid); if (app.isolated) { mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid); } app.setPid(0); } return false;}總結(jié) persistent的聲明在AndroidManifest.xml中的 t屬性,默認(rèn)值為false persistent的聲明,必須該app是系統(tǒng)內(nèi)置應(yīng)用,并且在AndroidManifest.xml中的聲明android:persisten = “true”,才能生效 persistent的聲明為true的內(nèi)置app被異常殺死的時(shí)候,系統(tǒng)會(huì)將其拉起重啟啟動(dòng)

以上就是Android關(guān)鍵字persistent詳細(xì)分析的詳細(xì)內(nèi)容,更多關(guān)于Android關(guān)鍵字persistent的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 老城街小面官网_正宗重庆小面加盟技术培训_特色面馆加盟|牛肉拉面|招商加盟代理费用多少钱 | 高空重型升降平台_高空液压举升平台_高空作业平台_移动式升降机-河南华鹰机械设备有限公司 | 武汉高温老化房,恒温恒湿试验箱,冷热冲击试验箱-武汉安德信检测设备有限公司 | 润东方环保空调,冷风机,厂房车间降温设备-20年深圳环保空调生产厂家 | 上海洗地机-洗地机厂家-全自动洗地机-手推式洗地机-上海滢皓洗地机 | 压接机|高精度压接机|手动压接机|昆明可耐特科技有限公司[官网] 胶泥瓷砖胶,轻质粉刷石膏,嵌缝石膏厂家,腻子粉批发,永康家德兴,永康市家德兴建材厂 | 除湿机|工业除湿机|抽湿器|大型地下室车间仓库吊顶防爆除湿机|抽湿烘干房|新风除湿机|调温/降温除湿机|恒温恒湿机|加湿机-杭州川田电器有限公司 | 机房监控|动环监控|动力环境监控系统方案产品定制厂家 - 迈世OMARA | 北京网站建设-企业网站建设-建站公司-做网站-北京良言多米网络公司 | 土壤检测仪器_行星式球磨仪_土壤团粒分析仪厂家_山东莱恩德智能科技有限公司 | 邢台人才网_邢台招聘网_邢台123招聘【智达人才网】 | 辊道窑炉,辊道窑炉厂家-山东艾希尔 | 称重传感器,测力传感器,拉压力传感器,压力变送器,扭矩传感器,南京凯基特电气有限公司 | 深圳办公室装修-写字楼装修设计-深圳标榜装饰公司 | 芜湖厨房设备_芜湖商用厨具_芜湖厨具设备-芜湖鑫环厨具有限公司 控显科技 - 工控一体机、工业显示器、工业平板电脑源头厂家 | 河北凯普威医疗器材有限公司,高档轮椅系列,推车系列,座厕椅系列,协步椅系列,拐扙系列,卫浴系列 | 有声小说,听书,听小说资源库-听世界网 | 2-羟基泽兰内酯-乙酰蒲公英萜醇-甘草查尔酮A-上海纯优生物科技有限公司 | 齿轮减速马达一体式_蜗轮蜗杆减速机配电机-德国BOSERL齿轮减速电动机生产厂家 | 油漆辅料厂家_阴阳脚线_艺术漆厂家_内外墙涂料施工_乳胶漆专用防霉腻子粉_轻质粉刷石膏-魔法涂涂 | 耐破强度测试仪-纸箱破裂强度试验机-济南三泉中石单品站 | 重庆小面培训_重庆小面技术培训学习班哪家好【终身免费复学】 | 水平垂直燃烧试验仪-灼热丝试验仪-漏电起痕试验仪-针焰试验仪-塑料材料燃烧检测设备-IP防水试验机 | 无机纤维喷涂棉-喷涂棉施工工程-山东华泉建筑工程有限公司▲ | 耐酸泵,耐酸泵厂家-淄博华舜耐腐蚀真空泵| 陕西华春网络科技股份有限公司 | 矿用履带式平板车|探水钻机|气动架柱式钻机|架柱式液压回转钻机|履带式钻机-启睿探水钻机厂家 | 离子色谱自动进样器-青岛艾力析实验科技有限公司 | 武汉印刷厂-不干胶标签印刷厂-武汉不干胶印刷-武汉标签印刷厂-武汉标签制作 - 善进特种标签印刷厂 | 气体检测仪-氢气检测仪-可燃气体传感器-恶臭电子鼻-深国安电子 | 飞象网 - 通信人每天必上的网站 全球化工设备网—化工设备,化工机械,制药设备,环保设备的专业网络市场。 | HDPE土工膜,复合土工膜,防渗膜价格,土工膜厂家-山东新路通工程材料有限公司 | 土壤有机碳消解器-石油|表层油类分析采水器-青岛溯源环保设备有限公司 | 南京试剂|化学试剂|分析试剂|实验试剂|cas号查询-专业60年试剂销售企业 | 行星齿轮减速机,减速机厂家,山东减速机-淄博兴江机械制造 | 焊接减速机箱体,减速机箱体加工-淄博博山泽坤机械厂 | 传爱自考网_传爱自学考试网| 合肥抖音SEO网站优化-网站建设-网络推广营销公司-百度爱采购-安徽企匠科技 | 99文库_实习生实用的范文资料文库站 | 膏方加工_丸剂贴牌_膏滋代加工_湖北康瑞生物科技有限公司 | 大数据营销公司_舆情监测软件_上海SEO公司-文军营销官网 |