如何通过在Android-Studio中编辑build.gradle将我的库放在android.jar前面

时间:2014-12-12 10:16:01

标签: android android-studio gradle android-gradle

首先,这是我在Eclipse中的Java构建路径: enter image description here

这四个jar的common.jar,core.jar,framework.jar,layout.jar'是从Android源代码打包的,其中包含一些开发人员无法公开使用的类。他们不必是导出因为它们是作弊编译器。在Eclipse中一切都很好。

现在我正在尝试使用gradle将我的项目导入Android-Studio。我已经将jar添加到依赖项中,但是我无法更改我的jar和android jar的编译顺序。我不能把这些罐放在android jar前面。我不熟悉gradle,现在编译器无法在这些jar中找到类。任何帮助将不胜感激! 这是我的build.gradle:

apply plugin: 'android'    
dependencies {

    compile files('jars/common.jar')
    compile files('jars/core.jar')
    compile files('jars/framework.jar')
    compile files('jars/layout.jar')
    compile fileTree(dir: 'libs', include: '*.jar')
    compile files('jars/animation_nineoldandroids_src.jar')
    compile files('jars/json_simple_src.jar')
    compile files('jars/jsoup-1.7.2-sources.jar')
}

android {

    compileSdkVersion 17
    buildToolsVersion "21.1.1"
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        // Move the tests to tests/java, tests/res, etc...
        instrumentTest.setRoot('tests')

        // Move the build types to build-types/<type>
        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
        // This moves them out of them default location under src/<type>/... which would
        // conflict with src/ being used by the main source set.
        // Adding new build types or product flavors should be accompanied
        // by a similar customization.
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }
}

11 个答案:

答案 0 :(得分:10)

你不能在Gradle(*)中做你想做的事,至少在写这篇文章时的可预见的未来。一些问题妨碍你:

  • Gradle并没像Eclipse那样对构建类路径中的依赖项进行排序,这就是您将类放在android.jar之前的做法。 Gradle的理念是你应该明确你的构建中的依赖关系,这样才能理解和重复。依赖类路径排序的系统往往是微妙和脆弱的。因此,您需要做的是告诉Gradle您的项目取决于您的自定义类而不是android.jar,但插件的DSL并没有为您提供这样做的方法。在http://forums.gradle.org/gradle/topics/classpath_ordering_againhttp://www.gradle.org/docs/current/userguide/dependency_management.html
  • 进行了一些讨论
  • 另一种看待它的方式是android.jar的引用被硬编码到Android Gradle插件中,因此您无法获得该依赖项并将其替换为其他内容。

(*)说完了这一切,没有什么是不可能的 - 你可以让它发挥作用,但你必须要一起破解某些东西,所以它会比它更容易出问题Eclipse方法,面对SDK和工具更新更难以维护。当出现问题时,你将自己独立。

  • 您可以使用自己的android.jar组合自己的自定义SDK。
  • 你可以破解Android Gradle插件。这种方法肯定很难 - 那里的学习曲线相当陡峭,而且代码处于大量开发状态,这将是您在保持最新状态时的维护负担。

我对这些方法中的任何一种都提供了更多的洞察力,部分原因是我不太了解它并且很容易给你不好的建议,部分是因为我不想要没有经验的开发人员看到这一点认为这是一件很棒的事情。但是如果你弄明白的话,那将是非常值得写的,因为我之前已经看过这样的问题,所以你并不是唯一的问题。

答案 1 :(得分:10)

以下脚本适用于我:

allprojects {
    gradle.projectsEvaluated {
       tasks.withType(JavaCompile) {
           options.compilerArgs.add('-Xbootclasspath/p:/mylib.jar')
       }
    }
}

答案 2 :(得分:8)

我从this post解决了使用系统库构建应用程序的问题:

假设您在libframework.jar中添加了libcore.jarapp/libs等系统库:

  • Xbootclasspath添加到您的顶级build.gradle

    allprojects {
    
        gradle.projectsEvaluated {
            tasks.withType(JavaCompile) {
                options.compilerArgs.add('-Xbootclasspath/p:app/libs/libframework.jar:app/libs/libcore.jar')
            }
        }
    }
    
  • 在您的应用build.gradle
  • ,请使用provided

    dependencies {
        provided fileTree(include: ['*.jar'], dir: 'libs')
    }
    
  • 在同一个应用build.gradle中,添加一个任务,将<orderEntry>引用Android API 25 Platform放在app.iml的最后一个位置,这样gradle会考虑到首先考虑您的系统库和最后的Android SDK:

    preBuild {
    
        doLast {
            def imlFile = file(project.name + ".iml")
            println 'Change ' + project.name + '.iml order'
            try {
                def parsedXml = (new XmlParser()).parse(imlFile)
                def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
                parsedXml.component[1].remove(jdkNode)
                def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
                new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
                groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
            } catch (FileNotFoundException e) {
                // nop, iml not found
            }
        }
    }
    

