Android Product Flavors Manifests - android

I'm working on my first android app, and I'm just getting started with product flavors. I have a free version in beta, and I'm starting to make a a paid version. I'm a bit confused about the manifests.
The paid version will have one activity that the free version does not, and the two will have different permissions. I'm thinking that I will remove the permissions from the main manifest, that the free manifest will have nothing in it but its permissions, and the paid manifest will have nothing in it but its permissions and the extra activity.
For example, the free manifest might be
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.INTERNET"/>
</uses-permission>
</manifest>
Is this correct?

That's correct, however, I would recommend you put all common Manifest information in the main, as CommonsWare mentioned.
Also, as a tip, if you do need to replace a value in the main Manifest for any reason (debugging for example), I would use the tools:replace tag like so:
Free flavor:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example">
<application
android:name=".FreeApp"
android:allowBackup="false"
tools:replace="allowBackup,name"/>
</manifest>
This would replace the tags name and allowBackup from main with what you have in this manifest.
I recommend you check out the following link for more information about flavoring and variants, in case you haven't already:
https://developer.android.com/studio/build/build-variants.html

Related

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

Does an Android Library need a manifest ,app_name,Icon?

I have an android Library that outputs an aar library. This library will be built into different projectFlavors of Mobile, TV and Wear apps. I think that each of these platforms' should be the ones that set variables like the app name, icon, and permissions through the manifest and productflavors.
Is there any way to build an AAR without requiring an AndroidManifest.xml and therefore drawables(for the icon)?
More information about what I'm doing can be found at my last question on the subject:
Android Studio Java Library Module vs. Android Library Module
Any android library needs to have an AndroidManifest.xml file, but a name or an icon is not required. It's only needed when there is an activity that is MAIN and LAUNCHER.
You simply could use this manifest and your library will work like a charm.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="[your package]"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="[min supported version]" />
<application/>
</manifest>
You can go with the AndroidManifest.xml below if you don't need to setup any Android component like Activities or Services or add custom properties.
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.your.library.base.package" />

How can I add additional Android permissions for my UI test project only?

I try to write files to the external SD card in a from InstrumentationTestCase2 derived test case for pure testing purposes. This works all well when android.permission.WRITE_EXTERNAL_STORAGE is configured in the AndroidManifest.xml file of the application under test, but does not work if this setting is only present in the AndroidManifest.xml file of the test project.
Naturally, I don't want to add this permission to the main manifest, since I only need this capability during my functional tests. How can I achieve that?
In short you should add the same android:sharedUserId for both application's manifest and test project's manifest and declare necessary permission for the test project.
This workaround comes from the fact that Android actually assigns permissions to linux user accounts (uids) but not to application themselves (by default every application gets its own uid so it looks like permissions are set per an application).
Applictions that are signed with the same certificate can however share the same uid. As a consequence they have a common set of permissions. For example, I can have application A that requests WRITE_EXTERNAL_STORAGE permission and application B that requests INTERNET permission. Both A and B are signed by the same certificate (let's say debug one). In AndroidManifest.xml files for A and B android:sharedUserId="test.shared.id" is declared in <manifest> tag. Then both A and B can access network and write to sdcard even though they declare only part of needed permissions because permissions are assigned per uid. Of course, this works only if both A and B are actually installed.
Here is an example of how to set up in case of the test project. The AndroidManifest.xml for application:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testproject"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="com.example.testproject.uid">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<activity
android:name="com.example.testproject.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And the AndroidManifest.xml for a test project
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testproject.test"
android:sharedUserId="com.example.testproject.uid"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.testproject" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<uses-library android:name="android.test.runner" />
</application>
</manifest>
The drawback of this solution is that the application is able to write to external storage too when test package is installed. If it accidentally writes something to a storage it may remain unnoticed until release when the package will be signed with a different key.
Some additional information about shared UIDs can be found at http://developer.android.com/guide/topics/security/permissions.html#userid.
There is another easy answer.
Set the permission in src/debug/AndroidManifest.xml. If the file doesn't exist, create it.
By default, AndroidTest uses debug as BuildType, so if you define your testing permissions there, then the manifest merging process will add these permissions to your UI test build.
Here is the Manifest with new permissions. Note that I didn't include the package attribute because it will be inherited from lower priority level manifest.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>
Also, if you want to apply these permissions to a buildType other than debug, then just move your new AndroidManifest.xml to the folder you want, and use this:
android {
...
testBuildType 'release' // or other buildType you might have like 'testUI'
}

Is versionCode/versionName required in library manifest?

Below is a manifest of one of my library projects. Currently I increase the versionCode and versionName with every change. Is that required?
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="preferExternal"
android:versionCode="14"
android:versionName="1.1.7"
package="com.tubala.android" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="11" />
</manifest>
Thanks in advance.
Currently AndroidManifest.xml of Android Library is completely ignored when building application that uses this library. The only thing that is used by aapt tool is package attribute (to generate R class into correct package).
This might be changed in next releases. But I'd say you should keep your versioning anyway. This is a good practice (even if build tools are ignoring it).
android:versionName attribute is not necessary. It's just a version users see when they open your application information in the application manager.
android:versionCode is more important. You must increase it every time you publish your application on the Android Market.

Android: app incompatible with Huawei?

I have two apps listed on the marketplace. One of them is a free demo application, and the second is a second key application that unlocks the full version of the first application. I received a report from a user that the demo installs on their Huawei, but the market lists they application as "incompatible". I haven't received any other reports of this, and can't find anything useful on Google. The two manifest xmls are below, the demo app first and the key app second. Could this be caused by the check license permission? In android market developer console, the "supported devices" section is the exact same for both apps:
Supported Devices [Learn More] This
application is only available to
devices with these features, as
defined in your application manifest.
Screen layouts: SMALL NORMAL LARGE
XLARGE
Required device features
android.hardware.touchscreen
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="..."
android:versionCode="3"
android:versionName="1.1">
<application ...>
</application>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package=...
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7"/>
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
<application ...
</application>
</manifest>
One thing to do is download both apps from Market, pull them off the device (with "adb pull"), and then use "aapt dump badging " on each of them. This prints out the "badging" information for the app; it is the same thing that Market uses to determine filtering and other things about the app. If there is nothing different between these, then the problem is not in how you have built your apps.

Categories

Resources