Jak mogę uzyskać dostęp do wartości BuildConfig w moim pliku AndroidManifest.xml?

137

Czy jest możliwy dostęp do wartości BuildConfig z AndroidManifest.xml?

W moim pliku build.gradle mam:

defaultConfig {
    applicationId "com.compagny.product"
    minSdkVersion 16
    targetSdkVersion 21
    versionCode 1
    versionName "1.0"

    // Facebook app id
    buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID
}

FACEBOOK_APP_ID jest zdefiniowany w moich plikach gradle.properties:

# Facebook identifier (app ID)
FACEBOOK_APP_ID=XXXXXXXXXX

Aby korzystać z połączenia z Facebookiem w mojej aplikacji, muszę dodać ten wiersz do mojego pliku AndroidManifest.xml:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/applicationId"/> 

Chcę zamienić @string/applicationIdna pole BuildConfig FACEBOOK_APP_IDzdefiniowane w gradle, na przykład:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="FACEBOOK_APP_ID"/> 

Czy jest to możliwe przy użyciu BuildConfig? Jeśli nie, jak mogę to osiągnąć?

antoni
źródło

Odpowiedzi:

190

Zastąpić

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

z

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

następnie przebuduj swój projekt (Android Studio -> Build -> Rebuild Project).

Oba polecenia generują wygenerowane wartości - składające się ze stałych Java w pierwszym przypadku i zasobów systemu Android w drugim - podczas budowania projektu, ale druga metoda wygeneruje stringwartość zasobu, do której można uzyskać dostęp za pomocą @string/FACEBOOK_APP_IDskładni. Oznacza to, że można go używać zarówno w manifeście, jak iw kodzie.

stkent
źródło
1
To jest dokładny kod, którego używam, ale mam problem: zestaw SDK Facebooka z jakiegoś powodu odczytuje ciąg jako liczbę całkowitą, a następnie generuje wyjątek ClassCastException, ponieważ nie można rzutować liczby całkowitej na ciąg. Czy ktoś napotkał ten problem?
WKS
@WKS Jeśli spojrzysz na wygenerowany plik zasobów, czy typ zasobu jest zgodny z tym, czego się tam spodziewasz (ciąg znaków)?
stkent
to jest ciąg:<item name="facebook_app_id" type="string">15233522...</item>
WKS
13
upewnij się, że wpisujesz resValue „string”, a NIE resValue „String”
keybee
1
Jeśli chcesz użyć wartości logicznej, wpisz resValue „bool” zamiast „boolean” -> tanelikorri.com/tutorial/android/set-variables-in-build-gradle
reavcn
85

Innym sposobem uzyskania dostępu do wartości konfiguracji Gradle Build Config z pliku AndroidManifest.xml jest użycie takich symboli zastępczych:

android {
    defaultConfig {
        manifestPlaceholders = [ facebookAppId:"someId..."]
    }
    productFlavors {
        flavor1 {
        }
        flavor2 {
            manifestPlaceholders = [ facebookAppId:"anotherId..." ]
        }
    }
}

a potem w swoim manifeście:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${facebookAppId}"/> 

Zobacz więcej szczegółów tutaj: https://developer.android.com/studio/build/manifest-build-variables.html

(Stary link tylko w celach informacyjnych: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger )

GregoryK
źródło
2
To świetne rozwiązanie.
BinaryShrub
2
Tak, to niezła metoda na wstrzykiwanie ciągu znaków tylko w manifeście!
stkent
2
Jak uzyskać wartość z manifestPlaceholder w java? Byłoby to przydatne w przypadku stałych używanych zarówno w kodzie java, jak iw manifeście.
Louis CAD,
@LouisCAD Przypuszczam, że możesz spróbować zdefiniować zmienną w pliku kompilacji, a następnie użyć jej do zdefiniowania symbolu zastępczego i (dodatkowo) pola BuildConfig, abyś mógł go użyć w swoim kodzie.
GregoryK
1
@LouisCAD Nie próbowałem tego, ale możesz spróbować: var placeholder = 'your placeholder' (new line) buildConfigField "String", "PLACEHOLDER_NAME", placeholder (new line) manifestPlaceholder = [placeholderName: placholder] (nowe line) Byłoby miło wiedzieć, czy to działa dla Ciebie
GregoryK,
40

uwaga: kiedy używasz resValuewartość może zostać przypadkowo nadpisana przez plik zasobów stringów (np. dla innego języka)

Aby uzyskać prawdziwą stałą wartość, której możesz użyć w manifeście i kodzie java, użyj obu manifestPlaceholdersi buildConfigField: np