答案 3 :(得分:0)

您可以自动执行此操作,就像在Eclipse中一样:

File&gt; Project structure...&gt; (select app in Modules)&gt; (go to Dependencies tab)&gt; reposition with arrows on the right

另一种方法是编辑应用程序所在文件夹中的[AppName] .iml文件。您要更改的是文件末尾的标记。但是,每次清理或重新打开项目时,Android Studio都会重新排列这些内容。

答案 4 :(得分:0)

  1. 制作目录(例如:exlibs)
  2. 将您的jar文件复制到exlibs目录
  3. ...

    dependencies {
            provided files("$projectDir/exlibs/yourlib.jar")
    }
    

答案 5 :(得分:0)

我使用以下场景,完美的解决方案!

  1. 将您的XXX.jar添加到资料库
  2. 然后change将“范围”改为“已提供”
  3. 在项目.gradle中找到此内容:

    allprojects { repositories { jcenter() } }

  4. 将其更改为:

    allprojects { repositories { jcenter() } gradle.projectsEvaluated { tasks.withType(JavaCompile) { options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\XXX.jar') } } }

  5. YourApplicationName.iml文件中,将XXX.jar调整为顶部,例如this

  6. 所以,没关系!

答案 6 :(得分:0)

将app / app.iml文件订单更新为

<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="common" level="project" />
<orderEntry type="library" exported="" name="framework" level="project" />
<orderEntry type="library" exported="" name="layout" level="project" />
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />

答案 7 :(得分:0)

对我来说,最简单的解决方案是将android.jar替换为包含隐藏API的android.jar。从此项目library that provides access to Android hidden API and internal resources获取compileSdkVersion并将其放入您的ASDK平台文件夹,以及您正在编译的平台(uint32_t mod_add(uint32_t x, uint32_t y, uint32_t n) { uint32_t res; res = (x + y) % n; )。

我确信它也适用于Eclipse))

答案 8 :(得分:0)

一个更新的,更符合未来发展的答案(因为在最近的JDK中bootclasspath编译器args有所更改):

  • 假设您已从aosp中间件(构建aosp时生成)中获取了诸如framework.jar和libcore.jar之类的系统库,并将它们添加到项目中的文件夹(例如system_libs)中,则将库添加到build中的编译类路径中.gradle:
dependencies {
    compileOnly fileTree(dir: 'system_libs', include: ['*.jar'])
}

gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
        options.bootstrapClasspath = files(
            new File("./system_libs/framework.jar").path,
            new File("./system_libs/libcore.jar").path
        )
    }
}
  •   

    将指向Android API平台的任务添加到app.iml中的最后一个位置,这样gradle将首先考虑系统库,最后考虑Android SDK:

preBuild {
    doLast {
        def imlFile = file(project.name + ".iml")
        println 'Change ' + project.name + '.iml order'
        try {
            def parsedXml = (new XmlParser()).parse(imlFile)
            def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
            parsedXml.component[1].remove(jdkNode)
            def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
            new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
            groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
        } catch (FileNotFoundException e) {
            // nop, iml not found
        }
    }
}

基于@Bertrand的答案

答案 9 :(得分:0)

这真的很简单! 而且您无需再修改项目中的 build.gradle

第 1 步: 在Android-SDK目录下备份你原来的android.jar(例如你的应用compileSdkVersion=30build.gradle中,对应的路径是“~/Library/Android/sdk /platforms/android-30”(在 MacOS 上)。

第 2 步: 将您的自定义 framework.jar(*) 重命名为“android.jar”并将其复制到您的 Android-SDK 目录中,与原始目录相反。

第 3 步: 如果需要,同步 gradle,然后你可以使用你想要的@hide 函数而不会报告红色错误。

(*) 如果你不想花时间克隆 AOSP 并编译它,你最好在 Github 上下载它:https://github.com/anggrayudi/android-hidden-api

祝你好运~

答案 10 :(得分:0)

似乎*.impl文件路径已经改变,你需要改变

def imlFile = file(project.name + ".iml")

def imlFile = file(".." + File.separator + ".idea" + File.separator + "modules" + File.separator + project.name + File.separator + rootProject.name + "." + project.name + ".iml")