新西兰服务器

怎么在Android中识别预装的第三方App


怎么在Android中识别预装的第三方App

发布时间:2021-02-25 17:00:48 来源:高防服务器网 阅读:195 作者:Leah 栏目:移动开发

这期内容当中小编将会给大家带来有关怎么在Android中识别预装的第三方App,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

<package name="com.tencent.mm"   codePath="/data/app/com.tencent.mm-TSn6yG4fF7A_EaxE5OtrHQ=="   nativeLibraryPath="/data/app/com.tencent.mm-TSn6yG4fF7A_EaxE5OtrHQ==/lib"   primaryCpuAbi="armeabi" publicFlags="945307204"   privateFlags="0" ft="167702c7508" it="1676feab448"   ut="167702c8a57" version="1360" userId="10118">  ...  </package>    <package name="com.android.providers.downloads"   codePath="/system/priv-app/DownloadProvider"   nativeLibraryPath="/system/priv-app/DownloadProvider/lib" publicFlags="944258629"   privateFlags="8" ft="11e8dc5d800" it="11e8dc5d800"   ut="11e8dc5d800" version="28" sharedUserId="10006" isOrphaned="true">  ...  </package>

其中it的值便是安装时间,这里是用十六进制保存的,上面这2个App的安装时间换算成十进制分别是1543770911816和1230739200000,对应的北京时间即2018-12-03 01:15:11和2009-01-01 00:00:00。 【嗯…想不到我12月3号1点多还没睡,还安装了个微信……】

系统启动时,PackageManagerService由SystemServer启动,PackageManagerService会扫描/data/app、/system/app、/system/priv-app、/vendor/app等等目录,可以理解为会把这些目录中的Apk安装一遍,PackageManagerService会结合上面提到的packages.xml把各个App解析成PackageParser.Package对象。

思路

根据上面的知识,我们可以知道,如果packages.xml已经有了某个App的信息,那么这个App的安装时间肯定就是packages.xml中记录的时间。第一次启动手机时packages.xml文件还不存在,或者新安装一个App时,packages.xml中还没有这个App的记录,也就是说,确认这个packages.xml中的firstInstallTime(即it)是如果生成的便是问题的关键。

以下基于7.0.0_r1版本代码。

通过搜索PackageManagerService,在scanPackageDirtyLI方法中有这么一段代码:

// Take care of first install / last update times.  if (currentTime != 0) {   if (pkgSetting.firstInstallTime == 0) {   pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;   } else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {   pkgSetting.lastUpdateTime = currentTime;   }  } else if (pkgSetting.firstInstallTime == 0) {   // We need *something*. Take time time stamp of the file.   pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;  } else if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {   if (scanFileTime != pkgSetting.timeStamp) {   // A package on the system image has changed; consider this   // to be an update.   pkgSetting.lastUpdateTime = scanFileTime;   }  }

其中,currentTime是scanPackageDirtyLI方法的一个参数。pkgSetting是从packages.xml中读取到的该App的信息(PackageSetting对象),如果packages.xml中不存在这个App的信息,会根据从Apk中解析到的信息创建一个PackageSetting。scanFileTime是Apk文件的最后修改时间。
可以看到存在这么几种情况:

  • 传入的currentTime不为0,从packages.xml中读取到的firstInstallTime为0。这种情况会将firstInstallTime和lastUpdateTime均设置为传入的currentTime的值。

  • 传入的currentTime不为0,传入的scanFlags设置了SCAN_UPDATE_TIME。这种情况会将lastUpdateTime设置为传入的currentTime的值。

  • 传入的currentTime为0,从packages.xml中读取到的firstInstallTime为0。这种情况会将firstInstallTime和lastUpdateTime均设置为Apk的最后修改时间。

  • 传入的currentTime为0,从packages.xml中读取到的firstInstallTime不为0,传入的policyFlags设置了PackageParser.PARSE_IS_SYSTEM_DIR,scanFileTime与packages.xml中读取到的timeStamp(packages.xml中package标签的ft)不相同。这种情况会将lastUpdateTime设置为Apk的最后修改时间。

