如何在不公开源代码的情况下使用 gradle 创建 Android Library Jar?
Posted
技术标签:
【中文标题】如何在不公开源代码的情况下使用 gradle 创建 Android Library Jar?【英文标题】:How to create an Android Library Jar with gradle without publicly revealing source code? 【发布时间】:2013-10-02 18:56:24 【问题描述】:我想从一个 android 库项目中创建一个 Jar。设置方式如下:
ProjectName
\- lib
| \- lib
| \- armeabi
| \- libNativeFirst.so
| \- libNativeSecond.so
\- src
\- main
\- java
\- com.package.sdk
\- PackageSDK.java
我希望将所有这些打包在一个 Jar 中,但不透露 PackageSDK.java
中的源代码。
我这样设置我的build.gradle
文件:
buildscript
repositories
mavenCentral()
dependencies
classpath 'com.android.tools.build:gradle:0.5.+'
apply plugin: 'android-library'
repositories
mavenCentral()
android
compileSdkVersion 18
buildToolsVersion "18.0.1"
defaultConfig
minSdkVersion 10
targetSdkVersion 18
sourceSets
main
java
srcDir 'src/main/java'
resources
srcDir 'src/../lib'
task jar(type: Jar)
from android.sourceSets.main.allSource
当我在项目目录中运行gradlew clean jar
时,会在ProjectName\build\libs
中创建一个名为ProjectName.jar
的Jar 文件。其结构如下:
ProjectName.jar
\- lib
| \- armeabi
| \- libNativeFirst.so
| \- libNativeSecond.so
\- com
\- package
\- sdk
\- PackageSDK.java
我希望在执行jar
任务时包含已编译的PackageSDK.class
而不是PackageSDK.java
文件。我可以改变什么来实现这一点?
编辑:
根据 Ben Manes 的建议,我将 sourceSets
的配置更改为以下内容:
sourceSets
main
java
srcDir 'src/main/java'
resources
srcDir 'src/../lib'
output
classesDir 'build/classes'
resourcesDir 'build/javaResources'
而jar
任务如下:
task jar(type: Jar)
from android.sourceSets.main.output
Gradle 现在给我这个输出:
Could not find method output() for arguments [build_25r1m0a3etn5cudtt5odlegprd$_run_closure2_closure9_closure10_closure13@138532dc] on source set main.
【问题讨论】:
尝试对类文件使用android.sourceSets.main.output
,而不是使用源来构建jar
我应该将sourceSets main output srcDir '_____'
设置成什么?
android插件不使用Java插件吗?其中大部分是预先配置的。也许这必须是output.dirs
。看看 Gradle user guide
我认为它们在某些方面有所不同,但我不能 100% 确定。我用.dirs
尝试过,但它有同样的问题。我发现我可以只使用build/bundles/release
中的classes.jar
文件并将其重命名为ProjectName.jar
,但我希望我不必这样做。
【参考方案1】:
注意:答案已被编辑。请参阅下面的 2014 年 7 月 28 日更新。
这是我最终想出的解决方案。可能有更好的方法可用,但我还没有找到。
android
compileSdkVersion 18
buildToolsVersion "18.0.1"
defaultConfig
minSdkVersion 10
targetSdkVersion 18
sourceSets
main
java
srcDir 'src/main/java'
resources
srcDir 'src/../lib'
task clearJar(type: Delete)
delete 'build/libs/ProjectName.jar'
task makeJar(type: Copy)
from('build/bundles/release/')
into('build/libs/')
include('classes.jar')
rename ('classes.jar', 'ProjectName.jar')
makeJar.dependsOn(clearJar, build)
运行gradlew makeJar
在build/libs
目录中创建一个ProjectName.jar
。这个jar的结构如下:
ProjectName.jar
\- lib
| \- armeabi
| \- libNativeFirst.so
| \- libNativeSecond.so
\- com
\- package
\- sdk
\- PackageSDK.class
这正是我需要的结果。我现在可以在其他项目中成功使用ProjectName.jar
。
编辑:虽然我可以在 Android Studio 中的项目中使用生成的 jar,但我不能在 ADT 中创建的项目中这样做,因为有关 jar 文件中存在本机代码的警告。据说有一个标志可以关闭此签入设置,但它无法正常工作。因此,如果你想创建一个使用原生代码的库,那些使用 ADT 的人将不得不手动将 armeabi 目录复制到 libs/ 中。
2014 年 7 月 28 日更新:
从 Android Studio 0.8.0 开始,Gradle 输出目录已更改,上述配置将不起作用。我已将配置更改为以下内容:
task clearJar(type: Delete)
delete 'build/outputs/ProjectName.jar'
task makeJar(type: Copy)
from('build/intermediates/bundles/release/')
into('build/outputs/')
include('classes.jar')
rename ('classes.jar', 'ProjectName.jar')
重要提示:请注意,ProjectName.jar
现在将被放入 build/outputs/
而不是 build/libs/
。
【讨论】:
它在早期版本中可以使用,但与最新版本的工作室无关,请您检查并更新。 @pyus13 我已经通过配置更改更新了答案,使其适用于最新的 Android Studio 非常感谢。但是我仍然很困惑,想知道如果我们自己编写任务,目录为何重要。我知道默认任务(链接 apk 生成和所有)的输出目录在 0.8.0 中发生了变化,但是它如何影响我们编写的任务,我只想知道我的知识? 就是这样 - Gradle 任务在某些目录中移动文件。由于目录已更改,因此需要更新任务以查看正确的任务。否则,一切都差不多。 +1 用于保持这个答案是最新的。请继续这样做:)【参考方案2】:只是为@BVB 的答案添加一个轻微的替代方案(尽管很大程度上基于它),这是我必须输出一个 jar myapp-api.jar
的方法,该 jar 用于处理 rest API 交互的纯 Java 项目。它依赖于 Android.jar,因此需要使用 apply plugin: 'com.android.application'
而不仅仅是 apply plugin: 'java'
从 myJavaAPIProject 调用 ./gradlew build jar
来构建和生成 .jar 到 myJavaAPIProject/build/libs/myapp-api.jar
build.gradle
//Even though this is a Java project, we need to apply the android plugin otherwise it cannot find the SDK/android.jar and so cannot compile
apply plugin: 'com.android.application'
dependencies
//this ensures we have gson.jar and anything else in the /lib folder
compile fileTree(dir: 'lib', include: '*.jar')
repositories
mavenCentral()
android
compileSdkVersion 21
buildToolsVersion "21.0.1"
defaultConfig
minSdkVersion 10
targetSdkVersion 21
sourceSets
main
java
//points to an empty manifest, needed just to get the build to work
manifest.srcFile 'AndroidManifest.xml'
//defined our src dir as it's not the default dir gradle looks for
java.srcDirs = ['src']
//enforce java 7
compileOptions
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
//Actually created the .jar file
task jar(type: Jar)
//from android.sourceSets.main.java
from 'build/intermediates/classes/release/'
archiveName 'myapp-api.jar'
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- this is a dummy file needed to ensure gradle validates and builds ok -->
<manifest
package="com.myapp.android"
/>
【讨论】:
以上是关于如何在不公开源代码的情况下使用 gradle 创建 Android Library Jar?的主要内容,如果未能解决你的问题,请参考以下文章
在不公开服务名称和主机名的情况下使用 Android XMPP Smack
如何在不设置密码的情况下在防火墙后面使用 Gradle,只是一个用户?
如何在不污染全局命名空间的情况下公开 javascript 对象以进行单元测试