美文网首页
Android 15.0 ROM定制:无源码App图标替换指南

Android 15.0 ROM定制:无源码App图标替换指南

作者: 龙之叶 | 来源:发表于2025-10-18 13:50 被阅读0次

1. 概述

在Android 15.0系统产品ROM定制化开发过程中,部分产品需求要求替换Launcher3中显示的app图标。对于无源码的app,这一操作需通过修改PMS(PackageManagerService)在解析app时的行为来实现。具体来说,需在解析过程中替换app的icon资源。

2. 无源码app修改icon图标的相关核心类

核心类位于:

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

3. 无源码app修改icon图标的核心功能实现与分析

3.1 PMS(PackageManagerService)概述

PMS是Android提供的包管理系统服务,负责管理所有包的信息,包括应用的安装、卸载、更新以及解析AndroidManifest.xml文件。PMS通过解析每个安装应用的AndroidManifest.xml文件,保存其中的数据,并为AMS(ActivityManagerService)提供所需数据。

3.2 解析app的方法分析

在安装过程中,PMS首先遍历/data/app/system/app文件夹,找到apk文件,然后通过submit()方法进行apk的解析。解析时,将apk文件路径传入PackageParser对象的parsePackage()方法进行解析。不同系统源码版本的解析方式可能有所不同。

3.2.1 parsePackage()方法

@UnsupportedAppUsage
public Package parsePackage(File packageFile, int flags) throws PackageParserException {
    if (packageFile.isDirectory()) {
        return parseClusterPackage(packageFile, flags);
    } else {
        return parseMonolithicPackage(packageFile, flags);
    }
}

在解析app时,PMS会优先调用parsePackage(File packageFile, int flags, boolean useCaches)方法(尽管示例中未直接展示,但根据描述可推断),进而调用parseMonolithicPackage(File apkFile, int flags)方法进行app资源的解析。

3.2.2 parseMonolithicPackage()方法

public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
    final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
    if (mOnlyCoreApps) {
        if (!lite.coreApp) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    "Not a coreApp: " + apkFile);
        }
    }
    final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
    try {
        final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
        pkg.setCodePath(apkFile.getCanonicalPath());
        pkg.setUse32bitAbi(lite.use32bitAbi);
        return pkg;
    } catch (IOException e) {
        throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                "Failed to get path: " + apkFile, e);
    } finally {
        IoUtils.closeQuietly(assetLoader);
    }
}

parseMonolithicPackage()方法中,会调用parseBaseApk()方法进一步解析app。

3.2.3 parseBaseApk()方法

@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
        String[] outError) throws XmlPullParserException, IOException {
    // 解析app的基础信息,包括版本号、编译SDK版本等
    final String pkgName;
    final Package pkg = new Package(pkgName);
    // ... 其他解析代码 ...
    return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
}

parseBaseApk()方法最终会调用parseBaseApkCommon()方法继续解析app的xml内容。当解析到TAG_APPLICATION标签时,会调用parseBaseApplication()方法解析application的相关内容。

3.2.4 parseBaseApplication()方法

private boolean parseBaseApplication(Package owner, Resources res,
        XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException {
    final ApplicationInfo ai = owner.applicationInfo;
    final String pkgName = owner.applicationInfo.packageName;
    TypedArray sa = res.obtainAttributes(parser,
            com.android.internal.R.styleable.AndroidManifestApplication);
    
    // 解析application的icon资源
    ai.iconRes = sa.getResourceId(
            com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
    ai.roundIconRes = sa.getResourceId(
            com.android.internal.R.styleable.AndroidManifestApplication_roundIcon, 0);
    
    // 示例:修改特定app的icon(以com.sprd.sprdnote为例)
    if (!TextUtils.isEmpty(pkgName) && pkgName.equals("com.sprd.sprdnote")) {
        ai.iconRes = com.android.internal.R.drawable.ic_battery;
    }
    
    // ... 其他解析代码 ...
}

parseBaseApplication()方法中,首先获取ApplicationInfopkgName,然后解析application的属性。其中,ai.iconRes即为app的图标资源ID。因此,要修改app的图标,只需修改此属性即可。

相关文章

网友评论

      本文标题:Android 15.0 ROM定制:无源码App图标替换指南

      本文链接:https://www.haomeiwen.com/subject/qncptstx.html