Как поставить мои библиотеки перед android.jar, отредактировав build.gradle в Android-Studio

Сначала вот мой путь сборки Java в Eclipse: enter image description here

Эти четыре jars 'common.jar, core.jar, framework.jar, layout.jar' упакованы из исходного кода Android, который содержит некоторые классы, которые не могут быть публично использованы разработчиком. Их не нужно экспортировать, потому что они для чит-компилятора. В Eclipse все в порядке.

Сейчас я пытаюсь импортировать свой проект в Android-Studio с помощью gradle. Я добавил jar файлы в зависимости, однако я не могу изменить порядок компиляции jar файлов и jar файлов Android. Я не могу поставить эти jar файлы перед jar-ом android. Я не знаком с 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')
    }
}

Ответ 1

Вы не можете делать то, что хотите в Gradle (*), по крайней мере, в обозримом будущем, когда написано это. На вашем пути несколько проблем:

  • Gradle не выполняет упорядочение зависимостей в пути к классам сборки, как это делает Eclipse, что вы и делали, чтобы ваши классы опережали android.jar. У Gradle есть философия, согласно которой вы должны четко указывать на зависимости в вашей сборке, поэтому происходящее понятно и повторяется; Системы, которые полагаются на порядок классов, как правило, тонкие и хрупкие. Поэтому вам нужно сказать Gradle, что ваш проект зависит от ваших пользовательских классов, а не от android.jar, но подключаемый модуль DSL не дает вам средств для этого. Там некоторые обсуждения на http://forums.gradle.org/gradle/topics/classpath_ordering_again и http://www.gradle.org/docs/current/userguide/dependency_management.html
  • Другой способ взглянуть на это - ссылка на android.jar жестко запрограммирована в плагине Android Gradle, поэтому вы не можете найти эту зависимость и заменить ее чем-то другим.

(*) Сказав все это, нет ничего невозможного - вы могли бы заставить это работать, но вам придется что-то взламывать вместе, так что это будет более подвержено проблемам, чем подход Eclipse, и сложнее поддерживать в лицо SDK и обновления инструментов. А когда что-то пойдет не так, вы останетесь сами по себе.

  • Вы можете собрать свой собственный SDK с вашим собственным android.jar.
  • Вы можете взломать плагин Android Gradle. Такой подход, безусловно, был бы сложным - кривая обучения там довольно крутая, а код находится в стадии интенсивной разработки, что будет сопряжено с трудностями обслуживания, если вы будете стараться быть в курсе последних новостей.

Я не решаюсь предложить гораздо более глубокое понимание любого из этих подходов, отчасти потому, что я о нем мало знаю и могу довольно легко дать вам плохой совет, а отчасти потому, что не хочу, чтобы неопытные разработчики увидели это, считая его потрясающим. вещь которую нужно сделать. Но если вы поймете это, это будет очень достойно написания, потому что я уже видел такой вопрос раньше, так что вы не единственный.

Ответ 2

У меня работает следующий скрипт:

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

Ответ 3

Я решил проблему из этого поста по созданию приложения с системными библиотеками:

Предположим, вы добавили системные библиотеки, такие как libframework.jar и libcore.jar в app/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
            }
        }
    }
    

Ответ 4

Вы можете сделать это автоматически, как в Eclipse:

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

Другой способ - отредактировать файл [AppName].iml в папке, в которой находится ваше приложение. То, что вы хотите изменить, это теги в конце файла. Тем не менее, Android Studio будет переставлять их каждый раз, когда вы чистите или заново открываете проект.

Ответ 5

  1. Make dir (ex: exlibs)
  2. Скопируйте файл JAR в каталог exlibs
  3. ..

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

Ответ 6

Я использую следующий сценарий, идеальное решение!

  1. Добавьте свой XXX.jar в библиотеку
  2. Затем измените "Область" на "Предоставлено"
  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 вверху, как этот

так что все в порядке!

Ответ 7

Обновите порядок файлов 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" />

Ответ 8

Самым простым решением для меня было заменить android.jar на другое с включенным скрытым API. Получите android.jar из библиотеки этого проекта , которая предоставляет доступ к скрытому API Android и внутренним ресурсам, и поместите его в папку платформ ASDK, на платформу, с которой вы компилируете (compileSdkVersion).

Я уверен, что это работает и с Eclipse))

Ответ 9

Обновленный и несколько более ориентированный на будущее ответ (поскольку компиляторы bootclasspath менялись в более новых JDK):

  • Предположим, что вы взяли системные библиотеки, такие как framework.jar и libcore.jar, из промежуточных соединений aosp (сгенерированных при сборке aosp) и добавили их в папку (например, 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