android 5.0 apk 安装失败提示INSTALL_FAILED_INVALID_URI

本文介绍在Android5.0设备上从U盘安装APK时遇到的问题及解决方法。当使用pm命令安装时,若不指定完整路径会因解析失败导致安装错误。文章提供了解决方案,并对比了不同Android版本间的行为差异。

在android 5.0 项目上开发的时候,进入U盘目录,通过pm 命令安装apk,发现安装失败,提示apk路径不对。

安装log信息如下:

cd /mnt/usb/2D80-E3ED/APK_backup

shell@yjw:/mnt/usb/2D80-E3ED/APK_backup # pm install AndyKeyTest.apk      
        pkg: AndyKeyTest.apk
Failure [INSTALL_FAILED_INVALID_URI]

logcat信息:

01-01 08:20:49.955 D/AndroidRuntime( 2952): Calling main entry com.android.commands.pm.Pm
01-01 08:20:49.968 W/asset   ( 2734): Asset path /AndyKeyTest.apk is neither a directory nor file (type=1).
--------- beginning of system
01-01 08:20:49.968 W/DefContainer( 2734): Failed to parse package at /AndyKeyTest.apk: android.content.pm.PackageParser$PackageParserException: Failed to parse /AndyKeyTest.apk


通过log信息及测试发现,原来在android5.0中不能直接在u盘目录下执行pm install 安装apk ,必须到要在pm 命令带上apk所在路劲。更早的android版本没有这个要求

改为在根目录下,执行下面命令,则安装apk成功

shell@yjw:/ # pm install mnt/usb/2D80-E3ED/APK_backup/AndyKeyTest.apk
       pkg: mnt/usb/2D80-E3ED/APK_backup/AndyKeyTest.apk
Success


针对上面的问题,查看了一下源码,发现android 5.0 的parsePackage功能在细节上有一些更改,所以出现上面的情况。

相关代码如下:

PackageParser.java@

    /**
     * Parse only lightweight details about the package at the given location.
     * Automatically detects if the package is a monolithic style (single APK
     * file) or cluster style (directory of APKs).
     * <p>
     * This performs sanity checking on cluster style packages, such as
     * requiring identical package name and version codes, a single base APK,
     * and unique split names.
     *
     * @see PackageParser#parsePackage(File, int)
     */
    public static PackageLite parsePackageLite(File packageFile, int flags)
            throws PackageParserException {
        if (packageFile.isDirectory()) {
            return parseClusterPackageLite(packageFile, flags);
        } else {
            return parseMonolithicPackageLite(packageFile, flags);
        }
    }


DefaultContainerService.java@

        /**
         * Parse given package and return minimal details.
         *
         * @param packagePath absolute path to the package to be copied. Can be
         *            a single monolithic APK file or a cluster directory
         *            containing one or more APKs.
         */
        @Override
        public PackageInfoLite getMinimalPackageInfo(String packagePath, int flags,
                String abiOverride) {
            final Context context = DefaultContainerService.this;
            final boolean isForwardLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;

            PackageInfoLite ret = new PackageInfoLite();
            if (packagePath == null) {
                Slog.i(TAG, "Invalid package file " + packagePath);
                ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
                return ret;
            }

            final File packageFile = new File(packagePath);
            final PackageParser.PackageLite pkg;
            final long sizeBytes;
            try {
                pkg = PackageParser.parsePackageLite(packageFile, 0);
                sizeBytes = PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride);
            } catch (PackageParserException | IOException e) {
                Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e);

                if (!packageFile.exists()) {
                    ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI;
                } else {
                    ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
                }

                return ret;
            }

            ret.packageName = pkg.packageName;
            ret.versionCode = pkg.versionCode;
            ret.installLocation = pkg.installLocation;
            ret.verifiers = pkg.verifiers;
            ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
                    pkg.packageName, pkg.installLocation, sizeBytes, flags);
            ret.multiArch = pkg.multiArch;

            return ret;
        }


