In my AndroidManifest.xml file I have the following meta-data tag which should be populated dynamically:
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${FACEBOOK_APP_ID}"/>
My gradle file looks like this:
manifestPlaceholders = [
GOOGLE_PROJECT_ID: "A888844613784",
FACEBOOK_APP_ID: "888570042741264"
]
After "Build & Assemble" the FACEBOOK_APP_ID in the manifest file looks like this:
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="1481023616.000000" />
Unfortunately this is not a String, but a float value. That's not correct or what I want.
I know there is another way to define the FACEBOOK_APP_ID in the string.xml file. But since I have lots of flavors it would be nice and easy to maintain if we put all flavors-related parameters in the build.gradle file instead of the strings.xml files.
Does anyone know how to avoid the string to float conversion?
You can use the following code to add a String value to your string resources from a build.gradle file:
resValue 'string', 'FACEBOOK_APP_ID', 'facebook_application_id'
But I'm not sure if the AndroidManifest.xml file does not support flavor specific strings (I can remember you will get a warning if you try, but I'm not sure).
You could also try to add a null-terminator to your FACEBOOK_APP_ID manifestPlaceholder as suggested in this answer:
FACEBOOK_APP_ID: "888570042741264\0"
Edit:
The code null-terminator method seems not to be working when used directly from the build.gradle file, it does however work when using the null-terminator inside the AndroidManifest.xml file:
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${FACEBOOK_APP_ID}\0"/>
I use manifestPlaceholders and force gradle to recognize the string by escaping the quotes like so:
manifestPlaceholders = [facebook_app_id:"\"9999000099990000\"",
fb_login_protocol_scheme:"fb9999000099990000"]
You don't need to it for the second param since it has the string fb in front.
This is working for me (if you do not use flavors, just put resValue into defaultConfig):
productFlavors {
production {
resValue 'string', 'facebookAppId', '22222222222'
resValue 'string', 'facebookSchemeId', 'fb22222222222'
}
development {
resValue 'string', 'facebookAppId', '11111111111'
resValue 'string', 'facebookSchemeId', 'fb11111111111'
}
}
Then in manifest:
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebookAppId" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/facebookSchemeId" />
</intent-filter>
</activity>
I just face a similar issue where my facebook values were treated as a number and garbled.
If I make sure to wrap them in " then it works as expected and they are treated as strings.
manifestPlaceholders += [FACEBOOK_APP_ID: "\"" + rootProject.facebookAppId + "\"", FACEBOOK_CLIENT_TOKEN: "\"" + rootProject.facebookClientToken + "\""]
Related
I needed to use two different dimensions in the project. But after this usage, whatever I do, Android Studio tells me "Default Activity Not Found". Actually there's no changes in the src folder because I don't need to modify any classes in the flavors.
flavorDimensions "device", "backend"
productFlavors {
dev {
buildConfigField "String", "API_VERSION", "\"1.1\""
...extra configs
dimension "backend"
}
staging {
buildConfigField "String", "API_VERSION", "\"1.1\""
...extra configs
dimension "backend"
}
prod {
buildConfigField "String", "API_VERSION", "\"1.1\""
...extra configs
dimension "backend"
}
android {
buildConfigField "String", "DEVICE_TYPE", "\"ANDROID\""
dimension "device"
}
huawei {
buildConfigField "String", "DEVICE_TYPE", "\"ANDROID_HW\""
versionCode 10000 + defaultConfig.versionCode
dimension "device"
}
}
main/AndroidManifest.xml:
<application
android:name=".XApplication"
...
<activity
android:name=".ui.SplashActivity"
android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
In AndroidManifest.xml, change the android:name attribute of your activity to the fully-qualified class name of your Activity, instead of using the .ui.SplashActivity notation. When you prefix the name with ., it will append that to the package annotation of your <manifest> attribute, which may or may not match the package of your actual Activity class. Make sure your Activity class has the correct package declaration at the top of the file and is located in the right src directory.
The same goes for your Application class name. I avoid using the . notation at all costs.
I'm an iOS developer who is trying to make some small changes on android side but with no clue of how to achieve them. My goal is to implement Facebook SDK inside the app, official documentation says:
In /app/res/values/strings.xml add new string element:
<string name="facebook_app_id">Facebook App ID</string>
Then add in AndroidManifest.xml file new meta-data like below:
<application android:label="#string/app_name" ...>
...
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/facebook_app_id"/>
...
</application>
All is understood but my problem is that I have few product flavors based on which I build at the end stand alone apps, for each I have different Facebook App ID. I would appreciate any kind of help. Thanks!
You can create multiple build types or product flavors inside the app-level build.gradle file and then define different strings for each build variant like this
buildTypes {
prod{
resValue "string", "facebook_app_id", "your app id"
}
dev {
resValue "string", "facebook_app_id", "your app id"
}
}
Now you can access this string inside manifest
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/facebook_app_id"/>
There are many ways. But as you already define multiple flavour in build.gradle in app level then you can define the string over there like this
android {
buildTypes {
flavour1 {
buildConfigField "String", "facebook_app_id", "\"first facebook id 1\""
}
flavour2 {
buildConfigField "String", "facebook_app_id", "\"first facebook id 2\""
}
}
}
It automatically initialise the facebook_app_id to the build when you are creating the build of the flavour.
Happy Coding :)
In build.gradle :
productFlavors {
appDev {
applicationId 'com.android.dev'
}
appTest {
applicationId 'com.android.test'
}
}
flavorDimensions "default"
Inside src folder:
create folder with flavors name
-src
-appDev(folder)
-java(folder)
-res(folder)
-values(folder)
-appTest(folder)
-java(folder)
-res(folder)
-values(folder)
inside values folder you can create strings.xml each folder act as different flavor
you need to pass your facebook app_id in the string files.
<string name="facebook_app_id">35166120881***</string>
<string name="fb_login_protocol_scheme">fb35166120881****</string>
...
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
...
</application>
Important this
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"/>
I have my facebook application id on my gradle properties with :
FACEBOOK_APPLICATION_ID="XXXXXXXXXXXXXXX"
and I set in my defaultConfig :
manifestPlaceholders = [facebookAppId: FACEBOOK_APPLICATION_ID]
then, I want to use this in my manifest with :
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="${facebookAppId}" />
but it doesn't work. The only things working are to set my faceboook id in a string :
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id" />
or to put this directly with :
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="\ XXXXXXXXXXXXXX" />
but I must set my facebook id in my gradle properties. What is the right way to do this ?
Thanks.
I am new on Gradle, but if I understood your questions I would suggest using something like that:
buildTypes {
debug {
// ...
}
release {
// ...
resValue "string", "facebook_application_id", "XXXXXXXXXXXXXXXXX"
}
}
Then, at your release build, for this example, you can use it as
android:value="#string/facebook_application_id"
Or even
R.string.facebook_application_id
I want to create a global variable similar with applicationId.
It is set value in build.gradle and will be used in manifest. Is it possible?
You can set them, for instance I'm setting it for different product flavors
productFlavors {
production {
applicationId = "com.myapp.app"
resValue "string", "authority", "com.facebook.app.FacebookContentProvider5435651423234"
}
development {
applicationId = "com.myapp.development"
resValue "string", "authority", "com.facebook.app.FacebookContentProvider2134564533421"
}
qa {
applicationId = "com.myapp.qa"
resValue "string", "authority", "com.facebook.app.FacebookContentProvider29831237981287319"
}
}
And use it like this
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="#string/authority"
android:exported="true" />
If you just want to use the application id set in gradle in your manifest, you can simply use:
${applicationId}
For instance:
<provider
android:authorities="${applicationId}.ShareFileProvider" ... >
...
</provider>
If you want the same behavior with custom variables, you can use manifestPlaceholders, like this:
android {
defaultConfig {
manifestPlaceholders = [hostName:"www.example.com"]
}
}
And in your manifest:
<intent-filter ... >
<data android:scheme="http" android:host="${hostName}" ... />
...
</intent-filter>
See https://developer.android.com/studio/build/manifest-build-variables.html for more information.
While Marko's answer seems to work, there's currently a better solution that doesn't require adding variables to the string resource files.
The manifest merger accepts placeholders:
For custom placeholders replacements, use the following DSL to
configure the placeholders values :
android {
defaultConfig {
manifestPlaceholders = [ activityLabel:"defaultName"]
}
productFlavors {
free {
}
pro {
manifestPlaceholders = [ activityLabel:"proName" ]
}
}
will substitute the placeholder in the following declaration :
<activity android:name=".MainActivity" android:label="${activityLabel}" >
You can also manipulate those strings with groovy functions.
To use the string in Manifest, you can directly make it in strings.xml.
Like this,
<string name="variable_name">value</string>
I have an app with multiple build variants. The variants are used to build versions of the same app for different companies. So, I have several different variants that build different apps:
com.acme.app1
com.schmoe.app2
com.yop.app3
etc...
The build.gradle file handles this very well:
productFlavors {
app1 {
applicationId "com.acme.app1"
}
app2 {
applicationId "com.schmoe.app2"
}
app3 {
applicationId "com.yop.app3"
}
}
Here's my problem. I am integrating Dropbox into my apps. The AndroidManifest.xml file must be changed for each variant to include the appropriate app key (stored in my string file). Dropbox has the following addition to the manifest file:
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboard">
<intent-filter>
<!-- Change this to be db- followed by your app key -->
<data android:scheme="db-abcdef" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Each build variant needs to change the following line:
<data android:scheme="db-abcdef" />
to the appropriate value for each app variant. In other words, I need to replace part of the above string based on the build variant. For instance
App1
<data android:scheme="db-111111" />
App2
<data android:scheme="db-222222" />
App3
<data android:scheme="db-333333" />
The line is the same for each variant up to the text "db-".
What I need is to dynamically replace the variable portion of the string (the x values) "db-xxxxxx" with a string from my string file.
I think this can be done with gradle scripts but I'm a complete newb with gradle. HELP!
If you can help, please be very specific about what goes where since I SUCK at gradle files and scripting. Thanks in advance!
You can save the string in build.gradle too:
productFlavors {
app1 {
applicationId "com.acme.app1"
resValue "string", "my_app_key", "db-abc"
}
app2 {
applicationId "com.schmoe.app2"
resValue "string", "my_app_key", "db-def"
}
app3 {
applicationId "com.yop.app3"
resValue "string", "my_app_key", "db-ghi"
}
}
And then use it like:
<data android:scheme="#string/my_app_key" />
You can do this the same way you would modify the app name, using a string resource. In your manifest, include:
<data android:scheme="#string/db_scheme" />
Next, you add resources folders for the various build types, and in each, place a custom copy of a resource file, say res/values/flavor.xml:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
<string name="app_name">Customer 1 App</string>
<string name="db_scheme">db-111111</string>
</resources>
This will allow you to have different API keys, schemes, app-names, icons, etc. for your various flavors.
For people visiting this in 2019: You can use manifestPlaceholders per flavor.
In your case:
productFlavors {
app1 {
applicationId "com.acme.app1"
manifestPlaceholders.scheme = "db-111111"
}
app2 {
applicationId "com.schmoe.app2"
manifestPlaceholders.scheme = "db-222222"
}
app3 {
applicationId "com.yop.app3"
manifestPlaceholders.scheme = "db-333333"
}
}
and then use it in your manifest:
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboard">
<intent-filter>
<!-- Change this to be db- followed by your app key -->
<data android:scheme="${scheme}" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Yet another way that is somewhat similar to Hibbem's answer:
android {
defaultConfig {
manifestPlaceholders = [schemeName: "default-scheme"]
}
...
app1 {
applicationId "com.acme.app1"
manifestPlaceholders = [schemeName: "db-111111"]
}
...
}
And in your manifest:
<intent-filter>
...
<data android:scheme="${schemeName}" />
...
</intent-filter>
More from the official docs