【问题标题】:How to put my libraries in front of android.jar by editing build.gradle in Android-Studio如何通过在 Android-Studio 中编辑 build.gradle 将我的库放在 android.jar 前面
【发布时间】:2015-02-11 00:45:38
【问题描述】:

首先这是我在 Eclipse 中的 Java 构建路径:

这四个jar'common.jar,core.jar,framework.jar,layout.jar'是从Android源码中打包出来的,里面包含了一些开发者不能公开使用的类。他们不需要导出是因为它们用于作弊编译器。在 Eclipse 中一切正常。

现在我正在尝试使用 gradle 将我的项目导入 Android-Studio。我已将 jars 添加到依赖项中,但是我无法更改我的 jars 和 android jar 的编译顺序。我不能把这些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')
    }
}

【问题讨论】:

  • build.gradle 是 Eclipse 生成的。从 File->Export->Android->Generated Gradle build files,不是我的工作。
  • 任何人都得到了适用于 Android Studio 的工作解决方案

标签: android android-studio gradle android-gradle-plugin


【解决方案1】:

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

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

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

【讨论】:

  • 但是这里没有android.jar,只有我的jars。我在Eclipse中调整了顺序。
  • @kelevandos 建议的解决方案将不起作用。理解是,framework.jar 可能包含额外的类或方法,并且可以覆盖 android.jar 文件。
【解决方案2】:

你不能在 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 插件。这种方法肯定会很困难——那里的学习曲线非常陡峭,而且代码正在大量开发中,当您试图保持最新状态时,这将是一个维护负担。

我不愿提供对这两种方法的更多见解,部分原因是我对此了解不多,很容易给你不好的建议,部分原因是我不希望没有经验的开发人员看到这种想法这是一件很棒的事情。但是如果你弄清楚了,那将非常值得写出来,因为我以前见过这样的问题,所以你不是唯一的。

【讨论】:

    【解决方案3】:

    以下脚本适用于我:

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

    【讨论】:

    【解决方案4】:
    1. 制作目录(例如:exlibs)
    2. 将 jar 文件复制到 exlibs 目录
    3. ..

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

    【讨论】:

      【解决方案5】:

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

      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】:

        将 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】:

          对我来说最简单的解决方案是用包含隐藏 API 的 android.jar 替换。从此项目 library that provides access to Android hidden API and internal resources 中获取 android.jar 并将其放置到您的 ASDK 平台文件夹中,放置到您正在编译的平台 (compileSdkVersion)。

          我确信它也适用于 Eclipse ))

          【讨论】:

            【解决方案8】:

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

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

            • 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中,添加一个任务将&lt;orderEntry&gt;指代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
                      }
                  }
              }
              

            【讨论】:

            • 我必须从 sdk/android.jar 替换 android.bluetooth。我构建了一个包含 android.bluetooth 类的 jar。我尝试了相同的步骤。 Studio 能够解析在 android.bluetooth 中添加的自定义方法。但是在构建时我得到编译错误说无法解析方法。有什么帮助吗? stackoverflow.com/questions/46314161/…
            • bootclasspath 应该是绝对路径。像这样:stackoverflow.com/a/55060070/3673440
            • @Bertrand Martel 我遇到了同样的问题,我已经使用了你的答案,现在 gradle 同步成功,但是如果我尝试构建它会失败并出现编译错误。你能帮忙吗?
            【解决方案9】:

            一个更新的、更具前瞻性的答案(因为 bootclasspath 编译器参数在最近的 JDK 中一直在变化):

            • 假设您从aosp中间体(构建aosp时生成)中获取了framework.jar和libcore.jar等系统库并将它们添加到项目中的文件夹(例如system_libs)中,将这些库添加到构建中的编译类路径.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
                    )
                }
            }
            
            • 在 app.iml 中添加一个任务,将引用 Android API 平台放在最后位置,这样 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 的回答

            【讨论】:

            • 很棒的帖子,你帮了我很多。只是一个小提示, file(project.name + ".iml") 返回不正确的路径。我不得不修改那条线并使用它。 def imlFile = new File("$rootDir/.idea/modules/$project.name/$rootProject.name"+"."+"$project.name"+".iml").absolutePath
            • 这个答案值100分!很有帮助!
            【解决方案10】:

            这真的很容易! 而且您不再需要在您的项目中修改build.gradle

            第 1 步: 将你原来的android.jar备份到Android-SDK目录下(如你的应用build.gradle中的compileSdkVersion=30,对应路径为“~/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

            祝你好运~

            【讨论】:

              【解决方案11】:

              *.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")
              
              

              【讨论】:

                猜你喜欢
                • 2021-11-18
                • 2016-10-22
                • 2015-07-10
                • 2016-03-25
                • 2015-09-14
                • 1970-01-01
                • 1970-01-01
                • 2023-03-20
                • 2011-12-30
                相关资源
                最近更新 更多