返回顶部
首页 > 资讯 > 精选 >persistent关键字怎么在Android中使用
  • 367
分享到

persistent关键字怎么在Android中使用

2023-06-14 10:06:27 367人浏览 八月长安
摘要

本篇文章为大家展示了persistent关键字怎么在Android中使用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Android关键字persistent原理分析在Android程序开发时我们会

本篇文章为大家展示了persistent关键字怎么在Android中使用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

Android关键字persistent原理分析

在Android程序开发时我们会接触到一些系统为了某些功能而定义的关键属性,例如在AndroidManifest.xml文件中

经常看到的persistent、process等,下面是自己对persistent关键字的分析,直奔主题。

persistent属性作用

该属性的定义在frameworks/base/core/res/res/values/attrs_manifest.xml中,其定义如下:

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

通过官方注释我知道该属性用于是否让你的应用一直处于运行状态(通常说的常驻内存)。设置 该属性为true的app具有如下特点:

  • 在系统启动的时候会被系统启动起来

  • 在该app被强制杀掉后系统会重新启动该app,这种情况只针对系统内置app,第三方安装的app不会被重启

使用

persistent属性是用于application标签上的,用法为:

AndroidManifest.xml

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

persistent的值默认为false

二、原理分析

通过第一点对persistent的功能说明后我们通过源码来分析一下它的工作原理

1、persistent属性的解析

该属性的解析主要在app被安装或者系统启动的时候发生

解析代码:

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;  } }//.............}

在解析完包信息之后系统会将解析好的所有包信息存放到PKMS中的mPackages的map中,而ApplicationInfo的flag中有一个bit位用于保存该app是否是persistent的。这里只是把保存persistent的flag设置为FLAG_PERSISTENT。在AndroidManifest设置了persistent为true的app是否能够在被异常杀死后能够得到重启的权力需要取决于该app对应的ProcessRecord的persistent属性,该属性只有在你的app既在AndroidManifest中配置了persistent=“true”,又是系统内置app时才会被设置为true。

2、系统启动时启动persistent为true的app

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

在系统启动时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 );   }  }  } catch (RemoteException ex) {  } } }

在startPersistentApps方法中首先是调用PackageManageServices的getPersistentApplications方法获取到所有在AndroidManifest设置了persistent为true的app,然后调用addAppLocked方法去启动他们。这样在AndroidManifest设置了persistent为true的app就随着系统的启动而启动了。

下面看一下getPersistentApplications方法,该方法调用了PKMS中的getPersistentApplicationsInternal方法。

该方法会遍历mPackages中的所有app,并找到其中在AndroidManifest设置了persistent为true的应用。从代码中可以看到,persistent为true并且是系统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创建新的ProcessRecord对象  app = newProcessRecordLocked(info, null, isolated, 0);  updateLruProcessLocked(app, false, null);  updateOomAdjLocked(); } // This package really, really can not be stopped. try {  //由于是开机第一次启动,所以新的app的启动状态是将要被启动状态,所以  //该app的停止状态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进行过滤,只有既是系统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 , null ); } return app; }}

接下来调用startProcessLocked方法启动app进程,在app启动完成后会在ActivityThread中调用AMS的attachApplication,将该app从mPersistentStartingProcesses中移除,并注册一个死亡讣告监听器AppDeathRecipient,用于在app异常被杀后的处理工作。

3、app被异常结束后系统重新启动persistent为true的app

进程启动时为app注册了一个死亡讣告,当该app被杀掉之后会调用AppDeathRecipient的binderDied方法,该方法会调用appDiedLocked方法进行善后处理,系统在进程死掉之后会对死掉的进程进行清理和资源回收,但是在这个过程中如果你的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是系统内置应用,并且在AndroidManifest.xml中的声明android:persisten = “true”,才能生效

  3. persistent的声明为true的内置app被异常杀死的时候,系统会将其拉起重启启动

上述内容就是persistent关键字怎么在Android中使用,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网精选频道。

--结束END--

本文标题: persistent关键字怎么在Android中使用

