I have to make some configuration settings specific to certain builds of my app, in the manifest.
These builds have same package name and code basis as the "normal" ones -> it's the same app. But I need these few little extras in the manifest.
It's clear that I can make that, just by creating 2 different builds with slightly different manifest file.
But: What will happen on app update? Are the manifest files overwritten, such that my extras will be removed?
I think this could not be the case, since I read some infos about special permissions for pre-installed apps. If the whole manifest was overwritten on updates, this would not work.
But I don't know how it works for other special informations in the manifest.
Thanks in advance!
The manifest is replaced when you update your app. This is how apps request or remove permissions, and add new Activities and Broadcast Receivers.
Certain pre installed apps get extra permission not only because of the manifest, but because they are installed in a separate folder on the device, which grants them more permissions.
When an app is updated, your manifest file is replaced.
Your primary question already being answered, I'll answer your secondary one. The special manifest permissions for pre-installed applications are managed by the code signing process. A manifest is allowed to use those permissions if and only if it is in a .apk file that's signed by the same key as the system build itself (e.g., if you're installing on a Samsung phone, it would have to be signed by Samsung's key, and so on). So it's actually less about being pre-installed and more about being authorized by the device manufacturer.
Related
Google Play Support keeps Rejecting the last deployment of my App.
Below I'm quoting the reason for the reject:
Issue found: Permission use is not directly related to your app's core
purpose. We found that your app is not compliant with how
REQUEST_INSTALL_PACKAGES permission is allowed to be used.
Specifically, the use of the permission is not directly related to the
core purpose of the app.
Additionally, follow these steps to bring your app into compliance:
Please remove the use of REQUEST_INSTALL_PACKAGES permission from your
app.
After removing an unused package that was using the REQUEST_INSTALL_PACKAGES permission, I tried to re-deploy but I've kept getting the app rejected.
I can confirm that the current list of used permissions does NOT include the REQUEST_INSTALL_PACKAGES.
On play.google.com, I checked the permission lists of the last uploaded versions (see attached screenshot).
I also unpacked the lastly uploaded SDK file (using apktool), and searched "REQUEST_INSTALL_PACKAGES" in the extracted folder; of course, no results were found.
Has anyone any suggestion on how to solve this issue?
The same issue occurred with me. My app's previous versions included this permission but in the latest update, I removed them but still received rejection message via mail. Then I found that in the other track (internal testing track), I had an apk with REQUEST_INSTALL_PACKAGES permission. This was the main cause of rejection of my app update. I observed that the form 'App bundles and APKs using sensitive permissions' was showing the internal track's apk information regarding the use of REQUEST_INSTALL_PACKAGES.
So, I tried to deactivate my previous internal track's apk with the new version (that didn't include any REQUEST_INSTALL_PACKAGE permission). Now when I open my form page 'App bundles and APKs using sensitive permissions' again.
Now, it showed that no app bundle or apk uses this sensitive permission.
Hope that it could solve this issue. I am too waiting for my update to be approved.
First step, Check in your manifest merger file if the specified
sensitive permission is shown. Check in release variant. (Most likely
not, if yes, remove this permission)
Second step, In playstore, Go to app bundles explorer and check if
any of the older app bundles have this permission and is still
active. If yes. you have to provide an update to this track. It is
unfortunate that Google play review email does not mention that issue can
be in an older app bundles or other tracks
Provide an update to playstore.
Note, If you want to forcefully remove this permission (if you do not care
which library is adding it)
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" tools:node="remove"/>
If none of the above works. You have to write them an email and clarify.
I am implementing runtime permissions in my app. I have few questions though to understand them clearly.
Situation:
My application B is a child app of application A
That being said my application resides inside application A as part of it and, whenever needed I can launch it.
Question:
If a user has already granted all the necessary runtime permissions to application A (the parent app), then can the child app i.e. application B carry the same permission grant or it has to ask them again?
Do I need to ask the permissions again if I install a newer version of an app on top of the old? Let's say version 2 to 3.
Technically, yes. If app-A and app-B are two separate apps, they each need their own set of permissions and permission requests.
And no, if a permission was previously allowed, then an installation of a newer version does not reset that permission's state.
However, if you want app-B to retain the same permission states as app-A, you should look into something called android:sharedUserId. If app-A has the same sharedUserId as app-B, then app-B will have the same permission states as app-A, and vice versa.
I couldn't find any posts talking sufficiently about the shared permission states between apps with the same, but you can check out some of these posts for extra notes:
Two app with shared UserID
What is sharedUserId in Android, and how is it used?
https://stackoverflow.com/a/49492023/6668797
https://stackoverflow.com/a/8507761/6668797
I did a quick test myself and can confirm that two apps with the same sharedUserId do share permission states, so go try it yourself. Just setup a sample project/app that checks and requests a permission, clone it, give them the same sharedUserId, install both of them, allow the permission on one, and you'll see it's already in the allowed-state on the other.
I have an app with free and pro versions. The pro version propose a migration assistant to import data from the free to the pro version when a user buy the pro after using the free.
I added a custom permission to protect the free version data. Both versions have the permission declared in their manifest, and only the pro version has the uses-permission.
It works well on pre-Lollipop devices, but on Lollipop, I get a INSTALL_FAILED_DUPLICATE_PERMISSION error message if I try to install the pro version when the free is installed. It works if I sign both versions with the same key (in debug for instance), but I didn't on the Play Store, and it can't be changed.
So, is there any solution, or are the permissions broken on Lollipop ??
is there any solution
In your case, you may be able to get away with Derek Fung's approach, since there is a clear installation order (few, if any, people will install the free app after installing the paid app).
Alternatively, you can skip permissions, since in this case, there are two apps that need to communicate with each other. You know what those apps are, and you know their signing keys. Perform your own validation as part of your IPC work:
Use Binder.getCallingUid() to get the UID of the calling app.
Use PackageManager and its getPackagesForUid() to find the application ID(s) associated with the UID. In your case, there should be just one, and you can confirm that the application ID is the expected value.
Use my SignatureUtils class (or just grab the code for it) to validate that the signing key of the calling application matches the expected value.
are the permissions broken on Lollipop ?
The behavior that you want — any app can define any other app's permission — is dreadful from a security standpoint.
Such "feature" would also prevent creating / using 3rd party content providers, because if your app is installed first, you need to have the permission's declaration
Custom permissions are designed for cases where there is a clear order of installation (e.g., pre-installed apps, host and plugins). Custom permissions are not well-suited for peer scenarios, where the order of installation is not pre-determined.
In some cases, this can be worked around by grafting in plugins where they might ordinarily not be needed:
App A wants to use the provider published by App B, but App A might be installed first
The author of App A creates a plugin (A') that has the <uses-permission> for App B's provider and mediates communication with App B
App A invokes something on A' when A' is installed (e.g., sends a broadcast to a specific component), so A' can validate that App A and App B were installed before A'
When the user tries to do something that involves A talking to B, if the plugin is not installed, lead the user to install the plugin
Clunky, but it should work.
It is likely that you both of your free and paid app has declared permission of the same name like below.
<permission android:name="com.example.permission" android:label="test_permission" android:protectionLevel="dangerous"></permission>
Edit:
For your case, seems you should only declare your permission on your free version. For your paid version, remove the <permission> tag and leave only the <uses-permission> tag
I've just created a very simple Android application that captures an Intent, manipulates it a bit, and sends out a new Intent. I transferred the app to my phone with adb install, and now looking at the app's requested permissions, I'm seeing that it requires permissions I never asked for:
read phone status and identity
modify or delete the contents of your USB storage
test access to protected storage
There's nothing in my manifest file requesting permissions, and the app itself is dead simple (here's the source on GitHub). Are these extra permissions added because I installed it with adb install, perhaps? Or is there something in my app that merits requiring these permissions that I'm just not seeing?
You are missing a <uses-sdk> element with android:minSdkVersion. These permissions were added to Android after its initial release, and apps supporting very old Android devices have these permissions "grandfathered in".
You really should add <uses-sdk> and add android:minSdkVersion, saying how old of an Android device (from an API level standpoint) you are willing to support.
My application define a permission with android:protectionLevel="signature".
<permission android:name="my.app.permission.EXAMPLE" android:protectionLevel="signature" />
My intention is make application modules that can be launched only by my signed app. These application modules have android:permission in its activities.
This works fine. but...
A third-party app can use the same permission name and changed the protection level to normal, like this
<permission android:name="my.app.permission.EXAMPLE" android:protectionLevel="normal" />
If my app is installed first, i can prevent others apps to override the permission. However, if one uninstalls my app and then installs his app it redefines the permission.
Is it possible prevent other application use the same permission name, for example, giving the permission a unique id like application package?
Although the Manifest is encrypted, anyone can read the permission name in log cat when it tries to start the activity that requires this permission (An exception is thrown having the required permission name).
There's no enforcement, only convention. Like the rest of the Java world, it loosely relies on domain name registration infrastructure. The idea is that you prefix your permission name with your public Internet domain name (e. g. com.myawesomecompany.myapp.MYPERMISSION) which you own.
Uniqueness of domain names is enforced by the registrar community, naturally.
Yes, the system is open for abuse.
EDIT: if you're securing a broadcast-based channel, you can add a two-way signature check if you feel like it. Call Context.sendBroadcast() with the permission name as a second parameter.
EDIT2: I feel you're overthinking this while closing your eyes at the bigger Android app security picture. Which is not impressive. Abusing the privilege infrastructure is not how one hacks into an Android app. If I set out to intercept your intents, I won't be putting together a fake intent receiver (activity, service). Instead, I'd connect with a debugger to the genuine receiver in your app, signature and all.
With publicly available tools, it takes minutes to put togther an Eclipse project for a given APK. Load it up into Eclipse, connect to a running process, set breakpoints in relevant system APIs (Android is open source, remember), voila. With a bit of extra effort, you can get decompiled Java sources for an APK and debug in terms of YOUR methods, as opposed to system ones.
copyed from Google Andorid Doc:
Note: The system does not allow multiple packages to declare a permission with the same name, unless all the packages are signed with the same certificate. If a package declares a permission, the system does not permit the user to install other packages with the same permission name, unless those packages are signed with the same certificate as the first package. To avoid naming collisions, we recommend using reverse-domain-style naming for custom permissions, for example com.example.myapp.ENGAGE_HYPERSPACE.
https://developer.android.com/guide/topics/permissions/defining
If you want to prevent other applications from changing your permission level, you can use system predefine permissions which have level "signature". No other regular app can define permission before system.
Use system permission to protect your resource doesn't mean your app have to sign with platform key.
example:
<service
android:name="xxx.xxx.xxx.exservice"
android:permission="android.permission.BROADCAST_PACKAGE_REMOVED" >
The only issue is AppStore would show which permission you use if below code shows in app's manifest.xml
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />
In this example, you can access you resource by the same sign key, but definitely you can't broadcast package remove.