Unity gradle は動的に android:launchMode の問題レコードを変更します

団結

ユニティ版 Gradle バージョン Android Gradle プラグインのバージョン
2023.1 7.3.3 7.2.1
2022.2 7.2 7.1.2
2022.1
2021.3
2021.2
2021.1 2021.1.16f1 以降
2020.3 2020.3.15f1 以降
6.1.1 4.0.1
2021.1 から 2021.1.15f1 まで
2020.1、2020.2、2020.3 から 2020.3.14f1 まで
5.6.4 4.0.1
2019.4 5.1.1 3.4.0

アンドロイド:

プラグインのバージョン 必要な Gradle バージョン
1.0.0 - 1.1.3 2.2.1 - 2.3
1.2.0 - 1.3.1 2.2.1 - 2.9
1.5.0 2.2.1 - 2.13
2.0.0 - 2.1.2 2.10 - 2.13
2.1.3 - 2.2.3 2.14.1+
2.3.0+ 3.3+
3.0.0+ 4.1+
3.1.0+ 4.4+
3.2.0 - 3.2.1 4.6+
3.3.0 - 3.3.3 4.10.1+
3.4.0 - 3.4.3 5.1.1+
3.5.0 - 3.5.4 5.4.1+
3.6.0 - 3.6.4 5.6.4+
4.0.0+ 6.1.1+
4.1.0+ 6.5+
4.2.0+ 6.7.1+
7.0 7.0+
7.1 / 7.1.2 7.2+
7.2 7.3+
7.3 / 7.3.0 7.4+

オンラインで見つかったバージョン:

android.applicationVariants.all { variant ->
    variant.outputs.all { output ->
        def processResources = output.hasProperty("processResourcesProvider") ?
                output.processResourcesProvider.get() : output.processResources
        processResources.doFirst { pm ->
            String manifestPath = processResources.manifestFile
            println "=====change manifestPath=====$manifestPath"
            def manifestContent = file(manifestPath).getText()

            def android = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android')
            def xml = new XmlParser().parseText(manifestContent)
            def mainActivity = xml.application[0].activity.findAll() { ac ->
                def action = ac.depthFirst().findAll() { node ->
                    return node.attribute(android.name) == 'android.intent.action.MAIN'
                }
                return action.size() > 0;
            }
            println "=====found main activity=====${mainActivity.size()} $mainActivity"
            mainActivity[0].attributes().put(android.launchMode, 'singleTop')

            def serialize = groovy.xml.XmlUtil.serialize(xml)
            file(manifestPath).write(serialize)
        }
    }
}

android:LaunchModeから apk と AAB のバージョンをサポートするなぜ Unity はそれを singleTask として持っているのですか? - Unity フォーラム

// Override LibraryManifest.xml values and switch launchMode to standard
android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def processManifest = output.getProcessManifestProvider().get()
        processManifest.doLast { task ->
            def outputDir = task.getManifestOutputDirectory()
            File outputDirectory
            if (outputDir instanceof File) {
                outputDirectory = outputDir
            } else {
                outputDirectory = outputDir.get().asFile
            }
   
            File manifestOutFile = file("$outputDirectory/AndroidManifest.xml")
 
            if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
                def newManifest = manifestOutFile.getText().replace("android:launchMode=\"singleTask\"", "android:launchMode=\"standard\"")
                manifestOutFile.write(newManifest, 'UTF-8')
            }
   
            // Make sure to modify bundle_manifest as well
            outputDir = task.getBundleManifestOutputDirectory();
   
            if (outputDir instanceof File) {
                outputDirectory = outputDir
            } else {
                outputDirectory = outputDir.get().asFile
            }
                   
            manifestOutFile = file("$outputDirectory/AndroidManifest.xml")
 
            if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
                def bundleManifest = manifestOutFile.getText().replace("android:launchMode=\"singleTask\"", "android:launchMode=\"standard\"")
                manifestOutFile.write(bundleManifest, 'UTF-8')
            }
        }
    }
}

