Get application Id in XML dynamically - android

I'm using shortcuts in my application and I have multiple product flavors. I want to get the application Id dynamically for target package.
I've given ${applicationId}, but it's not working. I tried with ${packageName} didn't work. any other alternative?
<shortcut
android:enabled="true"
android:icon="#drawable/ic_barcode_icon"
android:shortcutId="bar_code"
android:shortcutShortLabel="#string/shortcuts_my_bar_code">
<intent
android:action="android.intent.action.VIEW.myBarCode"
android:targetClass="com.appemirates.clubapparel.home.HomeActivity"
android:targetPackage="${applicationId}" />
</shortcut>

Manifest placeholders like ${applicationId} are only supported for the manifest, not arbitrary other XML files, such as shortcut metadata resources.
You could try:
Have a copy of your shortcut XML in each product flavor's source set, where that copy has the hardcoded application ID
Use resValue in Gradle to set up a string resource with the application ID (per flavor), and use #string/... notation to refer to it in the shortcut XML
The first one definitely works but is tedious due to the code duplication. I have not tried the second one.
Otherwise, you would be looking at building your own Gradle plugin or similar processor that could dynamically generate these resources from a template.

you can create BuildConfig parameter through gradle.
You need to add below in specific build flavor
resValue "string", "APP_ID", "com.example.myapp.india"
that will generate string resource as per your build flavor.And you can directly use it as below in your code.
<shortcut
android:enabled="true"
android:icon="#drawable/ic_barcode_icon"
android:shortcutId="bar_code"
android:shortcutShortLabel="#string/shortcuts_my_bar_code">
<intent
android:action="android.intent.action.VIEW.myBarCode"
android:targetClass="com.appemirates.clubapparel.home.HomeActivity"
android:targetPackage="#string/APP_ID" />
</shortcut>
Let me know for more help :)