<think>我们正在解决安装高德地图车机版APK时出现的INSTALL_FAILED_INVALID_APK错误。 根据引用内容,这个错误通常与APK签名有关。引用中提供了两种解决思路: 1. 修改系统属性:将/system/build.prop中的ro.install.3rd_cert=true改为ro.install.3rd_cert=false,然后重启设备(需要root权限)。 2. 检查APK签名:可能APK没有签名或者签名损坏,需要重新签名。 但是,用户是在安装高德地图车机版,我们假设用户下载的是官方APK,所以签名应该是正确的。因此,我们优先考虑修改系统属性(因为引用[1]提到这个方法解决了同样的问题)。 然而,修改系统属性需要root权限,并且需要修改系统文件。如果用户的车机已经root,那么可以尝试。如果没有root,则需要其他方法。 另外,引用[2]和[3]提到错误可能是由于APK没有签名(NO_CERTIFICATES)导致。因此,我们还需要考虑对APK进行签名。 因此,我们提供两种解决方案: 方案一:修改系统属性(需要root权限) 方案二:重新签名APK(如果用户有签名工具,或者使用签名工具对APK重新签名) 由于用户是在车机上安装,并且我们之前已经通过ADB连接,所以我们可以尝试通过ADB来执行这些操作。 步骤: 方案一:修改系统属性(需要root权限) 1. 通过ADB连接车机(如之前步骤) 2. 挂载系统分区为可写 3. 备份build.prop文件 4. 修改build.prop文件中的属性 5. 重启设备 方案二:重新签名APK 1. 在电脑上使用keytool生成密钥(如果已有密钥可跳过) 2. 使用jarsigner或apksigner对APK重新签名 3. 安装重新签名后的APK 由于用户可能没有签名工具,我们将提供详细的签名步骤。 另外,我们也可以尝试使用安装选项`--disable-verity`和`--disable-verification`来绕过验证(但需要Android 7.0以上),但这不是标准方法,且可能不适用。 根据引用,我们优先推荐方案一(如果车机已root),否则尝试方案二。 下面我们详细写出两个方案的步骤。</think>### 解决高德地图车机版安装错误 INSTALL_FAILED_INVALID_APK 的完整方案 #### 错误原因分析 当安装APK时出现`INSTALL_FAILED_INVALID_APK`错误,通常由以下原因导致: 1. **APK签名问题**(最常见原因)[^1] 2. 系统签名验证机制拦截(`ro.install.3rd_cert`参数限制)[^1] 3. APK文件损坏或下载不完整[^2] 4. 包名冲突或系统缓存异常[^3] --- ### 解决方案分步指南 #### 方案一:关闭系统签名验证(推荐) ```bash # 1. 连接车机 adb connect <车机IP>:5555 # 2. 获取root权限 adb root adb remount # 3. 备份原始配置文件 adb pull /system/build.prop ./build.prop.bak # 4. 修改系统配置(关键步骤) adb shell "echo 'ro.install.3rd_cert=false' >> /system/build.prop" # 5. 重启设备生效 adb reboot ``` > ✅ 修改后重新执行安装命令即可[^1] #### 方案二:APK重新签名 ```bash # 1. 生成签名密钥 keytool -genkey -v -keystore my-release-key.jks -alias alias_name -keyalg RSA -keysize 2048 -validity 10000 # 2.APK签名 jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 -keystore my-release-key.jks amap_auto.apk alias_name # 3. 验证签名 jarsigner -verify -verbose -certs amap_auto.apk # 4. 安装签名后的APK adb install amap_auto.apk ``` #### 方案三:强制安装模式 ```bash # 绕过签名验证 adb install --bypass-low-target-sdk-block --force-queryable amap_auto.apk # 或使用系统权限安装 adb shell pm install -t -i "com.android.shell" amap_auto.apk ``` #### 方案四:清理系统冲突 ```bash # 1. 清除包管理缓存 adb shell pm clear com.android.packageinstaller # 2. 删除冲突包 adb shell pm uninstall --user 0 com.autonavi.amapauto # 3. 清除ART缓存 adb shell cmd package compile --reset -f com.autonavi.amapauto ``` --- ### 验证安装成功 ```bash # 检查安装状态 adb shell pm list packages | grep amapauto # 查看版本信息 adb shell dumpsys package com.autonavi.amapauto | grep versionName ``` > ⚠️ **注意事项** > 1. 修改`build.prop`需root权限,操作前务必备份[^1] > 2. 签名需使用Java 8+环境,建议用Android Studio的`apksigner`工具 > 3. 下载APK后验证MD5:`certutil -hashfile amap_auto.apk MD5` > 4. 车机系统需开启`未知来源安装`选项 --- ### 常见问题处理 | 问题现象 | 解决方案 | |--------------------------|-----------------------------| | `Read-only file system` | 执行`adb root && adb remount` | | `Signature verification failed` | 使用方案二重新签名APK | | `INSTALL_FAILED_UPDATE_INCOMPATIBLE` | 先执行`adb uninstall com.autonavi.amapauto` | | 修改build.prop后无法启动 | 通过Recovery模式恢复备份文件 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值