本文链接: https://lsjlt.com/news/269945.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • persistent关键字怎么在Android中使用
    本篇文章为大家展示了persistent关键字怎么在Android中使用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Android关键字persistent原理分析在Android程序开发时我们会...
    99+
    2023-06-14
  • Android关键字persistent详细分析
    目录Android关键字persistent原理分析​persistent属性作用 使用 二、原理分析 1、persistent属性的解析 2、系统启动时启动persis...
    99+
    2024-04-02
  • static关键字怎么在java项目中使用
    本篇文章给大家分享的是有关static关键字怎么在java项目中使用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。静态方法通常在一个类中定义一个方法为static,即为静态方法...
    99+
    2023-05-31
    java static ava
  • throw和throws关键字怎么在java中使用
    throw和throws关键字怎么在java中使用?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。在程序中自定义类,大体上分为以下几个步骤:创建自定义异常类在方法...
    99+
    2023-06-06
  • LINQ中的关键字怎么使用
    这篇文章主要讲解了“LINQ中的关键字怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“LINQ中的关键字怎么使用”吧!什么是LINQLINQ是Language Integrated Q...
    99+
    2023-06-17
  • Java中 transient关键字怎么使用
    本篇文章为大家展示了Java中 transient关键字怎么使用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1. transient的作用及使用方法我们都知道一个对象只要实现了Serilizabl...
    99+
    2023-06-19
  • java中abstract关键字怎么使用
    在Java中,abstract关键字主要用于定义抽象类和抽象方法。1. 抽象类的定义:使用abstract关键字修饰类,将其声明为抽...
    99+
    2023-09-23
    java
  • java中this关键字怎么使用
    这篇文章主要介绍了java中this关键字怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java中this关键字怎么使用文章都会有所收获,下面我们一起来看看吧。this 的使用:修饰属性和方法,也可以理...
    99+
    2023-06-26
  • Java中super关键字怎么使用
    这篇文章主要讲解了“Java中super关键字怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中super关键字怎么使用”吧!supersuper是一个关键字,全部小写。sup...
    99+
    2023-07-02
  • C++中register关键字怎么使用
    本篇内容介绍了“C++中register关键字怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!register 简介:register...
    99+
    2023-07-05
  • Java中transient关键字怎么使用
    本篇内容主要讲解“Java中transient关键字怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java中transient关键字怎么使用”吧!一、概要介绍   对...
    99+
    2023-07-06
  • C++中auto关键字怎么使用
    今天小编给大家分享一下C++中auto关键字怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前提引入类型名,在绝大多数...
    99+
    2023-07-06
  • Python中nonlocal关键字与global关键字怎么用
    小编给大家分享一下Python中nonlocal关键字与global关键字怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!python引用变量的顺序: 当前作...
    99+
    2023-06-29
  • java中的volatile关键字怎么使用
    本篇内容介绍了“java中的volatile关键字怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.volatile实现可见性的原理...
    99+
    2023-06-25
  • typeScript中的extends关键字怎么使用
    本篇内容主要讲解“typeScript中的extends关键字怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“typeScript中的extends关键字怎么使用”吧!extends 是 ...
    99+
    2023-07-05
  • java中的super关键字怎么使用
    在Java中,super是一个关键字,用于引用父类的成员变量、成员方法和构造方法。1. 引用父类的成员变量:可以使用super关键字...
    99+
    2023-08-08
    java super
  • java中的final关键字怎么使用
    在Java中,final关键字可以用于修饰类、方法和变量。1. final修饰类:final修饰的类是不可被继承的,即该类不能有子类...
    99+
    2023-08-24
    java final
  • Golang中的defer关键字怎么使用
    在Golang中,defer关键字用于注册一个函数调用,该函数会在当前函数执行完成后被执行,无论函数是正常返回还是发生了panic。...
    99+
    2024-03-13
    Golang
  • 如何在Java中使用synchronized关键字
    如何在Java中使用synchronized关键字?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。java基本数据类型有哪些Java的基本数据类型分为:1、整数类...
    99+
    2023-06-14
  • 如何在java中使用var关键字
    这篇文章将为大家详细讲解有关如何在java中使用var关键字,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。常用的java框架有哪些1.SpringMVC,Spring Web MVC是一种基...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作