欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android關鍵字persistent詳細分析

 更新時間:2021年04月06日 08:41:04   作者:bobby_developer  
這篇文章主要介紹了Android關鍵字persistent的相關資料,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下

Android關鍵字persistent原理分析​

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

經??吹降膒ersistent、process等,下面是自己對persistent關鍵字的分析,直奔主題。

persistent屬性作用

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

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

通過官方注釋我知道該屬性用于是否讓你的應用一直處于運行狀態(tài)(通常說的常駐內存)。設置 該屬性為true的app具有如下特點:

  • 在系統(tǒng)啟動的時候會被系統(tǒng)啟動起來
  • 在該app被強制殺掉后系統(tǒng)會重新啟動該app,這種情況只針對系統(tǒng)內置app,第三方安裝的app不會被重啟

使用

persistent屬性是用于application標簽上的,用法為:

AndroidManifest.xml

<application
 android:persistent="true|false">


</application>

persistent的值默認為false

二、原理分析

通過第一點對persistent的功能說明后我們通過源碼來分析一下它的工作原理

1、persistent屬性的解析

該屬性的解析主要在app被安裝或者系統(tǒng)啟動的時候發(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)會將解析好的所有包信息存放到PKMS中的mPackages的map中,而ApplicationInfo的flag中有一個bit位用于保存該app是否是persistent的。這里只是把保存persistent的flag設置為FLAG_PERSISTENT。在AndroidManifest設置了persistent為true的app是否能夠在被異常殺死后能夠得到重啟的權力需要取決于該app對應的ProcessRecord的persistent屬性,該屬性只有在你的app既在AndroidManifest中配置了persistent=“true”,又是系統(tǒng)內置app時才會被設置為true。

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

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

在系統(tǒng)啟動時ActivityManagerService的systemReady()方法會將所有在AndroidManifest設置了persistent為true的app拉起來

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中調用了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方法中首先是調用PackageManageServices的getPersistentApplications方法獲取到所有在AndroidManifest設置了persistent為true的app,然后調用addAppLocked方法去啟動他們。這樣在AndroidManifest設置了persistent為true的app就隨著系統(tǒng)的啟動而啟動了。

下面看一下getPersistentApplications方法,該方法調用了PKMS中的getPersistentApplicationsInternal方法。

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

之后調用addAppLocked方法啟動app:

 final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,

  String abiOverride) {

 ProcessRecord app;

 //傳遞進來的isolated=false,所有一定會調用getProcessRecordLocked方法,但是由于是第一次啟動,所有返回的app = null

 if (!isolated) {

  app = getProcessRecordLocked(info.processName, info.uid, true);

 } else {

  app = null;

 }



 if (app == null) {

  //為新的app創(chuàng)建新的ProcessRecord對象

  app = newProcessRecordLocked(info, null, isolated, 0);

  updateLruProcessLocked(app, false, null);

  updateOomAdjLocked();

 }



 // This package really, really can not be stopped.

 try {

  //由于是開機第一次啟動,所以新的app的啟動狀態(tài)是將要被啟動狀態(tài),所以

  //該app的停止狀態(tài)stoped被設置為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);

 }

 

 //在這里對persistent的app進行過濾,只有既是系統(tǒng)app,persistent為true的app才會在

 //異常死亡之后被重啟

 if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {

  app.persistent = true;

  app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;

 }

 //如果該app已經啟動了,則不用處理,否則調用startProcessLocked方法啟動app。

 //由于啟動app是異步進行的,會將正在啟動而還沒有啟動完成的app添加到

 //mPersistentStartingProcesses列表中。當啟動完成后 再移除

 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {

  mPersistentStartingProcesses.add(app);

  //啟動該app

  startProcessLocked(app, "added application", app.processName, abiOverride,

   null /* entryPoint */, null /* entryPointArgs */);

 }



 return app;

 }

}

接下來調用startProcessLocked方法啟動app進程,在app啟動完成后會在ActivityThread中調用AMS的attachApplication,將該app從mPersistentStartingProcesses中移除,并注冊一個死亡訃告監(jiān)聽器AppDeathRecipient,用于在app異常被殺后的處理工作。

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

