Your Site Title

错误问题

cvc-complex-type.2.4.a: Invalid content was found starting with element ‘base-extension’. One of ‘{layoutlib}’ is expected

Android项目中有配置gradle, gradle jdk, gradle pluge, ndk等版本, 需要与Android SDK对应

gradle-wrapper.properties 配置gradle版本
gradle jdk: Android Studio-> File -> Project Structure -> SDK Location -> Gradle Setting

build.gradle(Module)
    android {
        compileSdkVersion configs.compileSdkVersion 编译SDK版本
        buildToolsVersion configs.buildToolsVersion 编译工具版本
        ndkVersion COMPILE_NDK_VERSION              NDK版本

    
classpath 'com.android.tools.build:gradle:3.2.1'    gradle pluger 版本 //        classpath 'me.tatarka:gradle-retrolambda:3.2.5'
classpath 'io.fabric.tools:gradle:1.25.4'
classpath 'com.google.gms:google-services:4.0.1'


Android SDK需要下载 编译Android SDK版本, 编译工具版本, NDK版本

Android Studio -> File -> Invalidate Caches

Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/vmdl1121716107.tmp/base.apk (at Binary XML file line #164): com.taobao.accs.EventReceiver: Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are presen

Android 31及以后, 4大组件如果有<intent-filter> 那么必须显示设置android:exported属性, 不然会报错

「gradle:4.0.0 & gradle-6.1.1-all.zip」 /**

com.android.tools.build:gradle:4.0.0 以上版本 「gradle:4.1.0 & gradle-6.5.1-all.zip」 /**

android.applicationVariants.all { variant -> variant.outputs.each { output -> def processManifest = output.getProcessManifestProvider().get() processManifest.doLast { task -> def outputDir = task.multiApkManifestOutputDirectory File outputDirectory if (outputDir instanceof File) { outputDirectory = outputDir } else { outputDirectory = outputDir.get().asFile } File manifestOutFile = file(“$outputDirectory/AndroidManifest.xml”) println(“———– ${manifestOutFile} ———– “)

        if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
            def manifestFile = manifestOutFile
            ///这里第二个参数是 false ,所以 namespace 是展开的,所以下面不能用 androidSpace,而是用 nameTag
            def xml = new XmlParser(false, false).parse(manifestFile)
            def exportedTag = "android:exported"
            def nameTag = "android:name"
            ///指定 space
            //def androidSpace = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android')
 
            def nodes = xml.application[0].'*'.findAll {
                //挑选要修改的节点,没有指定的 exported 的才需要增加
                //如果 exportedTag 拿不到可以尝试 it.attribute(androidSpace.exported)
                (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'service') && it.attribute(exportedTag) == null
 
            }
            ///添加 exported,默认 false
            nodes.each {
                def isMain = false
                it.each {
                    if (it.name() == "intent-filter") {
                        it.each {
                            if (it.name() == "action") {
                                //如果 nameTag 拿不到可以尝试 it.attribute(androidSpace.name)
                                if (it.attributes().get(nameTag) == "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()
 
        }
 
    }
} }

apply { 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-exported-plugin插件

Reference