We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
尝试创建新的SubStream
SubStream
abstract class SimpleClassCreatorTransform extends Transform { String prepareToCreateClass(TransformInvocation transformInvocation) { ... return transformInvocation.outputProvider.getContentLocation("main", getOutputTypes(), getScopes(), Format.DIRECTORY) } }
用Scope集合作为TransformOutputProvider.getContentLocation()有问题
Scope
TransformOutputProvider.getContentLocation()
class SplitComponentTransform extends SimpleClassCreatorTransform { @Override Set<? super QualifiedContent.Scope> getScopes() { return TransformManager.SCOPE_FULL_PROJECT } }
详见build目录下的__content__.json,基本没有混合Scope的SubStream
build
__content__.json
[ { "scopes": [ "EXTERNAL_LIBRARIES" ], "format": "JAR", "types": [ "DEX_ARCHIVE" ], "name": "...", "index": 0, "present": true }, { "scopes": [ "SUB_PROJECTS" ], "format": "JAR", "types": [ "DEX_ARCHIVE" ], "name": "...", "index": 352, "present": true }, { "scopes": [ "PROJECT" ], "format": "DIRECTORY", "types": [ "DEX_ARCHIVE" ], "name": "...", "index": 354, "present": true }, ]
Transform
IntermediateStream
所有使用Transform且Scope不包含EXTERNAL_LIBRARIES的插件。
EXTERNAL_LIBRARIES
修正TransformOutputProvider.getContentLocation()参数 建议改为ImmutableSet.of(QualifiedContent.Scope.PROJECT)。
ImmutableSet.of(QualifiedContent.Scope.PROJECT)
改用代码生成实现此流程 SplitComponentTransform的业务与R.java生成类似,但后者没有侵入到字节码编辑流程。
SplitComponentTransform
R.java
新建一个Android工程,然后把下面代码粘贴到主工程的build.gradle最后。
Android
build.gradle
import com.android.annotations.NonNull import com.android.build.api.transform.DirectoryInput import com.android.build.api.transform.Format import com.android.build.api.transform.JarInput import com.android.build.api.transform.Status import com.android.build.api.transform.TransformException import com.android.build.api.transform.TransformInput import com.android.build.api.transform.TransformInvocation import com.android.build.gradle.BaseExtension import com.android.build.gradle.internal.pipeline.TransformManager import com.android.build.api.transform.Transform import com.android.build.api.transform.QualifiedContent import com.google.common.collect.ImmutableSet import org.apache.commons.io.FileUtils import org.objectweb.asm.ClassWriter import org.objectweb.asm.Opcodes abstract class TransformBase extends Transform { @Override boolean isIncremental() { return false } @Override Set<QualifiedContent.ContentType> getInputTypes() { return ImmutableSet.of(QualifiedContent.DefaultContentType.CLASSES) } private static File getOutputFile(TransformInvocation invocation, QualifiedContent content, Format format) { def provider = invocation.outputProvider return provider.getContentLocation(content.name, content.contentTypes, content.scopes, format) } private static void transformJar(TransformInvocation invocation, JarInput jar) { if (jar.status == Status.REMOVED) { return } def outFile = getOutputFile(invocation, jar, Format.JAR) FileUtils.copyFile(jar.file, outFile) } private static void transformDirectory(TransformInvocation invocation, DirectoryInput dir) { if (!dir.file.exists()) { return } def statusMap = dir.getChangedFiles() def outDir = getOutputFile(invocation, dir, Format.DIRECTORY) FileUtils.copyDirectory(dir.file, outDir, { statusMap.getOrDefault(it, Status.NOTCHANGED) != Status.REMOVED }) } @Override void transform(@NonNull TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException { transformInvocation.inputs.each { TransformInput input -> input.jarInputs.each { transformJar(transformInvocation, it) } input.directoryInputs.each { transformDirectory(transformInvocation, it) } } } } class CopyTransform extends TransformBase { @Override String getName() { return "copy" } @Override Set<? super QualifiedContent.Scope> getScopes() { return ImmutableSet.of( QualifiedContent.Scope.PROJECT, QualifiedContent.Scope.SUB_PROJECTS ) } } class GenClassTransform extends TransformBase { private static final String FOO_CLASS_NAME = "Foo" private static final String FOO_CLASS_PACKAGE = "com.fish47.foo" @Override String getName() { return "genClass" } @Override Set<? super QualifiedContent.Scope> getScopes() { return TransformManager.SCOPE_FULL_PROJECT } private static getGenerateClassFile(File dir) { def subDir = FOO_CLASS_PACKAGE.replace(".", File.separator) def subPath = String.format("%s%c%s.class", subDir, File.separatorChar, FOO_CLASS_NAME) return new File(dir, subPath) } private static byte[] getGenerateClassBytes() { def fullName = String.format("%s/%s", FOO_CLASS_PACKAGE.replace(".", "/"), FOO_CLASS_NAME) def clzAcc = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER def cw = new ClassWriter(0) cw.visit(49, clzAcc, fullName, null, "java/lang/Object", null) def mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null) mv.visitVarInsn(Opcodes.ALOAD, 0) mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false) mv.visitInsn(Opcodes.RETURN) mv.visitMaxs(1, 1) mv.visitEnd() cw.visitEnd() return cw.toByteArray() } private static generateFooClass(TransformInvocation invocation) { def provider = invocation.outputProvider def types = ImmutableSet.of(QualifiedContent.DefaultContentType.CLASSES) def scopes = TransformManager.SCOPE_FULL_PROJECT def outDir = provider.getContentLocation("main", types, scopes, Format.DIRECTORY) def classFile = getGenerateClassFile(outDir) FileUtils.writeByteArrayToFile(classFile, getGenerateClassBytes()) } @Override void transform(@NonNull TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException { super.transform(transformInvocation) generateFooClass(transformInvocation) } } def androidExtension = project.extensions.findByName("android") if (androidExtension instanceof BaseExtension) { // ok // androidExtension.registerTransform(new CopyTransform()) // androidExtension.registerTransform(new GenClassTransform()) // crash androidExtension.registerTransform(new GenClassTransform()) androidExtension.registerTransform(new CopyTransform()) }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
直接原因
尝试创建新的
SubStream
用
Scope
集合作为TransformOutputProvider.getContentLocation()
有问题详见
build
目录下的__content__.json
,基本没有混合Scope
的SubStream
根本原因
Transform
都会"承上启下"地对应一个IntermediateStream
IntermediateStream
对应多个SubStream
SubStream
按Scope
匹配,大部分情况下游是上游的超集,但如果是部分包含则抛异常影响范围
所有使用
Transform
且Scope
不包含EXTERNAL_LIBRARIES
的插件。解决方法
修正
TransformOutputProvider.getContentLocation()
参数建议改为
ImmutableSet.of(QualifiedContent.Scope.PROJECT)
。改用代码生成实现此流程
SplitComponentTransform
的业务与R.java
生成类似,但后者没有侵入到字节码编辑流程。重现代码
新建一个
Android
工程,然后把下面代码粘贴到主工程的build.gradle
最后。The text was updated successfully, but these errors were encountered: