it-swarm.com.de

Erstellen Sie Varianten in Gradle für ein Bibliotheksprojekt in Android

Ich versuche mit Gradle ein Projekt zu konfigurieren, das einige externe Bibliotheken enthält. Mit Gradle kann ich verschiedene Umgebungskonfigurationen (mit einer Klasse in einer Konfigurationsdatei) für die Hauptanwendung mithilfe der Build-Varianten einrichten, sodass ich Code gemäß diesen Variablen ausführen kann. 

Das Problem ist, wie kann ich dasselbe für ein Bibliotheksprojekt tun? Ich habe diese Bibliothek für dieses Projekt erstellt und möchte verschiedene Build-Varianten für verschiedene Szenarien einrichten. 

Als Beispiel: Wenn Sie in der Bibliothek im Debug-Modus arbeiten, drucken Sie dann alle Protokolle, damit ich sie während der Entwicklung sehen kann. Im Freigabemodus nicht. 

Struktur der Dateien:

src ----- > debug -> Java -> config -> PlayerEnvConfig
            main -> com.mypackagename -> etc...
            release -> Java -> config -> PlayerEnvConfig

Code in Debug: Paket config;

/**
 * Environment configuration for Release
*/
public final class PlayerEnvConfig {
    public static final boolean USE_REPORTING = true;
    public static final boolean USE_ANALYTICS = true;
    public static final boolean USE_LOGGING = false;
    public static final boolean USE_DEBUG_LOGGING = false;
    public static final boolean USE_DEBUGING = false;
}

Code in der Freigabe:

package config;

/**
 * Environment configuration for Release
*/
public final class PlayerEnvConfig {
    public static final boolean USE_REPORTING = true;
    public static final boolean USE_ANALYTICS = true;
    public static final boolean USE_LOGGING = false;
    public static final boolean USE_DEBUG_LOGGING = false;
    public static final boolean USE_DEBUGING = false;
}

Das Problem ist, dass ich für dieses Hauptprojekt diese Build-Typen verwenden kann, um die Anwendung für verschiedene Szenarien unterschiedlich zu konfigurieren. Wie kann ich dasselbe für das Bibliotheksprojekt tun? 

Denn aus dem, was ich in http://tools.Android.com/tech-docs/new-build-system/user-guide/ gelesen habe, verwendet die Bibliothek nur den Debug-Modus während des Testens. 

Irgendwelche Ideen? 

Vielen Dank!

22
Javier Tarazaga

Es ist eine @bifmadei-Antwort aus google code issue und es hilft mir:

Stellen Sie dies im Abhängigkeitsprojekt ein

Android {
    publishNonDefault true
    ...
}

und dies in dem Projekt, das es verwendet

dependencies {
    releaseCompile project(path: ':theotherproject', configuration: 'release')
    debugCompile project(path: ':theotherproject', configuration: 'debug')
}

Von hier genommen: https://code.google.com/p/Android/issues/detail?id=66805

14
Beloo

Nicht sicher, was mit Ihrer Konfiguration falsch ist, aber was Ihre Bedürfnisse angeht, würde ich es anders machen.

In der Gradle-Build-Datei können Sie das Schlüsselwort buildConfig verwenden, um der generierten Klasse BuildConfig.Java eine bestimmte Zeile hinzuzufügen.

Sie könnten also in Ihrem build.gradle so etwas tun:

    release {
        buildConfig "public static final String USE_REPORTING = true;"
    }
    debug {

        buildConfig "public static final String USE_REPORTING = false;"
    }

Und so hat nur eine PlayerEnvConfig mit

public static final boolean USE_REPORTING = BuildConfig.USE_REPORTING;

Oder nicht mehr PlayerEnvConfig und verwenden Sie direkt die BuildConfig-Klasse.


BEARBEITEN Seit einem Update hat sich die Syntax geändert:

buildConfigField "<type>", "<name>", "<value>"
12
tbruyelle

