Android 得到安装包的信息

编程入门 行业动态 更新时间:2024-10-10 10:32:38

Android 得到<a href=https://www.elefans.com/category/jswz/34/1769751.html style=安装包的信息"/>

Android 得到安装包的信息

得到安装包的所有的信息

  一个APK安装包它的相关信息都配置在AndroidManifest.xml中,将它解析出来之后,是存放在PackageInfo类对象中,而PackageInfo类对象的生成相关代码,实现在PackageUtil类的getPackageInfo()方法中,看一下它的实现:

    @Nullablepublic static PackageInfo getPackageInfo(Context context, File sourceFile, int flags) {try {return context.getPackageManager().getPackageArchiveInfo(sourceFile.getAbsolutePath(),flags);} catch (Exception ignored) {return null;}}

  在这context一般是Activity实例,context.getPackageManager()得到的是ApplicationPackageManager实例。看一下它的getPackageArchiveInfo(sourceFile.getAbsolutePath(), flags)方法:

    @Nullablepublic PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath,@PackageInfoFlags int flags) {if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE| PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) {// Caller expressed no opinion about what encryption// aware/unaware components they want to see, so match bothflags |= PackageManager.MATCH_DIRECT_BOOT_AWARE| PackageManager.MATCH_DIRECT_BOOT_UNAWARE;}boolean collectCertificates = (flags & PackageManager.GET_SIGNATURES) != 0|| (flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0;ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset();ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefault(input,new File(archiveFilePath), 0, getPermissionManager().getSplitPermissions(),collectCertificates);if (result.isError()) {return null;}return PackageInfoWithoutStateUtils.generate(result.getResult(), null, flags, 0, 0, null,new PackageUserState(), UserHandle.getCallingUserId());}

  在这里,会将 flags 添加PackageManager.MATCH_DIRECT_BOOT_AWARE和PackageManager.MATCH_DIRECT_BOOT_UNAWARE。collectCertificates 会为false,代表不会收集签名。
  这里的input 实际是ParseTypeImpl对象。它用来保存解析的结果。
  这里首先通过ParsingPackageUtils.parseDefault()得到APK安装包的解析信息,然后调用PackageInfoWithoutStateUtils.generate()得到PackageInfo对象。
  看一下PackageInfoWithoutStateUtils.generate()方法,了解一下PackageInfo对象是怎么生成的。这里UserHandle.getCallingUserId()是Binder调用方的user id,它是通过调用方的uid得到的,如果当前没处在Binder调用中,则它是当前应用的user id。
  PackageInfoWithoutStateUtils.generate()方法会在内部调用PackageInfoWithoutStateUtils的静态方法generateWithComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo),看一下它的实现:

    @Nullableprivate static PackageInfo generateWithComponents(ParsingPackageRead pkg, int[] gids,@PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,Set<String> grantedPermissions, PackageUserState state, int userId,@Nullable ApexInfo apexInfo) {ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);if (applicationInfo == null) {return null;}PackageInfo info = generateWithoutComponents(pkg, gids, flags, firstInstallTime,lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);if (info == null) {return null;}if ((flags & PackageManager.GET_ACTIVITIES) != 0) {final int N = pkg.getActivities().size();if (N > 0) {int num = 0;final ActivityInfo[] res = new ActivityInfo[N];for (int i = 0; i < N; i++) {final ParsedActivity a = pkg.getActivities().get(i);if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,flags)) {if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.getName())) {continue;}res[num++] = generateActivityInfo(pkg, a, flags, state,applicationInfo, userId);}}info.activities = ArrayUtils.trimToSize(res, num);}}if ((flags & PackageManager.GET_RECEIVERS) != 0) {final int size = pkg.getReceivers().size();if (size > 0) {int num = 0;final ActivityInfo[] res = new ActivityInfo[size];for (int i = 0; i < size; i++) {final ParsedActivity a = pkg.getReceivers().get(i);if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,flags)) {res[num++] = generateActivityInfo(pkg, a, flags, state,applicationInfo, userId);}}info.receivers = ArrayUtils.trimToSize(res, num);}}if ((flags & PackageManager.GET_SERVICES) != 0) {final int size = pkg.getServices().size();if (size > 0) {int num = 0;final ServiceInfo[] res = new ServiceInfo[size];for (int i = 0; i < size; i++) {final ParsedService s = pkg.getServices().get(i);if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), s,flags)) {res[num++] = generateServiceInfo(pkg, s, flags, state,applicationInfo, userId);}}info.services = ArrayUtils.trimToSize(res, num);}}if ((flags & PackageManager.GET_PROVIDERS) != 0) {final int size = pkg.getProviders().size();if (size > 0) {int num = 0;final ProviderInfo[] res = new ProviderInfo[size];for (int i = 0; i < size; i++) {final ParsedProvider pr = pkg.getProviders().get(i);if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), pr,flags)) {res[num++] = generateProviderInfo(pkg, pr, flags, state,applicationInfo, userId);}}info.providers = ArrayUtils.trimToSize(res, num);}}if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {int N = pkg.getInstrumentations().size();if (N > 0) {info.instrumentation = new InstrumentationInfo[N];for (int i = 0; i < N; i++) {info.instrumentation[i] = generateInstrumentationInfo(pkg.getInstrumentations().get(i), pkg, flags, userId,true /* assignUserFields */);}}}return info;}

  该方法首先通过generateApplicationInfo()方法得到ApplicationInfo对象,然后通过该对象作为参数调用generateWithoutComponents()方法得到PackageInfo对象info。接下来,再根据flags标识判断是否得到四大组件Activity、Receiver、Service、Provider的信息。再通过PackageManager.GET_INSTRUMENTATION标识,得到Instrumentation信息。

