如何实现provided AAR?如何实现Jar依赖AAR

其实实现思路是简简单单的,就是对AAR剥皮提取其中的classes.jar。直接provided其中的jar即可。
第二个问题,如何Jar依赖AAR也是一样的道理,比如我们要对一组接口打成一个Jar包,但是接口的入参用到了Fragment,不好意思,编译失败,因为找不到Fragment
解决方案
1、获取依赖项对应的AAR地址,通过新增compile的方式对使用者提供入口。
2、extractAarTransform:把AAR拆开提前其中的jar到指定目录,。
3、aarTransform:过滤出所有的Jar文件,并输出。

可悲的是,在Gradle2版本上原生的ExtractAarTransform运行失效,未执行transform方法。没办法只能自己手动调用了。

源码如下:

import com.android.utils.FileUtils
import com.google.common.collect.ImmutableList
import com.google.common.collect.Lists
import com.google.common.io.ByteStreams
import com.google.common.io.Files
import org.gradle.api.artifacts.transform.ArtifactTransform

import javax.inject.Inject
import java.util.jar.JarOutputStream
import java.util.jar.Manifest
import java.util.regex.Pattern
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream

apply plugin: 'java-library'
apply plugin: MyPlugin

def SUPPORT_LIBS_VERSION = '25.1.1'
def targetSdkVersion = 19
def cachePath = "build/pitaya-caches/aar2jar"

public class MyPlugin implements Plugin<Project> {
   @Override
   void apply(Project project) {

       project.getConfigurations().create("AARCompile", new Action<Configuration>() {
           @Override
           public void execute(Configuration config) {

           }
       })
   }
}


sourceCompatibility = "1.7"
targetCompatibility = "1.7"


sourceSets {
   main {
       java.srcDirs = ['src/main/java/']
   }
}

dependencies {
   /*
     Android Jar
    */
   Properties properties = new Properties()
   properties.load(project.rootProject.file('local.properties').newDataInputStream())
   def sdkDir = properties.getProperty('sdk.dir')

   if (isGradle3()) {
       compileOnly files("${sdkDir}/platforms/android-${targetSdkVersion}/android.jar")
   } else {
       project.dependencies.add("compileOnly", files("${sdkDir}/platforms/android-${targetSdkVersion}/android.jar"))
   }

   AARCompile "com.android.support:appcompat-v7:$SUPPORT_LIBS_VERSION"
   AARCompile "com.android.support:recyclerview-v7:$SUPPORT_LIBS_VERSION"

   ExtractAarTransform extractAarTransform = new ExtractAarTransform()
   extractAarTransform.setOutputDirectory(new File(project.rootDir, cachePath))
   AarTransform aarTransform = new AarTransform()
   List<File> fileList = Lists.newArrayList()

   configurations.AARCompile.files.collect {
       if (it.absolutePath.endsWith(".jar")) {
           fileList.add(it.absoluteFile)

           compileOnly project.files(it.absolutePath)

           System.out.println("From AARCompile **===> " + it.absolutePath)
           return
       }

       List<File> tempRoot = extractAarTransform.transform(it.absoluteFile)
       List<File> tempAAR2JarFile = aarTransform.transform(tempRoot.get(0))

       if (isGradle3()) {
           compileOnly project.files(tempAAR2JarFile.toArray())
       } else {
           project.dependencies.add("compileOnly", project.files(tempAAR2JarFile.toArray()))
       }


       fileList.add(tempAAR2JarFile)
       System.out.println("From AARCompile AAR2JarFiles ===> " + tempAAR2JarFile.toArray())
       System.out.println("From AARCompile ===> " + it.absolutePath)
   }
}


public class ExtractAarTransform extends ArtifactTransform {
   private static final String LIBS_PREFIX = "libs/";
   private static final int LIBS_PREFIX_LENGTH = "libs/".length();
   private static final int JARS_PREFIX_LENGTH = "jars".length() + 1;

   @Inject
   public ExtractAarTransform() {
   }