私の最適化されたバージョンは次のとおりです (unity2022.2 より前のバージョンのみをサポートしています)。

// Override LibraryManifest.xml values and switch launchMode to singleTop
android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def processManifest = output.getProcessManifestProvider().get()
        processManifest.doLast { task ->
            def outputDir = task.getManifestOutputDirectory()
            println "=====change manifestPath==A===$outputDir"
            File outputDirectory
            if (outputDir instanceof File) {
                outputDirectory = outputDir
            } else {
                outputDirectory = outputDir.get().asFile
            }
   
            File manifestOutFile = file("$outputDirectory/AndroidManifest.xml")
            println "=====change manifestPath==B===$outputDirectory"
            if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
       /*          def newManifest = manifestOutFile.getText().replace("android:launchMode=\"singleTask\"", "android:launchMode=\"standard\"")
                manifestOutFile.write(newManifest, 'UTF-8') */
                 def manifestContent = file(manifestOutFile).getText()
                def android = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android')
                def xml = new XmlParser().parseText(manifestContent)
                def mainActivity = xml.application[0].activity.findAll() { ac ->
                    def action = ac.depthFirst().findAll() { node ->
                        return node.attribute(android.name) == 'android.intent.action.MAIN'
                    }
                    return action.size() > 0;
                }
                println "=====found main activity=====${mainActivity.size()} $mainActivity"
                mainActivity[0].attributes().put(android.launchMode, 'singleTop')
    
                def serialize = groovy.xml.XmlUtil.serialize(xml)
                file(manifestOutFile).write(serialize)
            }
   
            // Make sure to modify bundle_manifest as well
            outputDir = task.getBundleManifestOutputDirectory();
   
            if (outputDir instanceof File) {
                outputDirectory = outputDir
            } else {
                outputDirectory = outputDir.get().asFile
            }
          println "=====change manifestPath==C===$outputDirectory"  
            manifestOutFile = file("$outputDirectory/AndroidManifest.xml")
             
            if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
      /*           def bundleManifest = manifestOutFile.getText().replace("android:launchMode=\"singleTask\"", "android:launchMode=\"standard\"")
                manifestOutFile.write(bundleManifest, 'UTF-8') */
                 def manifestContent = file(manifestOutFile).getText()
                def android = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android')
                def xml = new XmlParser().parseText(manifestContent)
                def mainActivity = xml.application[0].activity.findAll() { ac ->
                    def action = ac.depthFirst().findAll() { node ->
                        return node.attribute(android.name) == 'android.intent.action.MAIN'
                    }
                    return action.size() > 0;
                }
                println "=====found main activity=====${mainActivity.size()} $mainActivity"
                mainActivity[0].attributes().put(android.launchMode, 'singleTop')
    
                def serialize = groovy.xml.XmlUtil.serialize(xml)
                file(manifestOutFile).write(serialize)
            }
        }
    }
}

ファローアップ:

参考リンク:

Android 12 は、エクスポートされたピット回避の詳細な分析に自動的に適応します - プログラマーが求めたもの

Android 12 は、エクスポートされた詳細な分析に自動的に適応し、落とし穴を回避します-コラム-SoundNet RTE Developer Community

上記のスクリプトは unity 2022.2 では有効ではなくなりました. 上記のリンクを参照して、さまざまなスクリプトの組み合わせを記述してください. android studio (plugs 7.4.1) と unity2022 で 3 つのスクリプトを試した後、最終的に最も効果的なスクリプトが得られました.

スクリプト 1 (unity は有効、android studio は無効)

