Jak stworzyć bibliotekę Androida z gradle bez publicznego ujawniania kodu źródłowego?

Chciałbym stworzyć Jar z projektu biblioteki Androida. Jest ona ustawiona w następujący sposób:

ProjectName
    \- lib
    |   \- lib
    |       \- armeabi
    |           \- libNativeFirst.so
    |           \- libNativeSecond.so
    \- src
        \- main
            \- java
                \- com.package.sdk
                    \- PackageSDK.java

Chciałbym, aby wszystko to zostało zapakowane w słoik, ale bez ujawniania kodu źródłowego obecnego w PackageSDK.java.

Ustawiłem mój build.gradle plik tak:

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
}

Kiedy uruchamiam gradlew clean jar w katalogu projektu, w ProjectName\build\libs tworzony jest plik Jar o nazwie ProjectName.jar. Jego struktura jest następująca:

ProjectName.jar
    \- lib
    |   \- armeabi
    |       \- libNativeFirst.so
    |       \- libNativeSecond.so
    \- com
        \- package
            \- sdk
                \- PackageSDK.java

Chciałbym, aby skompilowany PackageSDK.class został dołączony zamiast pliku PackageSDK.java podczas wykonywania zadania jar. Co mogę zmienić, aby to osiągnąć?

Edit:

Zgodnie z sugestią Bena Manesa zmieniłem konfigurację sourceSets na następującą:

sourceSets {
    main {
        java {
            srcDir 'src/main/java'
        }
        resources {
            srcDir 'src/../lib'
        }
        output {
            classesDir 'build/classes'
            resourcesDir 'build/javaResources'
        }
    }
}

I jar zadanie do:

task jar(type: Jar) {
    from android.sourceSets.main.output
}

Gradle daje mi teraz to wyjście:

Could not find method output() for arguments [build_25r1m0a3etn5cudtt5odlegprd$_run_closure2_closure9_closure10_closure13@138532dc] on source set main.

Author: BVB, 2013-09-26

2 answers

Uwaga: odpowiedź została edytowana. Zapoznaj się z aktualizacją 07/28/2014 poniżej.

Oto rozwiązanie, które wymyśliłem. Może jest lepszy sposób dostępny, ale jeszcze go nie znalazłem.

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)

Running gradlew makeJar tworzy ProjectName.jar w katalogu build/libs. Struktura tego słoika jest następująca:

ProjectName.jar
    \- lib
    |   \- armeabi
    |       \- libNativeFirst.so
    |       \- libNativeSecond.so
    \- com
        \- package
            \- sdk
                \- PackageSDK.class

To jest dokładny wynik, którego potrzebowałem. Jestem teraz w stanie z powodzeniem wykorzystać ProjectName.jar w innych projektach.

EDIT: skoro jestem w stanie użyć wynikający jar w projektach w Android Studio, nie mogę tego zrobić w projektach utworzonych w ADT z powodu ostrzeżenia o kodzie natywnym obecnym wewnątrz pliku jar. Podobno jest flaga, aby wyłączyć to sprawdzenie w Ustawieniach, ale nie działa poprawnie. Tak więc, jeśli chcesz utworzyć bibliotekę, która używa kodu natywnego, osoby korzystające z ADT będą musiały ręcznie skopiować katalog armeabi do libs/.

07/28/2014 aktualizacja:

Od wersji Android Studio 0.8.0, katalogi wyjściowe Gradle zostały zmienione i konfiguracja opisana powyżej nie będzie działać. Zmieniłem konfigurację na:

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')
}

Ważne: należy pamiętać, że ProjectName.jar będzie teraz umieszczony w build/outputs/, a nie w build/libs/.

 68
Author: BVB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-29 18:26:50

Aby dodać lekką alternatywę dla odpowiedzi @BVB (choć mocno na niej bazującej) oto, co musiałem zrobić, aby wygenerować Jar myapp-api.jar, który był tylko dla projektu Java, który zajmował się interakcją z rest API. Zależy od Androida.jar stąd potrzeba użycia apply plugin: 'com.android.application' a nie tylko apply plugin: 'java'

Wywołanie ./gradlew build jar z myJavaAPIProject w celu zbudowania i wygenerowania .jar to myJavaAPIProject/build/libs/myapp-api.jar

Zbuduj.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"
    />
 8
Author: scottyab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-13 17:16:43