android12-targetsdk31报错Failed to install-write all apks

一、错误描述

本人用的红米手机,android12的版本,原来的targetsdk为30,在android studio上直接run到手机上调试正常,但是将targetsdk调整为31后,一直install不上去,最后300秒超时,报错如下:

Installation did not succeed.
The application could not be installed.

List of apks:
[0] 'L:\xxx\app\build\outputs\apk\debug\app-debug.apk'
Installation failed due to: 'Failed to install-write all apks'

二、爬坑经历

在网上找了一圈,有一些解决方案,但是都不适用,如下

1. 打开usb调试、打开usb安装。(这些正常的开发都会打开的,而且30的版本都能安装成功,能没有打开吗)

2.手机内存空间满了,权限问题。(这些当然也不存在)

3.android版本问题。(30的能成功,这个自然也不存在)

三、问题分析

1.小米手机有个很坑的问题,开发的时候如果有版本系统适配错误,不会明确指出哪个第三方库、程序里面配置文件哪个地方错误,只会统一报一个错误(“Failed to install-write all apks”),所以,如果你用的是小米手机,就不要一直纠结这个错误找问题。

2.从"targesdk迁移31后报错"这个方向找问题,最终找到了一些实质可以解决的方案。

3.targetsdk从低版本迁移到31及以上后,程序改动比较大,并且第三方库也需要跟随改动。所以是件很麻烦的事情。

四、问题解决

以下是我的综合解决方案,不清楚到底是哪一条生效,哪一条没有生效,最终结果是综合生效,供大家借鉴,切勿生搬硬套,每个app每个环境都不一样。

1.开发者选项中usb调试、usb安装重开,miui优化开关关闭,重启手机

2.Android 12 自动适配 exported 深入解析避坑众所周知,从Android12开始,使用了TargetSDK31之后,四大组件如果使用了intent-filter,但是没显性质配置exportedApp将会无法安装,甚至编译不通过。比如启动的Activity就需要设置exported为true,至于其他组件是否设置为true则看它是否需要被其它应用调用。然而这个事情的状态是这样的:如果出现问题的AndroidManifest文件是你本地的,那手动修改即可;但如果出现问题的是第三方远程依赖,那就需要升级第三方依赖库为最新版本,要么用网上的一个脚本文件,运行的时候自动将其在清单文件中加入exported。

参考链接1:Android 12 自动适配 exported 深入解析避坑 - 思创斯聊编程

参考链接2:Android 12 快速适配要点 - 掘金

com.android.tools.build:gradle:4.0.0 以及其下版本用如下脚本

/**
 * 修改 Android 12 因为 exported 的构建问题
 */
android.applicationVariants.all { variant ->
    variant.outputs.all { output ->
        output.processResources.doFirst { pm ->
            String manifestPath = output.processResources.manifestFile
            def manifestFile = new File(manifestPath)
            def xml = new XmlParser(false, true).parse(manifestFile)
            def exportedTag = "android:exported"
            ///指定 space
            def androidSpace = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android')

            def nodes = xml.application[0].'*'.findAll {
                //挑选要修改的节点,没有指定的 exported 的才需要增加
                (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'service') && it.attribute(androidSpace.exported) == null

            }
            ///添加 exported,默认 false
            nodes.each {
                def isMain = false
                it.each {
                    if (it.name() == "intent-filter") {
                        it.each {
                            if (it.name() == "action") {
                                if (it.attributes().get(androidSpace.name) == "android.intent.action.MAIN") {
                                    isMain = true
                                    println("......................MAIN FOUND......................")
                                }
                            }
                        }
                    }
                }
                it.attributes().put(exportedTag, "${isMain}")
            }

            PrintWriter pw = new PrintWriter(manifestFile)
            pw.write(groovy.xml.XmlUtil.serialize(xml))
            pw.close()
        }
    }

}

如果你的项目不复杂,或者用到的第三方的库不多,先查看manifest.xml文件底部的MergedManifest 这个tab里面的报错信息,如果有报错,那么可以手动的去修改manifest文件,将exported属性添加上去。

参考链接:Android12 依旧提示使用 intent-filter 需设置 android:exported 属性_Earliest-Mlr的博客-CSDN博客

3.修改targetsdk和buildtool版本号匹配,我的是(targetSdkVersion=31,compileSdkVersion=31,buildToolsVersion=31.0.0)

修改了版本号后,出现了报错,如下:

意思是31的构建工具已经损坏,重新卸载后安装还是报错。所以不是下载过程的问题。

修改两个文件名称。

(1)进入到自己SDK的目录;

(2)进入到build-tools\31.0.0,修改 d8.bat 文件,将其名字改为dx;

(3)进入到build-tools\31.0.0\lib目录,修改d8.jar文件,将其名字改为dx.jar

参考链接:关于安卓项目targetSdkVersion升级到31后报错问题_水很清的博客-CSDN博客

4.在此过程中,修改了build.gradle后,clean project、重启android studio、重启手机都需要,按需吧。

五、最后说一句

项目比较复杂,用到的第三方库又多,又用的是比较坑的小米手机作为调试机,导致搞了3天才搞好。心态有点崩,android studio说真心话,各种版本、组件、第三方库、gradle版本、androidx、merge manifest等等适配真心很稀烂,有一说一,欢迎拍砖。

先写到这,一是对问题的总结,一是对猿友有个借鉴参考。

猜你喜欢

转载自blog.csdn.net/mawei7510/article/details/127860054
ALL
今日推荐