对应到我们真实使用手机的场景,上面4种情况分别对应以下几种场景:

  • 第一种情况:对应新安装App。currentTime为当前的时间戳,会将这个新安装的App的firstInstallTime和lastUpdateTime设置为当前时间戳。

  • 第二种情况:对应更新App。currentTime为当前的时间戳,会将lastUpdateTime设置为当前时间戳,firstInstallTime保持不变。

  • 第三种情况:手机启动时PackageManagerService扫描各个目录时发现了packages.xml中不存在的App(第一次启动时所有App都不在packages.xml中)。

  • 第四种情况:系统更新等操作更新了系统分区的App,导致其文件的最后修改时间和记录的不一致了,会被认为是更新。

我们可以大胆猜测,第一次启动手机时会走第三种情况,因此系统App和预装App的安装时间是文件的最后修改时间,而这些文件的最后修改时间都是整秒的。

如何验证?

我们先看看上面那个com.android.providers.downloads的Apk文件的最后修改时间。

# stat DownloadProvider.apk   File: `DownloadProvider.apk'   Size: 504712	 Blocks: 992	 IO Blocks: 512	regular file  Device: 10305h/66309d	 Inode: 1308	 Links: 1  Access: (644/-rw-r--r--)	Uid: ( 0/ root)	Gid: ( 0/ root)  Access: 2009-01-01 00:00:00.000000000  Modify: 2009-01-01 00:00:00.000000000  Change: 2009-01-01 00:00:00.000000000

时间与packages.xml中保存的时间一致,确实是把文件的最后修改时间作为了安装时间。那么还有一个问题需要确认,传入的currentTime是0吗?

我们追溯调用链,会在PackageManagerService的构造函数中看到扫描各个目录的方法。调用scanDirTracedLI方法传入的最后一个参数0即scanPackageDirtyLI方法中的currentTime。感兴趣的还可以仔细看看PackageManagerService到底扫描了哪些目录。

File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);  scanDirTracedLI(vendorOverlayDir, mDefParseFlags    | PackageParser.PARSE_IS_SYSTEM    | PackageParser.PARSE_IS_SYSTEM_DIR    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);    // Find base frameworks (resource packages without code).  scanDirTracedLI(frameworkDir, mDefParseFlags    | PackageParser.PARSE_IS_SYSTEM    | PackageParser.PARSE_IS_SYSTEM_DIR    | PackageParser.PARSE_IS_PRIVILEGED,    scanFlags | SCAN_NO_DEX, 0);    // Collected privileged system packages.  final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");  scanDirTracedLI(privilegedAppDir, mDefParseFlags    | PackageParser.PARSE_IS_SYSTEM    | PackageParser.PARSE_IS_SYSTEM_DIR    | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);    // Collect ordinary system packages.  final File systemAppDir = new File(Environment.getRootDirectory(), "app");  scanDirTracedLI(systemAppDir, mDefParseFlags    | PackageParser.PARSE_IS_SYSTEM    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);    // Collect all vendor packages.  File vendorAppDir = new File("/vendor/app");  try {   vendorAppDir = vendorAppDir.getCanonicalFile();  } catch (IOException e) {   // failed to look up canonical path, continue with original one  }  scanDirTracedLI(vendorAppDir, mDefParseFlags    | PackageParser.PARSE_IS_SYSTEM    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);    // Collect all OEM packages.  final File oemAppDir = new File(Environment.getOemDirectory(), "app");  scanDirTracedLI(oemAppDir, mDefParseFlags    | PackageParser.PARSE_IS_SYSTEM    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);    ...    scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);    scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags    | PackageParser.PARSE_FORWARD_LOCK,    scanFlags | SCAN_REQUIRE_KNOWN, 0);

如果感兴趣,你可以去跟一下安装App和更新App的代码,看传入的currentTime是不是当前的时间戳。

到此,我们已经证明了第一次启动手机时,系统会把文件的最后修改时间当成系统App和预装App的安装时间,而这个时间一般是类似于上面那样2009-01-01 00:00:00.000000000的整秒的时间(至于为什么是这样,那就是另一个问题了),而我们自己安装App时几乎不可能在一个整秒的时间安装,所有我们可以用安装时间是否为整秒来区分手机预装的App和用户手动安装的App

上述就是小编为大家分享的怎么在Android中识别预装的第三方App了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注高防服务器网行业资讯频道。

[微信提示:高防服务器能助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

[图文来源于网络,不代表本站立场,如有侵权,请联系高防服务器网删除]
[