生成ApplicationInfo对象

  它是由PackageInfoWithoutStateUtils类的generateApplicationInfo(ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId)实现:

    @Nullablepublic static ApplicationInfo generateApplicationInfo(ParsingPackageRead pkg,@PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {if (pkg == null) {return null;}if (!checkUseInstalled(pkg, state, flags)) {return null;}return generateApplicationInfoUnchecked(pkg, flags, state, userId,true /* assignUserFields */);}

  pkg 不问为null,它是解析APK文件得到的所有相关信息,它实际是ParsingPackageImpl对象。详细见Android 解析APK包。
  接着调用checkUseInstalled(pkg, state, flags)检查包的状态,如果返回false,则返回结果null。PackageUserState类用来描述包的每用户状态信息。它最终是调用PackageUserState类对象的isAvailable(int flags)方法实现,代码PackageUserState类对象的isAvailable(int flags)代码如下:

    /*** Test if this package is installed.*/public boolean isAvailable(int flags) {// True if it is installed for this user and it is not hidden. If it is hidden,// still return true if the caller requested MATCH_UNINSTALLED_PACKAGESfinal boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;return matchAnyUser|| (this.installed&& (!this.hidden || matchUninstalled));}

  如果标签flags存在PackageManager.MATCH_ANY_USER标识,则代表满足任一用户。这种情况直接返回true。
  如果状态是installed并且不是隐藏,返回true。但是状态是installed并且是隐藏,这种情况下调用者如果带PackageManager.MATCH_UNINSTALLED_PACKAGES标识也返回true。
  在这里PackageUserState类对象是新建的,所以installed为true,hidden 为false。所以返回true。
  最后接着调用generateApplicationInfoUnchecked(pkg, flags, state, userId, true /* assignUserFields */),来生成ApplicationInfo对象,它的代码如下:

    @NonNullpublic static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg,@PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,boolean assignUserFields) {// Make shallow copy so we can store the metadata/libraries safelyApplicationInfo ai = pkg.toAppInfoWithoutState();if (assignUserFields) {assignUserFields(pkg, ai, userId);}if ((flags & PackageManager.GET_META_DATA) == 0) {ai.metaData = null;}if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {ai.sharedLibraryFiles = null;ai.sharedLibraryInfos = null;}// CompatibilityMode is global state.if (!android.content.pm.PackageParser.sCompatibilityModeEnabled) {ai.disableCompatibilityMode();}ai.flags |= flag(state.stopped, ApplicationInfo.FLAG_STOPPED)| flag(state.installed, ApplicationInfo.FLAG_INSTALLED)| flag(state.suspended, ApplicationInfo.FLAG_SUSPENDED);ai.privateFlags |= flag(state.instantApp, ApplicationInfo.PRIVATE_FLAG_INSTANT)| flag(state.virtualPreload, ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)| flag(state.hidden, ApplicationInfo.PRIVATE_FLAG_HIDDEN);if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {ai.enabled = true;} else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;} else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED|| state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {ai.enabled = false;}ai.enabledSetting = state.enabled;if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {ai.category = state.categoryHint;}if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);}ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);final OverlayPaths overlayPaths = state.getAllOverlayPaths();if (overlayPaths != null) {ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]);ai.overlayPaths = overlayPaths.getOverlayPaths().toArray(new String[0]);}return ai;}

  这里通过ParsingPackageRead类对象pkg的toAppInfoWithoutState()得到ApplicationInfo对象。这里pkg是ParsingPackageImpl对象。所以这里调用的ParsingPackageImpl类的toAppInfoWithoutState()方法:

    @Deprecated@Overridepublic ApplicationInfo toAppInfoWithoutState() {ApplicationInfo appInfo = toAppInfoWithoutStateWithoutFlags();appInfo.flags = PackageInfoWithoutStateUtils.appInfoFlags(this);appInfo.privateFlags = PackageInfoWithoutStateUtils.appInfoPrivateFlags(this);appInfo.privateFlagsExt = PackageInfoWithoutStateUtils.appInfoPrivateFlagsExt(this);return appInfo;}@Overridepublic ApplicationInfo toAppInfoWithoutStateWithoutFlags() {ApplicationInfo appInfo = new ApplicationInfo();// Lines that are commented below are state related and should not be assigned here.// They are left in as placeholders, since there is no good backwards compatible way to// separate these.appInfo.appComponentFactory = appComponentFactory;appInfo.backupAgentName = backupAgentName;appInfo.banner = banner;appInfo.category = category;appInfo.classLoaderName = classLoaderName;appInfo.className = className;appInfopatibleWidthLimitDp = compatibleWidthLimitDp;appInfopileSdkVersion = compileSdkVersion;appInfopileSdkVersionCodename = compileSdkVersionCodeName;
//        appInfo.credentialProtectedDataDirappInfo.crossProfile = isCrossProfile();
//        appInfo.dataDirappInfo.descriptionRes = descriptionRes;
//        appInfo.deviceProtectedDataDirappInfo.enabled = getBoolean(Booleans.ENABLED);
//        appInfo.enabledSettingappInfo.fullBackupContent = fullBackupContent;appInfo.dataExtractionRulesRes = dataExtractionRules;// TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
//        appInfo.mHiddenApiPolicy
//        appInfo.hiddenUntilInstalledappInfo.icon =(ParsingPackageUtils.sUseRoundIcon && roundIconRes != 0) ? roundIconRes : iconRes;appInfo.iconRes = iconRes;appInfo.roundIconRes = roundIconRes;appInfo.installLocation = installLocation;appInfo.labelRes = labelRes;appInfo.largestWidthLimitDp = largestWidthLimitDp;appInfo.logo = logo;appInfo.manageSpaceActivityName = manageSpaceActivityName;appInfo.maxAspectRatio = maxAspectRatio;appInfo.metaData = metaData;appInfo.minAspectRatio = minAspectRatio;appInfo.minSdkVersion = minSdkVersion;appInfo.name = className;
//        appInfo.nativeLibraryDir
//        appInfo.nativeLibraryRootDir
//        appInfo.nativeLibraryRootRequiresIsaappInfoworkSecurityConfigRes = networkSecurityConfigRes;appInfo.nonLocalizedLabel = nonLocalizedLabel;appInfo.packageName = packageName;appInfo.permission = permission;
//        appInfo.primaryCpuAbiappInfo.processName = getProcessName();appInfo.requiresSmallestWidthDp = requiresSmallestWidthDp;
//        appInfo.resourceDirs
//        appInfo.secondaryCpuAbi
//        appInfo.secondaryNativeLibraryDir
//        appInfo.seInfo
//        appInfo.seInfoUser
//        appInfo.sharedLibraryFiles
//        appInfo.sharedLibraryInfos
//        appInfo.showUserIconappInfo.splitClassLoaderNames = splitClassLoaderNames;appInfo.splitDependencies = splitDependencies;appInfo.splitNames = splitNames;appInfo.storageUuid = mStorageUuid;appInfo.targetSandboxVersion = targetSandboxVersion;appInfo.targetSdkVersion = targetSdkVersion;appInfo.taskAffinity = taskAffinity;appInfo.theme = theme;
//        appInfo.uidappInfo.uiOptions = uiOptions;appInfo.volumeUuid = volumeUuid;appInfo.zygotePreloadName = zygotePreloadName;appInfo.setGwpAsanMode(gwpAsanMode);appInfo.setMemtagMode(memtagMode);appInfo.setNativeHeapZeroInitialized(nativeHeapZeroInitialized);appInfo.setRequestRawExternalStorageAccess(requestRawExternalStorageAccess);appInfo.setBaseCodePath(mBaseApkPath);appInfo.setBaseResourcePath(mBaseApkPath);appInfo.setCodePath(mPath);appInfo.setResourcePath(mPath);appInfo.setSplitCodePaths(splitCodePaths);appInfo.setSplitResourcePaths(splitCodePaths);appInfo.setVersionCode(mLongVersionCode);return appInfo;}

  从这里可以看到,主要是将ParsingPackageImpl对象的成员变量值赋给ApplicationInfo 类对象。
  再回到PackageInfoWithoutStateUtils类的generateApplicationInfoUnchecked(pkg, flags, state, userId, true /* assignUserFields */)方法里,接着assignUserFields如果为true,会调用assignUserFields(pkg, ai, userId),它主要是设置ApplicationInfo类对象的credentialProtectedDataDir、deviceProtectedDataDir、dataDir。
  接着会根据标识,判断是否设置ApplicationInfo类对象的metaData、sharedLibraryFiles、sharedLibraryInfos。
  下面主要是根据PackageUserState类对象state的值来设置一些对应的值。
  通过以上,我们明白了ApplicationInfo类对象的生成。

生成PackageInfo对象

  PackageInfo对象的生成主要是由PackageInfoWithoutStateUtils的generateWithoutComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)来生成,看一下它的代码:

    @Nullablepublic static PackageInfo generateWithoutComponents(ParsingPackageRead pkg, int[] gids,@PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,Set<String> grantedPermissions, PackageUserState state, int userId,@Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {if (!checkUseInstalled(pkg, state, flags)) {return null;}return generateWithoutComponentsUnchecked(pkg, gids, flags, firstInstallTime,lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);}

  checkUseInstalled(pkg, state, flags)前面说过了,这里略了。接着看generateWithoutComponentsUnchecked()方法:

    @NonNullpublic static PackageInfo generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids,@PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,Set<String> grantedPermissions, PackageUserState state, int userId,@Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {PackageInfo pi = new PackageInfo();pi.packageName = pkg.getPackageName();pi.splitNames = pkg.getSplitNames();pi.versionCode = pkg.getVersionCode();pi.versionCodeMajor = pkg.getVersionCodeMajor();pi.baseRevisionCode = pkg.getBaseRevisionCode();pi.splitRevisionCodes = pkg.getSplitRevisionCodes();pi.versionName = pkg.getVersionName();pi.sharedUserId = pkg.getSharedUserId();pi.sharedUserLabel = pkg.getSharedUserLabel();pi.applicationInfo = applicationInfo;pi.installLocation = pkg.getInstallLocation();if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0|| (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {pi.requiredForAllUsers = pkg.isRequiredForAllUsers();}pi.restrictedAccountType = pkg.getRestrictedAccountType();pi.requiredAccountType = pkg.getRequiredAccountType();pi.overlayTarget = pkg.getOverlayTarget();pi.targetOverlayableName = pkg.getOverlayTargetName();pi.overlayCategory = pkg.getOverlayCategory();pi.overlayPriority = pkg.getOverlayPriority();pi.mOverlayIsStatic = pkg.isOverlayIsStatic();pipileSdkVersion = pkg.getCompileSdkVersion();pipileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();pi.firstInstallTime = firstInstallTime;pi.lastUpdateTime = lastUpdateTime;if ((flags & PackageManager.GET_GIDS) != 0) {pi.gids = gids;}if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {int size = pkg.getConfigPreferences().size();if (size > 0) {pi.configPreferences = new ConfigurationInfo[size];pkg.getConfigPreferences().toArray(pi.configPreferences);}size = pkg.getReqFeatures().size();if (size > 0) {pi.reqFeatures = new FeatureInfo[size];pkg.getReqFeatures().toArray(pi.reqFeatures);}size = pkg.getFeatureGroups().size();if (size > 0) {pi.featureGroups = new FeatureGroupInfo[size];pkg.getFeatureGroups().toArray(pi.featureGroups);}}if ((flags & PackageManager.GET_PERMISSIONS) != 0) {int size = ArrayUtils.size(pkg.getPermissions());if (size > 0) {pi.permissions = new PermissionInfo[size];for (int i = 0; i < size; i++) {pi.permissions[i] = generatePermissionInfo(pkg.getPermissions().get(i),flags);}}final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();size = usesPermissions.size();if (size > 0) {pi.requestedPermissions = new String[size];pi.requestedPermissionsFlags = new int[size];for (int i = 0; i < size; i++) {final ParsedUsesPermission usesPermission = usesPermissions.get(i);pi.requestedPermissions[i] = usesPermission.name;// The notion of required permissions is deprecated but for compatibility.pi.requestedPermissionsFlags[i] |=PackageInfo.REQUESTED_PERMISSION_REQUIRED;if (grantedPermissions != null&& grantedPermissions.contains(usesPermission.name)) {pi.requestedPermissionsFlags[i] |=PackageInfo.REQUESTED_PERMISSION_GRANTED;}if ((usesPermission.usesPermissionFlags& ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) {pi.requestedPermissionsFlags[i] |=PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;}}}}if ((flags & PackageManager.GET_ATTRIBUTIONS) != 0) {int size = ArrayUtils.size(pkg.getAttributions());if (size > 0) {pi.attributions = new Attribution[size];for (int i = 0; i < size; i++) {pi.attributions[i] = generateAttribution(pkg.getAttributions().get(i));}}if (pkg.areAttributionsUserVisible()) {pi.applicationInfo.privateFlagsExt|= ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;} else {pi.applicationInfo.privateFlagsExt&= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;}} else {pi.applicationInfo.privateFlagsExt&= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;}if (apexInfo != null) {File apexFile = new File(apexInfo.modulePath);pi.applicationInfo.sourceDir = apexFile.getPath();pi.applicationInfo.publicSourceDir = apexFile.getPath();if (apexInfo.isFactory) {pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;} else {pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;pi.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;}if (apexInfo.isActive) {pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;} else {pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;}pi.isApex = true;}PackageParser.SigningDetails signingDetails = pkg.getSigningDetails();// deprecated method of getting signing certificatesif ((flags & PackageManager.GET_SIGNATURES) != 0) {if (signingDetails.hasPastSigningCertificates()) {// Package has included signing certificate rotation information.  Return the oldest// cert so that programmatic checks keep working even if unaware of key rotation.pi.signatures = new Signature[1];pi.signatures[0] = signingDetails.pastSigningCertificates[0];} else if (signingDetails.hasSignatures()) {// otherwise keep old behaviorint numberOfSigs = signingDetails.signatures.length;pi.signatures = new Signature[numberOfSigs];System.arraycopy(signingDetails.signatures, 0, pi.signatures, 0,numberOfSigs);}}// replacement for GET_SIGNATURESif ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {if (signingDetails != PackageParser.SigningDetails.UNKNOWN) {// only return a valid SigningInfo if there is signing information to reportpi.signingInfo = new SigningInfo(signingDetails);} else {pi.signingInfo = null;}}return pi;}

  这些代码看着很长,其实主要是新生成PackageInfo对象,然后给它的成员变量赋值。
  这里我们看到,前面生成的ApplicationInfo类对象是放到PackageInfo类对象的applicationInfo成员变量中。并且PackageInfo类对象大部分成员变量的值都来自ParsingPackageImpl类对象的成员变量的值。
  而ApplicationInfo类对象的值,大部分也都来自ParsingPackageImpl类对象。而ParsingPackageImpl类对象的值,也是来自安装包里的“AndroidManifest.xml”文件,这样就将ParsingPackageImpl类对象的值都设置到PackageInfo类对象中。

总结

  APK安装包里的配置信息都在“AndroidManifest.xml”文件中,通过解析它之后,是放到了ParsingPackageImpl类对象中。ParsingPackageImpl类对象通过自己的toAppInfoWithoutState(),将自己的值生成到ApplicationInfo对象中,而PackageInfo类对象的applicationInfo正是ApplicationInfo对象,并且PackageInfo类对象的其他成员也来自ParsingPackageImpl类对象。这样PackageInfo类对象就包含了安装包的信息。

更多推荐

Android 得到安装包的信息

本文发布于:2023-12-03 13:30:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1655875.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:安装包   信息   Android

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!