SDK 项目结构和构建 Gradle?
SDK Project structure and building with Gradle?
由于 AndroidStudio 正式成为 IDE 用于 Android 开发,我想从 Eclipse 迁移一些项目。
我已经在多个 Android 示例应用程序中共享了 Java 库项目。
在 Eclipse 中,我将 Java 库项目称为项目依赖项,但是当我分发时,Ant 脚本生成库 jar 并将其复制到 Android libs 文件夹。我能够轻松调试我的代码,而无需在分发时公开库源代码或整个项目。
分发后的最终结果必须是带有文档和库 jar 的压缩示例应用程序。关于如何在 Android Studio 中实现它的任何建议?
经过长时间的搜索,我决定编写自己的自定义 gradle 插件,但首先:
项目结构如下所示:
+--------------------+ +---------------------+
|Workspace (Project) | |Distributed archive |
| | | |
| | | |
| +------------+ | | +---------------+ |
| +-+ SDK | | | | SDK Jar lib | |
| | +------------+ | | +---------------+ |
| | | | |
| | +------------+ +---------> +---------------+ |
| +-> Sample 1 | | | | SDK Javadoc | |
| | +------------+ | | +---------------+ |
| | | | |
| | +------------+ | | +---------------+ |
| +-> Sample 2 | | | | Sample source | |
| +------------+ | | +---------------+ |
| | | |
+--------------------+ | +----------------+ |
| | Sample APK | |
| +----------------+ |
| |
+---------------------+
所以我们有几个项目的工作区:一个用于 SDK(纯 Java) 和 几个示例(Java 或 Android) 这取决于它,我们想分发一个包含以下内容的存档:
- SDK Jar 文件
- SDK Java文档
- 示例应用程序之一(来源
与 SDK jar 捆绑在一起)
- 示例应用程序 APK
- 带日期、版本项目和示例名称等的存档名称...
在 Eclipse 中很容易 - 一些依赖项、Ant 脚本和复制到这里,复制到那里,但是现在是迁移到 Intellij 和 Android Studio 的时候了。这是我成功编写自定义 Gradle 脚本的尝试:
apply plugin: CustomProcessor
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.LibraryPlugin
class CustomProcessor implements Plugin<Project> {
private Project mRoot;
private List<WrappedProject> mProjects = new ArrayList<>();
private File mDistribOutput;
class WrappedProject {
private final Project project;
private final Object android;
WrappedProject(Project project) {
this.project = project;
if (isLibrary()) {
this.android = project.plugins.getPlugin(LibraryPlugin)
project.logger.info "${project.name}: SDK (API) project detected."
} else if(isApplication()) {
project.logger.info "${project.name}: Demo (Sample) project detected."
this.android = project.plugins.getPlugin(AppPlugin)
} else {
project.logger.warn "${project.name}: No Android plugin detected."
this.android = null
}
}
public boolean isLibrary() {
return project.plugins.any { p -> p instanceof LibraryPlugin }
}
public boolean isApplication() {
return project.plugins.any { p -> p instanceof AppPlugin }
}
}
@Override
void apply(Project target) {
this.mRoot = target
this.mDistribOutput = new File(target.buildDir, "custom")
target.configure(target.allprojects) { module ->
module.afterEvaluate {
def wrapped = new WrappedProject(module)
mProjects.add(wrapped)
if (wrapped.isLibrary()) {
addSdkTasks(wrapped.project)
}
if (wrapped.isApplication()) {
addSampleTasks(wrapped.project)
}
}
}
}
void addSdkTasks(Object project) {
project.android.libraryVariants.all { variant ->
if (variant.name.equalsIgnoreCase("release")) {
Task t = project.task("generate${project.name.capitalize()}Javadoc", type: Javadoc, overwrite: true) {
description "Generates Javadoc for $project.name."
source = variant.javaCompile.source
ext.androidJar = "${project.android.sdkDirectory}/platforms/${project.android.compileSdkVersion}/android.jar"
classpath = project.files(variant.javaCompile.classpath.files) + project.files(ext.androidJar)
exclude '**/BuildConfig.java'
exclude '**/R.java'
failOnError = false
}
t.group = 'custom'
t = project.task("javadoc${project.name.capitalize()}", type: Jar, overwrite: true) {
description "Bundles Javadoc into a JAR file for $project.name."
classifier = "javadoc"
appendix = project.name
baseName = mRoot.name
version = project.version
from project.tasks["generate${project.name.capitalize()}Javadoc"]
}
t.group = 'custom'
t = project.task("jar${project.name.capitalize()}", type: Jar, overwrite: true) {
description "Bundles compiled .class files into a JAR file for $project.name."
baseName = mRoot.name
appendix = project.name
version = project.version
dependsOn: [project.tasks.assemble ]
from variant.javaCompile.destinationDir
exclude '**/R.class', '**/R$*.class', '**/R.html', '**/R.*.html'
}
t.group = 'custom'
}
}
}
void addSampleTasks(Object sample) {
Task t = sample.task(
"distribute${sample.name.capitalize()}",
dependsOn: [sample.tasks.assemble, ":sdk:jarSdk", ":sdk:javadocSdk"],
overwrite: true,
type: Zip
) {
baseName = mRoot.name
appendix = project.name
version = "v${mRoot.project(':sdk').getVersion()}_${getDate()}"
classifier = 'src'
from("${project.buildDir}/outputs/apk/") {
include '**-debug.apk'
into "apk"
}
from("${mRoot.project(':sdk').buildDir}/docs/javadoc") {
into "doc"
}
from("${mRoot.project(':sdk').buildDir}/libs") {
into "libs"
}
from("${mRoot.project(':sdk').buildDir}/libs") {
into "sample/app/libs"
}
from(sample.zipTree("${sample.rootDir}/sample.zip")) {
into "/"
}
from(sample.projectDir) {
exclude "build"
exclude "**.iml"
exclude "build.gradle"
into "sample/app"
}
}
t.group = 'custom'
}
static def getDate() {
def date = new Date()
def formattedDate = date.format('yyyyMMddHHmmss')
return formattedDate
}
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
allprojects {
repositories {
jcenter()
}
}
要在 Android Studio 中生成示例源作为可打开项目,我使用 sample.zip
,它是空的 Android Studio 项目模板。
由于 AndroidStudio 正式成为 IDE 用于 Android 开发,我想从 Eclipse 迁移一些项目。
我已经在多个 Android 示例应用程序中共享了 Java 库项目。 在 Eclipse 中,我将 Java 库项目称为项目依赖项,但是当我分发时,Ant 脚本生成库 jar 并将其复制到 Android libs 文件夹。我能够轻松调试我的代码,而无需在分发时公开库源代码或整个项目。
分发后的最终结果必须是带有文档和库 jar 的压缩示例应用程序。关于如何在 Android Studio 中实现它的任何建议?
经过长时间的搜索,我决定编写自己的自定义 gradle 插件,但首先:
项目结构如下所示:
+--------------------+ +---------------------+
|Workspace (Project) | |Distributed archive |
| | | |
| | | |
| +------------+ | | +---------------+ |
| +-+ SDK | | | | SDK Jar lib | |
| | +------------+ | | +---------------+ |
| | | | |
| | +------------+ +---------> +---------------+ |
| +-> Sample 1 | | | | SDK Javadoc | |
| | +------------+ | | +---------------+ |
| | | | |
| | +------------+ | | +---------------+ |
| +-> Sample 2 | | | | Sample source | |
| +------------+ | | +---------------+ |
| | | |
+--------------------+ | +----------------+ |
| | Sample APK | |
| +----------------+ |
| |
+---------------------+
所以我们有几个项目的工作区:一个用于 SDK(纯 Java) 和 几个示例(Java 或 Android) 这取决于它,我们想分发一个包含以下内容的存档:
- SDK Jar 文件
- SDK Java文档
- 示例应用程序之一(来源 与 SDK jar 捆绑在一起)
- 示例应用程序 APK
- 带日期、版本项目和示例名称等的存档名称...
在 Eclipse 中很容易 - 一些依赖项、Ant 脚本和复制到这里,复制到那里,但是现在是迁移到 Intellij 和 Android Studio 的时候了。这是我成功编写自定义 Gradle 脚本的尝试:
apply plugin: CustomProcessor
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.LibraryPlugin
class CustomProcessor implements Plugin<Project> {
private Project mRoot;
private List<WrappedProject> mProjects = new ArrayList<>();
private File mDistribOutput;
class WrappedProject {
private final Project project;
private final Object android;
WrappedProject(Project project) {
this.project = project;
if (isLibrary()) {
this.android = project.plugins.getPlugin(LibraryPlugin)
project.logger.info "${project.name}: SDK (API) project detected."
} else if(isApplication()) {
project.logger.info "${project.name}: Demo (Sample) project detected."
this.android = project.plugins.getPlugin(AppPlugin)
} else {
project.logger.warn "${project.name}: No Android plugin detected."
this.android = null
}
}
public boolean isLibrary() {
return project.plugins.any { p -> p instanceof LibraryPlugin }
}
public boolean isApplication() {
return project.plugins.any { p -> p instanceof AppPlugin }
}
}
@Override
void apply(Project target) {
this.mRoot = target
this.mDistribOutput = new File(target.buildDir, "custom")
target.configure(target.allprojects) { module ->
module.afterEvaluate {
def wrapped = new WrappedProject(module)
mProjects.add(wrapped)
if (wrapped.isLibrary()) {
addSdkTasks(wrapped.project)
}
if (wrapped.isApplication()) {
addSampleTasks(wrapped.project)
}
}
}
}
void addSdkTasks(Object project) {
project.android.libraryVariants.all { variant ->
if (variant.name.equalsIgnoreCase("release")) {
Task t = project.task("generate${project.name.capitalize()}Javadoc", type: Javadoc, overwrite: true) {
description "Generates Javadoc for $project.name."
source = variant.javaCompile.source
ext.androidJar = "${project.android.sdkDirectory}/platforms/${project.android.compileSdkVersion}/android.jar"
classpath = project.files(variant.javaCompile.classpath.files) + project.files(ext.androidJar)
exclude '**/BuildConfig.java'
exclude '**/R.java'
failOnError = false
}
t.group = 'custom'
t = project.task("javadoc${project.name.capitalize()}", type: Jar, overwrite: true) {
description "Bundles Javadoc into a JAR file for $project.name."
classifier = "javadoc"
appendix = project.name
baseName = mRoot.name
version = project.version
from project.tasks["generate${project.name.capitalize()}Javadoc"]
}
t.group = 'custom'
t = project.task("jar${project.name.capitalize()}", type: Jar, overwrite: true) {
description "Bundles compiled .class files into a JAR file for $project.name."
baseName = mRoot.name
appendix = project.name
version = project.version
dependsOn: [project.tasks.assemble ]
from variant.javaCompile.destinationDir
exclude '**/R.class', '**/R$*.class', '**/R.html', '**/R.*.html'
}
t.group = 'custom'
}
}
}
void addSampleTasks(Object sample) {
Task t = sample.task(
"distribute${sample.name.capitalize()}",
dependsOn: [sample.tasks.assemble, ":sdk:jarSdk", ":sdk:javadocSdk"],
overwrite: true,
type: Zip
) {
baseName = mRoot.name
appendix = project.name
version = "v${mRoot.project(':sdk').getVersion()}_${getDate()}"
classifier = 'src'
from("${project.buildDir}/outputs/apk/") {
include '**-debug.apk'
into "apk"
}
from("${mRoot.project(':sdk').buildDir}/docs/javadoc") {
into "doc"
}
from("${mRoot.project(':sdk').buildDir}/libs") {
into "libs"
}
from("${mRoot.project(':sdk').buildDir}/libs") {
into "sample/app/libs"
}
from(sample.zipTree("${sample.rootDir}/sample.zip")) {
into "/"
}
from(sample.projectDir) {
exclude "build"
exclude "**.iml"
exclude "build.gradle"
into "sample/app"
}
}
t.group = 'custom'
}
static def getDate() {
def date = new Date()
def formattedDate = date.format('yyyyMMddHHmmss')
return formattedDate
}
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
allprojects {
repositories {
jcenter()
}
}
要在 Android Studio 中生成示例源作为可打开项目,我使用 sample.zip
,它是空的 Android Studio 项目模板。