unity
Unity version | Gradle version | Android Gradle Plugin version |
---|---|---|
2023.1 | 7.3.3 | 7.2.1 |
2022.2 | 7.2 | 7.1.2 |
2022.1 2021.3 2021.2 2021.1 starting from 2021.1.16f1 2020.3 starting from 2020.3.15f1 | 6.1.1 | 4.0.1 |
2021.1 up to and including 2021.1.15f1 2020.1, 2020.2, 2020.3 up to and including 2020.3.14f1 | 5.6.4 | 4.0.1 |
2019.4 | 5.1.1 | 3.4.0 |
android:
插件版本 | 所需的 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)
}
}
}
支持apk 跟AAB 的版本,摘自android:LaunchMode. Why does Unity have it as singleTask? - Unity Forum
// 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 自动适配 exported 深入解析避坑_沙滩捡贝壳的小孩的博客-CSDN博客
Android 12 自动适配 exported 深入解析避坑 - 专栏 - 声网 RTE 开发者社区
以上脚本在unity 2022.2 不再生效,参考以上链接,编写不同脚本组合,经在 android studio(plugs 7.4.1)实验及unity2022 实验三个脚本写法,最后得出最有效的脚本
脚本一(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)
}
}
}
}
}
}
脚本二(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)
}
}
}
}
}
脚本三(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)
}
}
}
}
}