android {
    defaultConfig {
        def addConstant = {constantName, constantValue ->
            manifestPlaceholders += [ (constantName):constantValue]
            buildConfigField "String", "${constantName}", "\"${constantValue}\""
        }

        addConstant("FACEBOOK_APP_ID", "xxxxx")
    }

dostęp w pliku manifestu:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${FACEBOOK_APP_ID}"/>

z java:

BuildConfig.FACEBOOK_APP_ID

Jeśli stała wartość musi być specyficzna dla buildType, pomocnik addConstantmusi zostać zmodyfikowany (aby pracować z semantyką zamknięcia groovy), np.

buildTypes {
    def addConstantTo = {target, constantName, constantValue ->
        target.manifestPlaceholders += [ (constantName):constantValue]
        target.buildConfigField "String", "${constantName}", "\"${constantValue}\""
    }
    debug {
        addConstantTo(owner,"FACEBOOK_APP_ID", "xxxxx-debug")
    }
    release {
        addConstantTo(owner,"FACEBOOK_APP_ID", "xxxxx-release")
    }
TmTron
źródło
1
Nie działa to pokazuje nieprawidłowy identyfikator aplikacji, z oczywistego, ale kiedy zestaw z java to działa
Brajendra Pandey
Myślę, że to nie zadziała, jeśli spróbujesz dodać więcej niż jedną stałą!
Greg Ennis,
1
@GregEnnis Również więcej stałych działa dobrze dla mnie: np. Po prostu dzwonię addConstant()dwa razy ( constantNamesoczywiście z różnymi ). Jaki błąd otrzymujesz?
TmTron
1
@TmTron nie otrzymujesz błędu, ale ponownie przypisujesz całą tablicę „manifestPlaceholder” za każdym razem, gdy jest ona wywoływana, przechowując tylko ostatnią użytą wartość.
Greg Ennis
@GregEnnis masz absolutną rację! Miałem inny kod w moim projekcie testowym. Zaktualizowałem już moją odpowiedź: po prostu musimy użyć takiego +=operatoramanifestPlaceholders += [...]
TmTron
6

Uzyskaj dostęp do właściwości build.gradle w swoim manifeście, jak w poniższym przykładzie:

Na przykład masz właściwość „applicationId” w pliku build.gradle i chcesz uzyskać do niej dostęp w swoim AndroidManifest:

wprowadź opis obrazu tutaj

Otwórz „applicationId” w AndroidManifest:

<receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="${applicationId}" />
        </intent-filter>
    </receiver>

Podobnie możemy tworzyć zasoby ciągów dla innych stałych i uzyskiwać do nich dostęp w plikach kodu tak prostych jak:

context.getString(R.string.GCM_SENDER_ID);
Vinay
źródło
czy mogę zdefiniować facebookAppId: "anotherId ..." w pliku .properties, w którym będę zapisywał moje hasło do sklepu i wszystko. Następnie uzyskuję dostęp do tych w manifestplaceholderach, które byłyby pośrednio dostępne w AndroidManifest.xml. Czy mogę to zrobić?
Aman Verma
3

@stkent jest dobry, ale zapomina dodać, że później musisz odbudować swój projekt

Zastąpić

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

z

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

następnie

Android Studio -> Build -> Rebuild Project

Umożliwi to systemowi Android wygenerowanie zasobu ciągu dostępnego za pośrednictwem

R.string.FACEBOOK_APP_ID
BLA
źródło
Nie można uzyskać nieznanej właściwości „FACEBOOK_APP_ID” dla ProductFlavor_ ...
f.trajkovski
2

Inna opcja: użyj innego pliku zasobów ciągu, aby zastąpić wszystkie wartości zależne od smaku:

Krok 1: Utwórz nowy folder w folderze „src” z nazwą swojego smaku, w moim przypadku „stage”

Krok 2: Utwórz pliki zasobów dla wszystkich plików zależnych od smaku, na przykład:

wprowadź opis obrazu tutaj

Krok 3: Używam również różnych ikon, więc widzisz również foldery mipmap. W przypadku tego zapytania ważny jest tylko plik „strings.xml”. Teraz możesz nadpisać wszystkie ważne zasoby ciągów. Musisz tylko dołączyć te, które chcesz przesłonić, wszystkie inne zostaną użyte z głównego pliku „strings.xml”, pojawi się w Android Studio w następujący sposób:

wprowadź opis obrazu tutaj

Krok 4: Wykorzystaj zasoby tekstowe w swoim projekcie i zrelaksuj się:

wprowadź opis obrazu tutaj

Björn Kechel
źródło
Dobra alternatywa, zwłaszcza jeśli masz wiele innych ciągów, które musisz ustawić dla każdego wariantu.
stkent
czy mogę zdefiniować facebookAppId: "anotherId ..." w pliku .properties, w którym będę zapisywał moje hasło do sklepu i wszystko. Następnie uzyskuję dostęp do tych w manifestplaceholderach, które byłyby pośrednio dostępne w AndroidManifest.xml. Czy mogę to zrobić?
Aman Verma
0

Możesz użyć długiej wartości, jak poniżej

buildConfigField „long”, „FLAVOR_LONG”, „11500L”

Keyur Thumar
źródło