AGP 3.5.3升级到4.2.2问题记录
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AGP 3.5.3升级到4.2.2问题记录相关的知识,希望对你有一定的参考价值。
参考技术A修改前:
修改后:
项目早就支持了androidx,根目录下的gradle.properties已经有如下两行
但是rebuild后依然报上面的错,找了半天发现老项目的app的module下也有一个gradle.properties,但是里面的android.useAndroidX=false。。。。。。
醉了醉了,把这个多余的gradle.properties删掉就好了。
后来在 AGP4.2.0更新说明 中看到了这么一句话:
gradle.properties 文件的行为变更
从 AGP 4.2 开始,无法再从子项目中替换 Gradle 属性。也就是说,如果您在子项目(而不是根项目)上的 gradle.properties 文件中声明某个属性,该属性将被忽略。
AGP 3.6 以上的版本,在调试开发APP的时候采用了新的打包方式,这里关闭新的打包方式,可以让编译通过
android.namespacedRClass 属性已重命名为 android.nonTransitiveRClass
实验性标记 android.namespacedRClass 已重命名为 android.nonTransitiveRClass。
此标记在 gradle.properties 文件中设置,可启用每个库的 R 类的命名空间,以便其 R 类仅包含库本身中声明的资源,而不包含库的依赖项中的任何资源,从而缩减相应库的 R 类大小。
解决办法:删除gradle.properties中的android.nonTransitiveRClass=true
报错信息如下:Direct local .aar file dependencies are not supported when building an AAR.
The resulting AAR would be broken because the classes and Android resources from any local .aar
file dependencies would not be packaged in the resulting AAR. Previous versions of the Android
Gradle Plugin produce broken AARs in this case too (despite not throwing this error).
修改前aar依赖方式:
修改后aar依赖方式:
4.在module中添加对local_aar的依赖
可以参考: Direct local .aar file dependencies are not supported
[CIRCULAR REFERENCE:com.android.tools.r8.utils.b: Expected [access-flag]* void <init> at C:\\Users\\DT.gradle\\caches\\transforms-3\\fd8ee676f15f0d57578a9e28a336cbac\\transformed\\pol
yvPlayer-2.15.2\\proguard.txt:95:42
public PolyvAuxiliaryVideoView <init>;
解决办法: polyvPlayer升级至net.polyv.android:polyvPlayer:2.15.3
这个问题还未解决,应该是某个第三方library中manifest不规范少写了尖括号导致的
参考:
Android agp 对 R 文件内联支持
Android Gradle 插件版本说明
Gradle Receipes (AGP-7.3) & AGP 使用指南
本文所有代码是基于 https://github.com/android/gradle-recipes agp-7.3分支版本的官方 sample。由于缺乏清晰易懂的说明文档(目前我没有找到可读性较好的文档,如果你知道,请留言告知),有些sample代码即便能够跑通,但在细节方便仍然不是很容易让人理解。
从 AGP 7.0 开始,AGP的API相较AGP 7.0 以前的变化较大,且迭代更新比较频繁,目前官方最新已迭代至8.0,请注意对照你所使用的AGP版本。但是据官方的说法是,从 AGP 7.0+之后的API将逐渐趋于稳定,你不用担心升级之后API会变化太大而导致不能使用了。(我信你个鬼)
另外Gradle插件和Android Studio的版本之间存在着兼容要求,请参考这里
我的电脑目前使用的Android Studio的版本是小海豚,所以AGP的要求是7.3,Gradle的要求是至少7.4:
Groovy Use
获取所有Class文件
import org.gradle.api.DefaultTask
import org.gradle.api.file.Directory
import org.gradle.api.file.RegularFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.TaskAction
import org.gradle.api.provider.ListProperty
import com.android.build.api.artifact.MultipleArtifact
abstract class GetAllClassesTask extends DefaultTask
@InputFiles
abstract ListProperty<Directory> getAllClasses()
@InputFiles
abstract ListProperty<RegularFile> getAllJarsWithClasses()
@TaskAction
void taskAction()
allClasses.get().forEach directory ->
println("Directory : $directory.asFile.absolutePath")
directory.asFile.traverse(type: groovy.io.FileType.FILES) file ->
println("File : $file.absolutePath")
allJarsWithClasses.get().forEach file ->
println("JarFile : $file.asFile.absolutePath")
androidComponents
onVariants(selector().all(), variant ->
project.tasks.register(variant.getName() + "GetAllClasses", GetAllClassesTask.class)
it.allClasses.set(variant.artifacts.getAll(MultipleArtifact.ALL_CLASSES_DIRS.INSTANCE))
it.allJarsWithClasses.set(variant.artifacts.getAll(MultipleArtifact.ALL_CLASSES_JARS.INSTANCE))
)
执行任务后输出:
修改Class文件
在根目录build.gradle中引入javassist插件:
buildscript
dependencies
classpath("org.javassist:javassist:3.22.0-GA")
plugins
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
app/build.gradle中添加任务:
import org.gradle.api.DefaultTask;
import org.gradle.api.file.Directory;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.TaskAction;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.io.FileInputStream;
abstract class ModifyClassesTask extends DefaultTask
@InputFiles
abstract ListProperty<Directory> getAllClasses();
@OutputFiles
abstract DirectoryProperty getOutput();
@TaskAction
void taskAction()
ClassPool pool = new ClassPool(ClassPool.getDefault());
allClasses.get().forEach directory ->
System.out.println("Directory : $directory.asFile.absolutePath");
directory.asFile.traverse(type: groovy.io.FileType.FILES) file ->
System.out.println(file.absolutePath)
if (file.name == "SomeSource.class")
System.out.println("File : $file.absolutePath")
CtClass interfaceClass = pool.makeInterface("com.android.api.tests.SomeInterface");
System.out.println("Adding $interfaceClass")
System.out.println("Write to $output.get().asFile.absolutePath")
interfaceClass.writeFile(output.get().asFile.absolutePath)
new FileInputStream(file).withCloseable
CtClass ctClass = pool.makeClass(it)
ctClass.addInterface(interfaceClass)
CtMethod m = ctClass.getDeclaredMethod("toString")
if (m != null)
m.insertBefore(" System.out.println(\\"Some Extensive Tracing\\"); ")
ctClass.writeFile(output.get().asFile.absolutePath)
androidComponents
onVariants(selector().all(), variant ->
TaskProvider<ModifyClassesTask> taskProvider = project.tasks.register(variant.getName() + "ModifyAllClasses", ModifyClassesTask.class)
variant.artifacts.use(taskProvider)
.wiredWith( it.getAllClasses() , it.getOutput() )
.toTransform(MultipleArtifact.ALL_CLASSES_DIRS.INSTANCE)
)
新建一个 SomeSource 类:
package com.android.api.tests;
class SomeSource
public String toString()
return "Something !";
执行 assembleDebug 后会自动触发 debugModifyAllClasses 任务被执行
在build\\intermediates\\all_classes_dirs\\debug\\debugModifyAllClasses目录下生成一个SomeInterface.class接口类文件,同时SomeSource.class文件中实现了该接口:
添加Class文件
abstract class AddClassesTask extends DefaultTask
@OutputFiles
abstract DirectoryProperty getOutput();
@TaskAction
void taskAction()
ClassPool pool = new ClassPool(ClassPool.getDefault());
CtClass interfaceClass = pool.makeInterface("com.android.api.tests.SomeInterface2")
System.out.println("Adding $interfaceClass")
interfaceClass.writeFile(output.get().asFile.absolutePath)
androidComponents
onVariants(selector().all(), variant ->
TaskProvider<AddClassesTask> taskProvider = project.tasks.register(variant.getName() + "AddAllClasses", AddClassesTask.class)
variant.artifacts.use(taskProvider)
.wiredWith( it.getOutput() )
.toAppendTo(MultipleArtifact.ALL_CLASSES_DIRS.INSTANCE)
)
执行 assembleDebug 后会自动触发 debugAddAllClasses 任务,在 build\\intermediates\\all_classes_dirs\\debug\\debugAddAllClasses 目录下生成一个接口类文件SomeInterface2.class.
获取APK文件
import com.android.build.api.artifact.SingleArtifact
import com.android.build.api.variant.BuiltArtifacts
import com.android.build.api.variant.BuiltArtifactsLoader
abstract class DisplayApksTask extends DefaultTask
@InputFiles
abstract DirectoryProperty getApkFolder()
@Internal
abstract Property<BuiltArtifactsLoader> getBuiltArtifactsLoader()
@TaskAction
void taskAction()
BuiltArtifacts artifacts = getBuiltArtifactsLoader().get().load(getApkFolder().get())
if (artifacts == null)
throw new RuntimeException("Cannot load APKs")
artifacts.elements.forEach
println("Got an APK at $it.outputFile")
androidComponents
onVariants(selector().all(), variant ->
project.tasks.register(variant.getName() + "DisplayApks", DisplayApksTask.class)
it.apkFolder.set(variant.artifacts.get(SingleArtifact.APK.INSTANCE))
it.builtArtifactsLoader.set(variant.artifacts.getBuiltArtifactsLoader())
)
执行 debugDisplayApks 任务,输出:
修改 ApplicationId
abstract class ApplicationIdProducerTask extends DefaultTask
@OutputFile
abstract RegularFileProperty getOutputFile()
@TaskAction
void taskAction()
getOutputFile().get().getAsFile().write("set.from.task." + name)
androidComponents
onVariants(selector().withBuildType("debug")) variant ->
TaskProvider appIdProducer = tasks.register(variant.name + "AppIdProducerTask", ApplicationIdProducerTask.class) task ->
File outputDir = new File(getBuildDir(), task.name)
println("outputDir: $outputDir.absolutePath")
task.getOutputFile().set(new File(outputDir, "appId.txt"))
variant.setApplicationId(appIdProducer.flatMap task ->
task.getOutputFile().map it.getAsFile().text
)
执行 assembleDebug 任务,会自动执行 debugAppIdProducerTask 任务,然后运行app,发现BuildConfig.APPLICATION_ID和context.getPackageName() 返回的都是set.from.task.debugAppIdProducerTask。
重写 Manifest 文件
abstract class GitVersionTask extends DefaultTask
@OutputFile
abstract RegularFileProperty getGitVersionOutputFile()
@TaskAction
void taskAction()
// this would be the code to get the tip of tree version,
// String gitVersion = "git rev-parse --short HEAD".execute().text.trim()
// if (gitVersion.isEmpty())
// gitVersion="12"
//
getGitVersionOutputFile().get().asFile.write("1234")
abstract class ManifestProducerTask extends DefaultTask
@InputFile
abstract RegularFileProperty getGitInfoFile()
@OutputFile
abstract RegularFileProperty getOutputManifest()
@TaskAction
void taskAction()
String manifest = """<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.build.example.minimal"
android:versionName="$new String(getGitInfoFile().get().asFile.readBytes())"
android:versionCode="1" >
<application android:label="Minimal">
<activity android:name="MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
"""
println("Writes to " + getOutputManifest().get().getAsFile().getAbsolutePath())
getOutputManifest().get().getAsFile().write(manifest)
androidComponents
onVariants(selector().all(),
TaskProvider gitVersionProvider = tasks.register(it.getName() + 'GitVersionProvider', GitVersionTask)
task ->
task.gitVersionOutputFile.set(
new File(project.buildDir, "intermediates/gitVersionProvider/output")
)
task.outputs.upToDateWhen false
TaskProvider manifestProducer = tasks.register(it.getName() + 'ManifestProducer', ManifestProducerTask)
task ->
task.gitInfoFile.set(gitVersionProvider.flatMap it.getGitVersionOutputFile() )
it.artifacts.use(manifestProducer)
.wiredWith( it.outputManifest )
.toCreate(SingleArtifact.MERGED_MANIFEST.INSTANCE)
)
执行 assembleDebug 后会自动触发 debugManifestProducer 任务,而 debugManifestProducer 任务的输入依赖于 debugGitVersionProvider 的输出,因此 debugGitVersionProvider 任务先被执行,在 build/intermediates/gitVersionProvider/output 文件中生成版本号。然后会执行 debugManifestProducer 任务,在 build\\intermediates\\merged_manifest\\debug\\debugManifestProducer 目录下生成被覆写的AndroidManifest.xml 文件,其中android:versionName的值被替换为上面output 文件中生成的版本号:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.build.example.minimal"
android:versionName="1234"
android:versionCode="1" >
<application android:label="Minimal">
<activity android:name="MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
修改 Manifest 文件内容
abstract class GitVersionTask extends DefaultTask
@OutputFile
abstract RegularFileProperty getGitVersionOutputFile()
@TaskAction
void taskAction()
// this would be the code to get the tip of tree version,
// String gitVersion = "git rev-parse --short HEAD".execute().text.trim()
// if (gitVersion.isEmpty())
// gitVersion="12"
//
getGitVersionOutputFile().get().asFile.write("8888")
abstract class ManifestTransformerTask extends DefaultTask
@InputFile
abstract RegularFileProperty getGitInfoFile()
@InputFile
abstract RegularFileProperty getMergedManifest()
@OutputFile
abstract RegularFileProperty getUpdatedManifest()
@TaskAction
void taskAction()
String gitVersion = new String以上是关于AGP 3.5.3升级到4.2.2问题记录的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio Arctic Fox | 2020.3.1Gradle 7.0升级记录
Android Studio Arctic Fox | 2020.3.1Gradle 7.0升级记录