進程啟動時為app注冊了一個死亡訃告,當該app被殺掉之后會調用AppDeathRecipient的binderDied方法,該方法會調用appDiedLocked方法進行善后處理,系統(tǒng)在進程死掉之后會對死掉的進程進行清理和資源回收,但是在這個過程中如果你的app是persistent的話會被重啟:

binderDied

 |

 |——appDiedLocked

   |

   |——handleAppDiedLocked

     |

     |——cleanUpApplicationRecordLocked

在cleanUpApplicationRecordLocked中對persistent為true的app進行重啟

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的,需要對其進行重啟,并把它添加到正在啟動的列表中,并

  //設置restart=true

  if (mPersistentStartingProcesses.indexOf(app) < 0) {

  mPersistentStartingProcesses.add(app);

  restart = true;

  }

 }

....

//經過上面的過濾,會調用這個分支條件重啟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;



}

總結

  1. persistent的聲明在AndroidManifest.xml中的 t屬性,默認值為false
  2. persistent的聲明,必須該app是系統(tǒng)內置應用,并且在AndroidManifest.xml中的聲明android:persisten = “true”,才能生效
  3. persistent的聲明為true的內置app被異常殺死的時候,系統(tǒng)會將其拉起重啟啟動

以上就是Android關鍵字persistent詳細分析的詳細內容,更多關于Android關鍵字persistent的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解Android Activity之間跳轉出現短暫黑屏的處理方法

    詳解Android Activity之間跳轉出現短暫黑屏的處理方法

    本篇文章主要介紹了詳解Android Activity之間跳轉出現短暫黑屏的處理方法,非常具有實用價值,需要的朋友可以參考下
    2017-06-06
  • Android編程之利用服務實現電話監(jiān)聽的方法

    Android編程之利用服務實現電話監(jiān)聽的方法

    這篇文章主要介紹了Android編程之利用服務實現電話監(jiān)聽的方法,較為詳細的分析了Android基于服務實現針對電話監(jiān)聽的具體步驟與相關實現技巧,需要的朋友可以參考下
    2015-11-11
  • Android 進度條顯示在標題欄的實現方法

    Android 進度條顯示在標題欄的實現方法

    android進度條顯示在標題欄的實現方法,大概分文xml文件和java文件,具體代碼內容大家可以通過本文學習下
    2017-01-01
  • Android 多種dialog的實現方法(推薦)

    Android 多種dialog的實現方法(推薦)

    下面小編就為大家分享一篇Android 多種dialog的實現方法(推薦),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Android實現RecyclerView下拉刷新效果

    Android實現RecyclerView下拉刷新效果

    這篇文章主要為大家詳細介紹了Android實現RecyclerView下拉刷新效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android滑動沖突的完美解決

    Android滑動沖突的完美解決

    這篇文章主要為大家詳細介紹了Android滑動沖突的完美解決方案,針對三種滑動沖突場景進行解決,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android開發(fā)實例之多點觸控程序

    Android開發(fā)實例之多點觸控程序

    本文主要介紹 Android開發(fā)多點觸控,這里提供了詳細的資料和示例代碼,以及實現效果圖,有開發(fā)Android應用需要這樣的功能的小伙伴可以參考下
    2016-08-08
  • Android實現圖片文字識別

    Android實現圖片文字識別

    這篇文章主要為大家詳細介紹了Android實現圖片文字識別,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Android  隱式Intent的實例詳解

    Android 隱式Intent的實例詳解

    這篇文章主要介紹了Android 隱式Intent的實例詳解的相關資料,隱式意圖就是在不明確設置激活對象的前提下尋找最匹配的組件,需要的朋友可以參考下
    2017-08-08
  • Android學習項目之簡易版微信為例(一)

    Android學習項目之簡易版微信為例(一)

    這篇文章主要以簡易版微信為例,為大家介紹了Android簡易版微信項目的基礎知識,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評論