   public List<File> transform(File input) {
       //TODO 1
       File outputDir = new File(this.getOutputDirectory(), input.name);
       FileUtils.mkdirs(outputDir);

       StringBuilder sb = new StringBuilder(20);
       sb.append("jars").append(File.separatorChar);

       try {
           InputStream fis = new BufferedInputStream(new FileInputStream(input));
           Throwable var5 = null;

           try {
               ZipInputStream zis = new ZipInputStream(fis);
               Throwable var7 = null;

               try {
                   ZipEntry entry;
                   try {
                       while ((entry = zis.getNextEntry()) != null) {
                           try {
                               String name = entry.getName();
                               if (!entry.isDirectory()) {
                                   //TODO 2
                                   String path = name;
                                   if (!name.equals("classes.jar")) {
                                       continue
                                   }

                                   if (!name.equals("classes.jar") && !name.equals("lint.jar")) {
                                       if (name.startsWith("libs/")) {
                                           sb.setLength(JARS_PREFIX_LENGTH);
                                           String path2 = name.substring(LIBS_PREFIX_LENGTH);
                                           if ("classes.jar".equals(path2)) {
                                               sb.append("libs/").append("classes-2.jar");
                                           } else if ("lint.jar".equals(path2)) {
                                               sb.append("libs/").append("lint-2.jar");
                                           } else {
                                               sb.append("libs/").append(path2);
                                           }

                                           path = sb.toString();
                                       }
                                   } else {
                                       sb.setLength(JARS_PREFIX_LENGTH);
                                       sb.append(name);
                                       path = sb.toString();
                                   }

                                   File outputFile = new File(outputDir, path.replace("/".chars[0], File.separatorChar));
                                   FileUtils.mkdirs(outputFile.getParentFile());
                                   OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
                                   Throwable var13 = null;

                                   try {
                                       ByteStreams.copy(zis, outputStream);
                                       outputStream.flush();
                                   } catch (Throwable var81) {
                                       var13 = var81;
                                       throw var81;
                                   } finally {
                                       if (outputStream != null) {
                                           if (var13 != null) {
                                               try {
                                                   outputStream.close();
                                               } catch (Throwable var79) {
                                                   var13.addSuppressed(var79);
                                               }
                                           } else {
                                               outputStream.close();
                                           }
                                       }

                                   }
                               }
                           } finally {
                               zis.closeEntry();
                           }
                       }
                   } catch (Throwable var84) {
                       var7 = var84;
                       throw var84;
                   }
               } finally {
                   if (zis != null) {
                       if (var7 != null) {
                           try {
                               zis.close();
                           } catch (Throwable var78) {
                               var7.addSuppressed(var78);
                           }
                       } else {
                           zis.close();
                       }
                   }

               }
           } catch (Throwable var86) {
               var5 = var86;
               throw var86;
           } finally {
               if (fis != null) {
                   if (var5 != null) {
                       try {
                           fis.close();
                       } catch (Throwable var77) {
                           var5.addSuppressed(var77);
                       }
                   } else {
                       fis.close();
                   }
               }

           }
       } catch (Throwable var88) {
           throw new RuntimeException(var88);
       }

       File classesJar = new File(new File(outputDir, "jars"), "classes.jar");
       if (!classesJar.exists()) {
           try {
               Files.createParentDirs(classesJar);
               JarOutputStream jarOutputStream = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(classesJar)), new Manifest());
               jarOutputStream.close();
           } catch (IOException var80) {
               throw new RuntimeException("Cannot create missing classes.jar", var80);
           }
       }

       return ImmutableList.of(outputDir);
   }
}

public class AarTransform extends ArtifactTransform {

   @Inject
   public AarTransform() {
   }

   public List<File> transform(File input) {
       return getJars(input);
   }

   private static List<File> getJars(File explodedAar) {
       List<File> files = Lists.newArrayList();
       File jarFolder = new File(explodedAar, "jars");

       File file = FileUtils.join(jarFolder, "classes.jar");

       if (file.isFile()) {
           files.add(file);
       }

       File localJarFolder = new File(jarFolder, "libs");
       File[] jars = localJarFolder.listFiles(new FilenameFilter() {
           @Override
           boolean accept(File dir, String name) {
               return name.endsWith(".jar");
           }
       });
       if (jars != null) {
           files.addAll(Arrays.asList(jars));
       }

       return files;
   }
}

private boolean isGradle3() {
   Pattern GRADLE_ACCEPTABLE_VERSIONS = Pattern.compile("4\\.\\d*|0\\.\\d*[1-9]\\d*\$")
   if (GRADLE_ACCEPTABLE_VERSIONS.matcher(project.getGradle().getGradleVersion()).matches()) {
       return true
   }
   return false
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354