簡體   English   中英

SDK項目結構和使用Gradle構建?

[英]SDK Project structure and building with Gradle?

隨着Android Studio成為Android開發的官方IDE,我想從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 Javadoc
  • 其中一個示例應用程序(與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項目模板。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM