How to deal with "${applicationid}" in Xamarin? - android

I'm trying to create bindings for Zendesk library and I faced with a problem.
Zendesk Belvedere library (belvedere-1.0.2.1.aar) contains a file provider in its manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
...
<application>
<provider
android:name="com.zendesk.belvedere.BelvedereFileProvider"
android:authorities="${applicationId}.belvedere.attachments"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/belvedere_attachment_storage" />
</provider>
</application>
</manifest>
When Gradle is used as build tool, it puts this aar to the APK file and it replaces ${applicationId}.belvedere.attachments with com.your_package_name_here.belvedere.attachments in the merged manifest file. It's fine.
However, Xamarin handles it differently. Here is what I found in the manifest of my final APK:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
...
<application
...
...
<provider
android:name="com.zendesk.belvedere.BelvedereFileProvider"
android:exported="false"
android:authorities="dollar_openBracket_applicationId_closeBracket"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/belvedere_attachment_storage" />
</provider>
...
...
</application>
</manifest>
Obviously, dollar_openBracket_applicationId_closeBracket is not what I need.
Seems everything works, however it makes impossible to install several Xamarin applications that use these bindings, because all of them would have conflicting providers with the same authority (and user would get INSTALL_FAILED_CONFLICTING_PROVIDER error).
Is there a way to change dollar_openBracket_applicationId_closeBracket in the manifest?
Edit: A small sample that shows the problem: https://gitlab.com/lassana/ZendeskXamarin/

The current Xamarin.Android manifest merge build task, up to and including
version 7.1.0.19, does not provide any bundeID/ApplicationID (${}} substitution in the merged manifest like gradle does.
This is just a limitation in the manifest processing/merge task, thus you are ending up with dollar_openBracket_applicationId_closeBracket in your final manifest and will have to correct both manifests yourself.
The only current solution know to me to avoid the manifest merge task and it's limitation is to:
Remove the file provider entry from the '.aar`'s manifest
Add the complete file provider entry your app's manifest
Note: You have to do both steps
Depending upon how often the .aar is changing and where you are sourcing the .aar file from:
Manually unzip the aar, remove the entry and re-zip the aar (the quickest way)
Automated this in a build step via a shell script using bash or powershell cmds
Write a MSBuild C#-based Task to do it.
Request that the aar manifest be changed upstream (not likely to happen ;-) since it works fine w/ gradle)
FYI: Personally I have seen the ${applicationId} issue you are having a few times. I have written build scripts (bash/.ps1) to do the manifest fix-up as it seems to always be some special case in the .arr's manifest that I am dealing with.

According to Microsoft team, Xamarin.Build.Download (0.4.12-preview) finally fixes this bug.
So, you should follow these steps:
Update the Nuget Package to 0.4.12-preview3
Restart the IDE
Delete all cached locations of NuGet Packages
Delete bin/obj
Rebuild

The main manifest file of your project is the higher priority manifest, so if you add the provider element to main manifest file and apply a merge rule marker for android:authorities attribute, the merger tools replaces the android:authorities value that you declare in the main manifest.
Declare provider element in main manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
...
...
<application>
<provider
android:name="com.zendesk.belvedere.BelvedereFileProvider"
android:authorities="com.example.belvedere.attachments"
tools:replace=”android:authorities” >
</provider>
</application>

Related

How to override flutter apk manifest?

I am working on updating Android Manifest configurations on my Flutter project. However, there is one recommended fix that I could not find in the libraries I have used in flutter. But upon analyzing the APK, I found it in the AndroidManifest.xml in the APK via APK Analyzer
Shown above is the config I have to update. A very simple update where I have to replace android:exported to false.
I need help in figuring out a way to actually update this manifest since I do not see any file even after looking through each manifest files of the packages I've included in my project that contains the code/config shown above.
Add this in manifest
<application
tools:replace="android:label"
android:name="io.flutter.app.FlutterApplication"
android:label="flutterwp"
android:icon="#mipmap/ic_launcher">
You can simply edit this AndroidManifest.xml file.
Use tools:replace attr.
Checkout following example from official docs:
In library
<activity android:name="com.example.ActivityOne"
android:theme="#oldtheme"
android:exported="false"
android:windowSoftInputMode="stateUnchanged" />
Your own implementation
<activity android:name="com.example.ActivityOne"
android:theme="#newtheme"
android:exported="true"
android:screenOrientation="portrait"
tools:replace="android:theme,android:exported"

Crashlytics Manifest Merge issue with Instant App Architecture

I have a multi-feature instant app setup and when I try to view the merged manifest of the application I see the following:
Error: Attribute provider#com.crashlytics.android.CrashlyticsInitProvider#authorities
value=(com.happyapp.app.crashlyticsinitprovider) from AndroidManifest.xml:14:13-75 is also present
at AndroidManifest.xml:40:87-161 value=(com.happyapp.app.app.crashlyticsinitprovider). Suggestion: add 'tools:replace="android:authorities"' to <provider> element at AndroidManifest.xml:12:9-16:39 to override. app main manifest (this file), line 13
I have looked multiple places and have not found any way to fix this. I can follow the suggestion, but the line that is mentioned to fix doesn't exist in the manifest.
This is the installed app manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.happyapp.app" />
My colleague was able to workaround the issue by adding the following element to the installed apk AndroidManifest.xml
<application>
<provider
android:name="com.crashlytics.android.CrashlyticsInitProvider"
android:authorities="com.happy.happyapp.happyapp.crashlyticsinitprovider"
tools:replace="android:authorities" />
</application>

androidTest AndroidManifest.xml ignored

I have the same issue mentioned in this post AndroidTest Manifest permission not detected
and this post AndroidManifest in androidTest directory being ignored
--> If I put the test manifest in androidTest, debugAndroidTest, androidTestDebug, it never gets picked up and merged.
the answers about putting the AndroidManifest.xml in the debug folder are correct; that does seem to work. (put the test manifest in src/debug
What I want to know is why can't you put it in the androidTest directory? All the documentation I've read while trying to figure this out makes it sound like you should be able to, and that if you can't then I'm thinking that sounds like some bug in the manifest merger.
For what it's worth, I'm using Android Studio
That is correct and totally agree with you on the confusing documentation. The AndroidManifest.xml under androidTest* source sets would be packaged for the instrumentation APK that does your tests on your actual app APK. If you open the generated APKs for debug and androidTest under build/outputs/apk/ after compiling your app module with the command gradlew assembleDebugAndroidTest (assuming that you haven't changed the testBuildType in you build.gradle, more info here), you'll find that any AndroidManifest.xml configuration added under androidTest will be in the androidTest APK and not in your debug app APK.
And also as you said, in case you need test specific configurations like extra permissions, you'll have to place them in the AndroidManifest.xml under the debug source set instead of main, hence they'll only be available for testing your app but not in your release build. Of course you can always double check by opening the generated APKs after compiling to make sure that the configuration is right for each build variant.
If you need to add extra permissions for tests, you can do it.
You should set the same android:sharedUserId in default AndroidManifest.xml and androidTest/AndroidManifest.xml.
For example:
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:sharedUserId="com.yourpackagename.uid">
<application
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="android:allowBackup">
</application>
</manifest>
androidTest/AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="com.yourpackagename.uid">
<uses-permission android:name="android.permission.***" />
</manifest>
For details: https://stackoverflow.com/a/14196493/3901000

Fabric/Crashlytics Android adding string resource for Apikey causes Crashlytics Developer Tools Error

In my android app, I added a the following string resource in the
AndroidManifest.xml
<meta-data
android:name="io.fabric.ApiKey"
android:value="#string/fabric_key" />
and in strings.xml
<string name="fabric_key">XXXXXXXXXXXXXXXXXXXXXXXX</string>
when I try to build the project I get the following error:
Error:Execution failed for task ':app:fabricGenerateResourcesDevDebug'.
Crashlytics Developer Tools error.
Any help would be appreciated.
Try refreshing kit-libs folder by right clicking on "kit-libs" and then selecting refresh kits.
I just looked into this pretty closely. This doesn't work because the android:value attribute is taken literally. To use a resource id you'd have to use android:resource attribute instead but the Fabric gradle plugin does not make use of this android:resource attribute at all because it processes the manifest as an XML document rather than as an Android Manifest class.
After decompiling the Fabric source code and figuring out how the DefaultManifestData and StandardAndroidProject classes work, I confirmed the following:
The Easiest Way to Provide a Separate ApiKey for Debug Builds
Leverage manifest merging by creating app/src/debug/AndroidManifest.xml with the following contents (you must use the tools:replace attribute for this to work):
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<!-- Meta-data -->
<meta-data
android:name="io.fabric.ApiKey"
android:value="[yourDebugApiKey]"
tools:replace="android:value"/>
</application>
</manifest>
Your debug ApiKey is located in your project's Organization Settings page.

Android-Tools Gradle Plugin 0.12 fails with error 'duplicated with element declared at AndroidManifest.xml'

I am struggling with a build error when using Gradle with the Android-Tools Gradle plugin to compile a multi-project build. 2 of my projects fail to build with the error reported above.
Note that we have added additional elements to the Android manifest that we use. Essentially, our AndroidManifest.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xxx.yyy.zzz"
android:versionCode="13"
android:versionName="1.2.3">
<uses-sdk
.../>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.xxx.yyy.CONFIGURATION"/>
<application
...>
<activity
...>
...
</activity>
<activity
...>
...
</activity>
</application>
<meta-data android:name="www" android:value="xxxx"/>
<meta-data android:name="xxx" android:value="yyyy"/>
<meta-data android:name="xxx" android:value="zzzz"/>
</manifest>
The error is being reported on the last 2 meta-data lines (at the bottom of the above example), where the android:name attributes are identical. My limited research has identified this to be valid XML. Unfortunately I have not been able to validate the schema as I understand that no schemas are published.
Extract from the build log:
:src:aaa:processDebugManifest
/xxx/aaa/src/main/AndroidManifest.xml:36:3 Error:
Element meta-data#xxx at AndroidManifest.xml:36:3 duplicated with element declared at AndroidManifest.xml:35:3
/xxx/aaa/src/main/AndroidManifest.xml/AndroidManifest.xml:0:0 Error:
Validation failed, exiting
:src:aaa:processDebugManifest FAILED
I have been using earlier versions of the Android-Tools Gradle Plugin with an identical Android manifest file and this has not caused an issue (last known working version 0.8).
Question: Can I add configuration to my build.gradle file to ignore this? Or would it be worthwhile raising as an issue on the Android-Tools repo?
Thanks

Categories

Resources