I ran into one confusing issue today about the security tip on developer.android.com such as
allowbackup
debuggable
according to
this merging logic, I think it will come to application manifest and then library manifest. if now host app overwrite the flags i set in library, does that mean i no longer have protection to my library?
for example,
<manifest //this is library manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MYLIBRARY_MANIFEST"
xmlns:tools="http://schemas.android.com/tools">
<application android:allowBackup="false"
android:label="#string/app_name">
</application>
</manifest>
<manifest //this is application manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MYAPPLICATION_MANIFEST"
xmlns:tools="http://schemas.android.com/tools">
<application android:allowBackup="true" //overwrite it as true
android:label="#string/app_name">
</application>
</manifest>
Is there a away to protect the library itself by forcing the library not allowbackup or not debuggable?
does that mean i no longer have protection to my library?
Libraries do not really have "protection" in the first place with respect to manifest entries. Users do.
The developer of the app that uses your library can choose what to do for android:allowBackup, android:debuggable, etc. In the specific case of android:debuggable, that is usually set via Gradle: debug builds set it true; release builds set it false.
Is there a away to protect the library itself by forcing the library not allowbackup or not debuggable?
Libraries do not really have "protection" in the first place with respect to manifest entries. Users do.
You cannot prevent developers from setting whatever value they want for those attributes.
You are welcome to examine the ApplicationInfo object for the app (call getApplicationInfo() on any Context) to see what those flags are set to. You are then welcome to take whatever steps you want based upon that information.
However, bear in mind that the step you appear to want to take — prevent the app from running if the developer does not submit to your demands — simply means that your library will not be used. Telling developers that they cannot do debug builds, for example, is not going to be very popular.
You have Host project and Library. I will explain in debuggable example.
Actually host app always will be play a most important role.
If you doesn't include debuggable flag into manifest file in your library, Android get this flag in Host App (if exist).
So when you setup debuggable = false flag in Library and debuggable=true in Host App, this means that you debuggable flag doesn't affect library, but Host app - affected.
Related
I'm the developer of a library that makes use of APP_RESTRICTIONS. Till now I had the following configuration in the AndroidManifest.xml:
<meta-data
android:name="android.content.APP_RESTRICTIONS"
android:resource="#xml/library_restrictions" />
However, one of our customers now contacted us because his build was failing after adding our library. It turns out that he uses another library which also provides APP_RESTRICTIONS. I know that I can use
tools:node="replace"
or
tools:node="merge"
however this basically means that just one of the restriction configurations get active since it is an attribute on the meta-data. What I need is the content of the two resource files merged automatically to guarantee that the configuration field shows up in the MDM solution. Does anyone know a solution other than informing the developer in the readme that he has to manually merge the content of these two files?
While developing an Android app targeting all versions above 4.1, I observed that uninstalling my app and installing it again does not clear its data.
The app is designed to store the details that it asks in its first screen.
After uninstalling and installing again in OS version 4.4.4, the app prompts the user to fill in the data, which is normal. However in version 6.0 the same install/uninstall sequence bring backs the data originally input.
I tried to ensure by visiting /data/data/my package folder to see the database is gone after uninstalling and indeed that folder gets deleted during uninstall.
I tried to delete the app by visiting the settings page, through Titanium Backup and the results are same. The device is rooted Nexus 5 running v6.0.
What could be the reason for this strange behavior?
It's because Android 6 has automatic backup. You need to tune android:allowBackup and android:fullBackupContent in your manifest <application> tag if you don't want your data backed up or if you want to include or exclude some resources. It's not a bug.
More about AutoBackup on Android here.
greywolf82's answer is correct but I want to add some info to this.
When developing my Android app (using Xamarin), I noticed that whenever I'd re-launch the app from Visual Studio, my data would revert back to data from a few months ago. It didn't matter if I simply stopped and re-ran it from VS, or if I completely uninstalled the app and reinstalled it.
It's also worth noting that we never explicitly told the app to store a backup.
The backup also seemed to overwrite newer data when launching from Visual Studio, and we have reports of users using the release build of our app and also getting newer data overwritten by the backups.
Since I don't know exactly when backups and restores occur this feature seems to cause only problems.
We've modified our AndroidManifest by adding the following two lines:
android:allowBackup="false"
android:fullBackupOnly="false"
After adding them, our AndroidManifest contained the following xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.XXXXXXX" android:versionName="8.0.0" android:installLocation="auto" android:versionCode="439">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="24" />
<application
android:label="#string/appName"
android:icon="#drawable/icon_small"
android:installLocation="internalOnly"
android:largeHeap="true"
android:allowBackup="false"
android:fullBackupOnly="false"
/>
...
</manifest>
Once we explicitly set the value to false, all seems to work. I'd expect this to be an opt-in feature but...seems like it might be on by default for apps which don't specify the value either way.
You should check your device's Backup and Reset settings, and turn off Automatic restore (when reinstalling an application, backed up settings and data will be restored.)
Turning off auto-backup is different from the auto-restore. If you think it will be helpful to turn on auto-backup for your application do so. But if you think this will make end users who are not aware that the auto-restore feature of their device is turned on, feel free to turn it off.
In my case, I turned off the allowBackup feature, but since I already had a backup of the previous version on the Cloud, it still kept on restoring.
See image as reference for a Samsung device on Android 6.0. Other devices and versions may have a different screen. See image below.
Automatic Restore Setting under Backup and Reset
Just adding to this, we found that in Android 9 (on a HMD Nokia device) that the assets were held, even after deleting the app through the interface and through adb.
The answer of adding:
android:allowBackup="false"
android:fullBackupOnly="false"
Obviously, this is not a new answer - but an observation for people who were in the same position as us.
I recently needed to take advantage of these features, I was able to uncover documentation and upon extensive testing this is what I have been able to deduce:
Android:allowbackup - will backup local app data on the device it is located on.
Android:fullBackupContent - is used in conjunction with Google's backup restore api and CAN be controlled via an xml file to specify what exactly to backup, as well as a BackupManager class you may implement for further control over the process.
However the documentation states, and I have confirmed with testing, that a restore will only occur either when the device is restored and the restore app data process is triggered. OR it will also restore when the app is sideloaded through adb, which is what we do when we run the app for testing or debug on our devices through Android Studio. Note that if you set android:allowbackup but do not configure android:fullBackupContent with a Google api code then the apps data only gets stored locally, whereas if you configured it properly then if your app was backed up and you get a new device the apps data was stored on the cloud so it can be restored on a new device.
If you are targeting android 10 then you have to put android:hasFragileUserData="true" in application tag of AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".MyApplication"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:allowBackup="true"
android:hasFragileUserData="true">
.....
</application>
</manifest>
android:hasFragileUserData is a new manifest setting (I’m guessing on ). “If true the user is prompted to keep the app’s data on uninstall”. This seems ripe for abuse, but I can see where it might be useful for some apps.
See https://commonsware.com/blog/2019/06/06/random-musings-q-beta-4.html
Adding android:allowBackup="false" under application tag in Manifest file solved my issue.
Here goes the android documentation for Back up user data with Auto Backup
I also added:
tools:replace="android:allowBackup"
to override same option in a used component
This answer summarizes multiple other existing answers, and includes recent details as of Android 12 being introduced, and includes instructions for clearing existing app backup data generated from a device.
For more information, see
https://developer.android.com/guide/topics/data/autobackup#EnablingAutoBackup
https://developer.android.com/about/versions/12/behavior-changes-12#backup-restore
https://developer.android.com/guide/topics/manifest/application-element
http://android-doc.github.io/preview/backup/index.html (for clearing existing app backup data stored in Google Drive from a device: Settings > Backup > toggle Google One backup off then back on again, then try uninstall/reinstall again)
As a side note, some of the other answers suggest android:fullBackupContent="false" but that doesn't seem correct anymore since that is currently meant to specify an xml file of a specific format, not a true/false.
These attributes to <application> allow for disabling or configuring specifics for Android auto-backup functionality.
<application
tools:replace="android:label, android:icon, android:allowBackup, '...any other attribute you want to override with a value you set in this file for in case dependencies set them to other values...'"
'...your other attributes set here like android:label and android:icon...'
android:allowBackup="false" '...default is true, and setting this false prevents data backups of any kind (except device to device transfers if your app targets Android 11 (API 30) or higher)...'
android:fullBackupContent="#xml/backup_rules_android_11_and_below" '...optional, for Android 11 and below, referring to a file res/xml/backup_rules_android_11_and_below.xml you need to create...'
android:dataExtractionRules="#xml/backup_rules_android_12_and_above" '...optional, for Android 12 and above (fullBackupContent still needed along with this, assuming you support Android 11 and below), referring to a file res/xml/backup_rules_android_12_and_above.xml you need to create, with a slightly different required xml format...'
android:fullBackupOnly="false" '...optional, and default is false, but if set to true this field description says it enables auto backup on Android 6 (API 23) devices or higher (I am not sure how this matters compared to the more broadly reaching allowBackup)...'
android:hasFragileUserData="false" '...optional, and default is false, but if set to true this field description says it gives the user an option when they uninstall the app whether or not to backup their app data...'
>
'...contents of application element...'
</application>
The <application> changes only affect creation (or lack of creation) of future app backups; any existing app backup data will still exist and be used until overwritten or cleared (see above for instructions to clear that data for a device).
Just change android:allowBackup="true" to android:allowBackup="false" in manifiest.xml. It will be worked.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<application
android:allowBackup="false"
android:icon="#mipmap/app_icon"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
</manifest>
Currently I'm using twilio to make calls in android in my application but they don't support arm64 phones yet, my application keeps crashing as it doesn't find the appropriate libtwilio-native.so file.
Is there a way to disable this service only for an architecture? Is there a way to disable the service by default and enable it in runtime?
Additional info:
My manifest.xml file has this:
<service
android:name="com.twilio.client.TwilioClientService"
android:exported="false" />
The bools.xml trick doesn't work for me as arm64 phones and others phones can have the same android version.
Is there a way to disable the service by default and enable it in runtime?
Add android:enabled="false" to the <service> in the manifest. Then, at runtime, you can use PackageManager and the awkwardly-named setComponentEnabledSetting() method to enable it, if desired.
The bools.xml trick doesn't work for me as arm64 phones and others phones can have the same android version.
True, though if you are using product flavors in Android Studio for handling your CPU architecture splits, you should be able to use resConfig in the product flavor definitions in Gradle in lieu of the actual bools.xml files to define the boolean resource, and use that in android:enabled. Note that I have not tried this, YMMV, do not taunt Happy Fun Ball, etc.
Background
In the past, when Eclipse&ADT were the official tools to develop for Android, you could simply use "manifestmerger.enabled=true" inside the "project.properties" of the app's project, and you got it merging all of the libraries' manifests automatically (and I've posted about it here).
This worked, sometimes. It had a lot of weird issues, and I always preferred to just avoid using it, and put what is needed into the main manifest file manually.
The problem
Somewhere on 2014, Google announced that the new Android-Studio (0.1 I think), together with Gradle, will allow you to choose exactly how to perform merging of libraries' components.
However, the new instructions (link here) are very complex and I really (really) tried to understand how to use them, and also didn't find samples of how to use them.
It's not that I didn't understand anything, but I'm not sure if I understood well.
What I've found
On the bright side, I've found out that merging is done completely automatically, so if you have a BroadcastReceiver on the library's manifest (and as a class, of course), it will be added to the app's project that uses it.
The question
I can't simply ask everything to be explained. I think it will be enough to ask those questions:
How can I choose which app components (permissions, activities,...) to be ignored from being auto-merged?
How can I point override app components (of the library) attributes (on the app's project) ? for example the theme of the activities?
Is there a way to completely disable the auto-merger for the manifest files?
What happens with manifests of dependencies that are inside repositories? Are they merged too?
Are there any tutorials/samples/videos regarding this new (well new for me) feature?
Are there any things I should be aware of when using the auto-merger?
I hope those questions are representative enough, informative enough, yet not too hard to answer for people who know.
1. Disabling elements
You can always explicitly disable permissions and features in your app's manifest and override any library values. And i found that you can disable elements from library.
Example
Consider the following code from the above link:
<activity-alias android:name="foo.bar.alias">
<meta-data
android:name="zoo"
tools:node="remove" />
</activity-alias>
By having this code inside your manifest you ensure that the merger finds any <activity-alias> elements with android:name="foo.bar.alias" attribute and removes a <meta-data> element if it has the android:name="zoo" attribute. It removes just the "zoo" meta data. Not the activity alias. If you specify this in your main manifest it will be effective on anything that has been merged so far (elements from libraries).
Example #2
Since you requested an example with activities, this is what I've come up with:
<activity android:name="com.example.ui.MyActivity" tools:node="remove" />
This line will make the merger remove any activities with android:name="com.example.ui.MyActivity" attribute that have been merged so far. So if you specify this in your main manifest it will effectively remove any com.example.ui.MyActivity entries that might have been merged from libraries.
2. Overriding attributes from library
The order in which the values are merged are described here. Basically, it goes like this: libraries, then main manifest, then flavors and build types manifests if you use those.
What are build types?
The default are "debug" and "release". You can define your own and override settings like signing or proguard. For your purposes you could say it's the equivalent of run configurations.
It works like this: you put your default and shared values inside the main manifest. Then in flavor manifests you override the values you need. Google "gradle flavors" for more info.
The following example is taken from a previous version of manifest merger documentation.
Override an attribute coming from a library
Using tools:replace="x, y, z" will override x,y,z attributes from the
imported library’s activity XML declarations.
Higher Priority declaration
<activity
android:name="com.foo.bar.ActivityOne"
android:screenOrientation="portrait"
android:theme="#theme1"
tools:replace="theme"/>
with a lower priority declaration :
<activity
android:name="com.foo.bar.ActivityOne"
android:theme="#olddogtheme"
android:windowSoftInputMode="stateUnchanged"
android:exported="true">
will result in :
<activity
android:name="com.foo.bar.ActivityOne"
android:screenOrientation="portrait"
android:theme="#theme1"
android:windowSoftInputMode="stateUnchanged"
android:exported="true"/>
3. Disabling manifest merger altogether
See Disable Manifest Merger in Android Gradle Build.
android.applicationVariants.all { variant ->
variant.processResources.manifestFile = file('src/main/AndroidManifest.xml')
variant.processManifest.enabled=false
}
In what file do you put this?
At the end of your module's (not root project) build.gradle.
4. Are manifests from dependencies merged?
Yes they are (they're libraries).
Is there a way to block merging certain library manifests?
Not that I know of, sorry.
5. Any tutorials?
Depends on what are you trying to achive. So far it always worked for me out-of-the-box.
e.g. http://www.myandroidsolutions.com/2014/04/10/android-gradle-manifest-merge/
The manifest merger documentation (link below).
I don't know about any videos.
6. Anything I should be aware of?
You can check the generated manifest if you get suspicious about extra permissions etc. It's located in project/module/build/intermediates/manifests/full/[flavor]/build-type/AndroidManifest.xml.
Source: https://developer.android.com/studio/build/manifest-merge
Some of the links in this thread are obsolete. Here's the main one that is updated related to auto merger of manifests, by gradle, for Android AARs.
https://developer.android.com/studio/build/manifest-merge
If I wanted to research how and where permissions [requested in the Mainfest.xml] were used in an Android app for the purposes of removing them is there an easy way of doing this? Does lint or findbugs offer some sort of support for tracking permissions used/abused in a project?
I came from the future to save your lives.
Here (in the future), LINT does check for missing permissions as you can see on LINT checks.
So, go to your AndroidManifest.xml and remove all tags <uses-permission> using Android permissions (meaning, don't delete permissions that belong to your app, such as UA_DATA and C2D_MESSAGE).
Then run LINT analysis. Click on Analyze then Inspect Code...
Look under Android -> Constant and Resource Type Mismatches
You should see all missing permissions.
Then you can just right-click them and select Apply fix "Add Permission". If you select this option, Android Studio will include one permission for every error. So you'll end up with multiple copies of the same permission on your Manifest file, just delete the duplicates. You can do it manually too.
Here is the description of the LINT rule:
ID ResourceType
Description
This inspection looks at Android API calls that have been annotated with various support annotations (such as RequiresPermission or UiThread) and flags any calls that are not using the API correctly as specified by the annotations. Examples of errors flagged by this inspection:
Passing the wrong type of resource integer (such as R.string) to an API that expects a different type (such as R.dimen).
Forgetting to invoke the overridden method (via super) in methods that require it
Calling a method that requires a permission without having declared that permission in the manifest
Passing a resource color reference to a method which expects an RGB integer value.
...and many more. For more information, see the documentation at http://developer.android.com/tools/debugging/annotations.html
I'm using Android Studio 2.1.2.
In your app manifest file you should have a tab "Merged Manifest" there you can see your final manifest and the permissions you request you can click on a permission to see where it came from. (who added it - ex': sdk or what code it came from)
There is also a simple way to remove a permission by adding to manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
tools:node="remove" />
Also remember to add the tools at the top:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="...">
The way I would do it for an app for which I didn't write the code would be to remove the permissions one by one and test the app end-to-end each time. When it fails, narrow it down. If not, that permission may not be used.
You will have to try removing them one by one and checking i fthe app still works OK. This is not checked by lint in any way (it should be).
When they come back (they are currently down), you can upload your apk to this website (if that's ok with you) and let them statically analyse the permissions you are using: http://www.android-permissions.org/
Best way is to understand what the may actually do. If it is ever going to use the camera then you know you need the camera permission.
Or you could just learn what your app does and then go through the permissions and see which ones are extra. What does your app do, what phone features does it use. There should be some documentation somewhere on what it should do and what methods are in there