In your app's build.gradle.kts (Gradle Kotlin DSL) you could add:
android {
// your setup...
androidComponents {
onVariants { variant ->
variant.resValues.put(
variant.makeResValueKey("string", "app_id"),
ResValue(variant.applicationId.get())
}
}
}
Which will write a string into the resources with the name app_id and use the application ID of the variant. You will then be able to reference the string resource using #string/app_id inside your XML resource files. ${applicationId} unfortunately only works in Manifest files, as has been mentioned in the other answers.
This solution should also work with flavours and build types which augment the application ID by using applicationIdSuffix, and thus answers the comment from Get application Id in XML dynamically.

Related

How to store app keys in a separate file locally and load from there in build.gradle?

I have some keys or app_id, for instance, fabric app_id, in my build.gradle, different for different build like -
manifestPlaceholders = [
appIcon : "#mipmap/kj_launcher",
roundappIcon: "#mipmap/kj_launcher",
fabric_id: "fabric_app_id"
]
which I indirectly use in AndroidManifest file.
So, my question is, a way to store that fabric_id inside any file which is present locally in my system and then load it over here in the above code, different for the different build?
Just like we do in .properties file and get the value from that inside build.gradle.
I don't want to expose these ids.
There's a number of ways to do this, but the way I do this is to define it the gradle.properties file.
In my local gradle.properties file:
MY_SECRET_API_KEY=Dev_Api_Key_That_I_Dont_Care_If_Devs_Have_Access_To
Then on my CI build server, I have a script that replaces Dev_Api_Key_That_I_Dont_Care_If_Devs_Have_Access_To with a value of the production API key.

Can I use a build.gradle generated String in strings.xml?

Our app name is defined in my build.gradle flavors as
appNameFlavor{
resValue "string", "app_name", "MyApp"
}
This is necessary due to a trademark issue in another country.
The name is also used a lot in our strings.xml file by using
<!DOCTYPE resources [
<!ENTITY appname "MyApp">
]>
<resources>
<string name="activity_intro" translatable="true">&appname; Tour</string>
</resources>
This is not ideal because the string is hard coded and needs to be switched for every flavor.
I tried using #strings/app_name instead of MyApp in the entity and while Android Studio actually rendered it correctly, the build failed.
There are several StackOverflow answers mentioning that I should use <!ENTITY % ents SYSTEM "./res/raw/entities.ent"> instead and simply create those files for each flavor, but the file cannot be resolved.
How could I solve this issue of having a variable app name without putting all the strings that reference the app name into a flavor specific strings.xml file, preferably sticking to the way the app name is currently defined?

Android Studio debug/android manifest doesn't change & giving error

I worked on a android project all day today. Now I am trying to load a project into android studio. It gives me error on > debug/android manifest
even though I corrected the error . It keeps repeating the same error on same place. It looks like coding doesn't change
Error:(45) Tag attribute authorities has invalid character '#'.
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="com.facebook.app.FacebookContentProvider#string/facebook_app_id"
android:exported="true" />
It automatically inserted between permissions on debug/android manifest. original manifest file has no error nor any unnecessary coding between permissions
In Android Studio, try File -> Invalidate Cache and Restart.
I'd similar problem where changes in res/AndroidManifest.xml were not being reflected in debug\AndroidManifest.xml and above step did the trick for me.
Did you checked sample project on facebook-android-sdk repo?
https://github.com/facebook/facebook-android-sdk/blob/master/samples/RPSSample/AndroidManifest.xml
Here
<provider android:authorities="com.facebook.app.FacebookContentProvider157578437735213"
android:name="com.facebook.FacebookContentProvider"
android:exported="true" />
app_id is entered as hard-coded instead of string parameter. You can try this or ensure that you have "facebook_app_id" parameters in strings.xml.
It's failing because you're accessing an #string reference in the middle of the value of the authorities attribute, and references need to appear by themselves to be interpreted correctly. There are a couple approaches around this.
First, you can hardcode the facebook app id by appending it to the end of FacebookContentProvider like so (assume 22222222 is the facebook app id):
<provider android:authorities="com.facebook.app.FacebookContentProvider22222222"
android:name="com.facebook.FacebookContentProvider"
android:exported="true" />
But this is not ideal if you have different facebook app ids (for example, one for development, one for staging, and one for production). To set the authorities attribute dynamically, you first need to set the specific values in your build.gradle file:
...
buildTypes {
release {
resValue "string", "facebook_content_provider_app_id", "\"com.facebook.app.FacebookContentProvider55555555555\""
}
debug {
resValue "string", "facebook_content_provider_app_id", "\"com.facebook.app.FacebookContentProvider22222222222\""
}
}
Once you have that in place, you can reference the facebook app id regardless of the build type dynamically in the AndroidManifest.xml:
<provider android:authorities="#string/facebook_content_provider_app_id"
android:name="com.facebook.FacebookContentProvider"
android:exported="true" />

How can I obfuscate XML resource files with DexGuard?

I am using to DexGuard to process my android applications.
On DexGuard's Homepage they say it features: XML resource obfuscation
I already tested DexGuard and decompiled my output .apks with apktool.
The problem is ALL resource files are decompiled succesffully, so they have not been obfuscated apparently.
Now my question is, does DexGuard automatically obfuscate XML resources or do i have to activate it somehow in my dexguard-project.txt file?
Is it possible to obfuscate XML resources like strings.xml or am I misunderstanding this feature?
Why do you want to obfuscate strings.xml? is it because you have api keys or oauth secrets in there? If so, then better to move them to assets/config.properties file and load to a java.util.Properties object like this...
Properties appConfigProperties = new Properties();
appConfigProperties.load(context.getAssets().open("config.properties"))
String myApiKey = appConfigProperties.get("my_api_key");
(for brevity I've removed the exception handling)
Be sure to enable asset encryption in your DexGuard config file:
-encryptassetfiles assets/**
I received the following statement from DexGuard:
Resource XML files are obfuscated automatically in release builds,
although the differences may be subtle. You can compare the
differences with for instance aapt d xmltree application.apk
AndroidManifest.xml. We are working on more obfuscation of resources
for upcoming versions.
After executing the proposed command aapt d xmltree application.apk (where application.apk is a simple HelloWorld Application) i finally could see what DexGuard actually obfuscates in XML files:
Each attribute in an XML resource file is identified by a name, but often also by a numeric identifier.
 In AndroidManifest.xml for example:
android:versionName(0x010102lc) = "1.0"
In the obfuscation step, DexGuard can remove the name of an attribute, but only if this attribute also has a numeric identifier.
After DexGuard obfuscation the above attribute will look like this:
:(0x010102lc) = "1.0"
As XML elements of strings.xml for instance only have a name and no numeric identifier, there won't be any differences in the decompiled XML file.

Android Eclipse Switching between debug and release for XML file

I have an XML file that contains some config data for my Android App. In it there is config info that can be used for development and production. E.g. the link to our api can be set as follows:
For production:
<api>api.example.com</api>
For development:
<api>dev.example.com</api>
I keep this config file under /assets/app-config.xml
It is quite a hassle to keep having to remember which setting I have in the XML. Is there a way to automatically configure eclipse/ android so that it uses the production for runtime (export etc.) and the development when in debug mode.
Define multiple resources and use BuildConfig.DEBUG to conditionally get a resource or another:
<string name="url_api">api.example.com</string>
<string name="url_api_dev">dev.example.com</string>
When extracting the resource:
getString(BuildConfig.DEBUG ? R.string.url_api_dev : R.string.url_api);
This constant is set to true as long as you run from Eclipse. When you select the Export Signed Application Package option, it will be set to false.
If you use this method, it is a good idea to be aware of this bug.
Customize your build using ANT
Please refer the following link for more information
http://playaprogrammer.blogspot.com/2013/01/android-build-configuration-tutorial.html
I use this to create test and production builds from single source. You can have different configurations for development, QA, Production...

Categories

Resources