android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def vn
            if (variant.getFlavorName() != null && variant.getFlavorName() != "") {
                vn = variant.name;
            } else {
                if (variant.getBuildType().name == "release") {
                    vn = "Release"
                } else {
                    vn = "Debug"
                }
            }
            def taskName = "process${vn}MainManifest";
            try {
                println("=============== taskName ${taskName} ===============")
                project.getTasks().getByName(taskName)
            } catch (Exception e) {
                return
            }
            ///你的自定义名字
            project.getTasks().getByName(taskName).doFirst {
                it.getManifests().getFiles().each {
                    if (it.exists() && it.canRead() && it.canWrite()) {
                        def manifestFile = it
                        ///这里第二个参数是 false ,所以 namespace 是展开的,所以下面不能用 androidSpace,而是用 nameTag
                        def xml = new XmlParser(false, false).parse(manifestFile)
                        if (xml.application != null && xml.application.size() > 0) {
                            def mainActivity = xml.application[0].activity.findAll { ac ->
                                def action = ac.depthFirst().findAll() { node ->
                                    if(node != null){
                                        return node.attributes().get("android:name") == 'android.intent.action.MAIN'
                                    }
                                }

                                return action.size() > 0;
                            }
                            println "=====found main1 activity=====${mainActivity.size()} $mainActivity"
                            if(mainActivity[0]!=null){
                                mainActivity[0].attributes().put("android:launchMode", 'singleTop')
                            }
                            //mainActivity[0].attributes().put(android.launchMode, 'singleTop')
                            println "=====found main2 activity=====${mainActivity.size()} $mainActivity"
                            def serialize = groovy.xml.XmlUtil.serialize(xml)
                            file(it).write(serialize)
                        }
                    }
                }
            }
        }
    }

スクリプト 2 (android studio と UNITY の両方が無効)

android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.processResources.doLast {
                String manifestPath = output.processResources.manifestFile
                println "=====found manifestPath activity=====${manifestPath}"
                def manifestOutFile = new File(manifestPath)
                if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
                    ///这里第二个参数是 false ,所以 namespace 是展开的,所以下面不能用 androidSpace,而是用 nameTag
                    def xml = new XmlParser(false, false).parse(manifestOutFile)
                    def nameTag = "android:name"
                    println "=====found xml activity=====${xml}"
                    if (xml.application != null && xml.application.size() > 0) {
                        def mainActivity = xml.application[0].activity.findAll { ac ->
                            def action = ac.depthFirst().findAll() { node ->
                                if (node != null) {
                                    return node.attributes().get(nameTag) == 'android.intent.action.MAIN'
                                }
                            }

                            return action.size() > 0;
                        }
                        println "=====found main1 activity=====${mainActivity.size()} $mainActivity"
                        if (mainActivity[0] != null) {
                            mainActivity[0].attributes().put("android:launchMode", 'singleTop')
                        }
                        //mainActivity[0].attributes().put(android.launchMode, 'singleTop')
                        println "=====found main2 activity=====${mainActivity.size()} $mainActivity"
                        def serialize = groovy.xml.XmlUtil.serialize(xml)
                        file(manifestOutFile).write(serialize)
                    }
                }
            }
        }
    }

スクリプト 3 (android stuido unity の両方が有効)

android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def processManifest = output.getProcessManifestProvider().get()
        println("=============== processManifest ${processManifest} ===============")
        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()) {
                ///这里第二个参数是 false ,所以 namespace 是展开的,所以下面不能用 androidSpace,而是用 nameTag
                def xml = new XmlParser(false, false).parse(manifestOutFile)
                println "=====found xml activity=====${xml}"
                if (xml.application != null && xml.application.size() > 0) {
                    def mainActivity = xml.application[0].activity.findAll { ac ->
                        def action = ac.depthFirst().findAll() { node ->
                            if (node != null) {
                                return node.attributes().get('android:name') == 'android.intent.action.MAIN'
                            }
                        }

                        return action.size() > 0;
                    }
                    println "=====found main1 activity=====${mainActivity.size()} $mainActivity"
                    if (mainActivity[0] != null) {
                        mainActivity[0].attributes().put('android:launchMode', 'singleTop')
                    }
                    println "=====found main2 activity=====${mainActivity.size()} $mainActivity"
                    def serialize = groovy.xml.XmlUtil.serialize(xml)
                    file(manifestOutFile).write(serialize)
                }
            }

        }
    }
}

おすすめ

転載: blog.csdn.net/daweibalang717/article/details/125936568