Dies ist in https://code.google.com/p/Android/issues/detail?id=52962 dokumentiert. Wie Sie herausgefunden haben, wird der Build-Typ nicht für Bibliotheksprojekte weitergegeben, und es gibt keine gute Lösung. Wenn Sie die Kontrolle über den Code des Bibliotheksprojekts haben, können Sie den Debug-Status als veränderliche globale Variable festlegen und beim Start von Ihrer Hauptanwendung aus festlegen. Es ist ein bisschen hackend und hat den Nachteil, dass der Compiler die ungenutzten Codepfade nicht von Release-Builds weg optimieren kann, aber es sollte funktionieren, wenn etwas Ungewöhnliches passiert.

4
Scott Barta

UPDATE - Seit dem Zeitpunkt dieses Beitrags wurden im Gradle-Build-Prozess große Fortschritte erzielt. Daher ist diese Antwort möglicherweise nicht die empfohlene bewährte Methode, und neue Änderungen können sie sogar bremsen. Verwenden Sie nach eigenem Ermessen.

Ich glaube, dass die gesamte Projektstruktur und -konfiguration etwas verwirrt ist. Nehmen wir an, Sie haben die folgende build.gradle-Konfiguration

sourceSets {

    main {
        manifest.srcFile 'src/main/AndroidManifest.xml'
        Java.srcDirs = ['src/main/Java']
        //resources.srcDirs = ['src/main']
        //aidl.srcDirs = ['src/main']
        //renderscript.srcDirs = ['src/main']
        res.srcDirs = ['src/main/res']
        assets.srcDirs = ['src/main/assets']
    }

    debug.setRoot('build-types/debug')
    release.setRoot('build-types/release')
}

Ihre Projektordnerstruktur sollte wie folgt aussehen

project_root
   -src
      -main
         -Java
            -com
               -example
   -build-types
      -debug
         -Java
            -com
               -example
                  -FooBar.Java
      -release
         -Java
            -com
               -example
                  -FooBar.Java

FooBar.Java darf nicht im prooject_root/src/main/Java/com/example sein. Es muss sich im debug- und release-Ordner befinden, der sich außerhalb des src-Ordners, aber im build-types-Ordner befinden soll. Das wird von der setRoot('build-types/*****')-Methode konfiguriert. Viele Leute werden verwirrt, wenn sie 'debug/Java' und 'main/Java' sehen, wobei später auf eine Art 'src/main/Java' von der Präsentation aus verwiesen wird und letztendlich 'debug/Java' in src, der falscher Ordner Ich hoffe diese Hilfe.

Für komplexere Umgebungen mit anderen Bibliotheken können Sie meine Antwort hier abrufen. https://stackoverflow.com/a/19918834/319058

3
Win Myo Htet

Wie Scott weist darauf hin, ist dies ein bekanntes Manko von Gradle . Als Problemumgehung können Sie diese Methode verwenden, die den Feldwert mithilfe der Reflektion aus der App (nicht der Bibliothek) abruft:

/**
 * Gets a field from the project's BuildConfig. This is useful when, for example, flavors
 * are used at the project level to set custom fields.
 * @param context       Used to find the correct file
 * @param fieldName     The name of the field-to-access
 * @return              The value of the field, or {@code null} if the field is not found.
 */
public static Object getBuildConfigValue(Context context, String fieldName) {
    try {
        Class<?> clazz = Class.forName(context.getPackageName() + ".BuildConfig");
        Field field = clazz.getField(fieldName);
        return field.get(null);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

Um beispielsweise das Feld DEBUG zu erhalten, rufen Sie dieses einfach über Ihre Activity auf:

boolean debug = (Boolean) getBuildConfigValue(this, "DEBUG");

Ich habe diese Lösung auch auf dem AOSP Issue Tracker veröffentlicht.

0
Phil

Dies ist bei Bibliotheksprojekten nicht möglich, wie Sie selbst erwähnt haben. 

Sie können das Bibliotheksprojekt einfach in ein Anwendungsprojekt ändern. Das scheint gut zu funktionieren (zumindest theoretisch habe ich es nicht selbst getestet).

Die andere Möglichkeit wäre, diese Klasse in Ihrem Anwendungsprojekt zu überschreiben. Ihre Anwendungsprojektklasse wird beim Zusammenführen ausgewählt und Ihnen stehen diese Werte zur Verfügung.

0
Saad Farooq