Permission Denial when using ContentResolver - android

On Android 10,
I am trying to get data from external apps (like file managers, google photo etc) into my app using this guide -
https://developer.android.com/training/sharing/receive
After receiving the intent in my app, I am trying to open an input stream:
InputStream inputStream = new BufferedInputStream(CGlobals.context.getContentResolver().openInputStream(receivedURI));
It works initially from the Activity specified in the manifest, and even after.
However, I get a Permission Denial error in logcat-
Permission Denial: reading com.google.android.libraries.storage.storagelib.FileProvider uri content://com.google.android.apps.nbu.files.provider/2/721 from pid=19038, uid=10264 requires the provider be exported, or grantUriPermission()
when I am trying to get the input stream from other activities or threads in my app.
After trying for some time, I managed to find that this permission problem appears after I finish the initial activity.
What I can guess from this is, the Android system is granting this permission only as long as the initial activity is not finished.
If what I discovered is true, is this normal or a bug?
Thank you very much.

Related

Registering ContentObserver for Android CallLog causes crash

Recently my app keeps crashing when registering a contentObserver for the Android CallLog (in onCreate of a Service). This is the way I register it:
getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, true, new MyObserver(new Handler()));
Part of the stacktrace:
java.lang.RuntimeException: Unable to create service
nl.xelion.restandroid.service.CallLogChanged:
java.lang.SecurityException: Permission Denial: opening provider
com.android.providers.contacts.CallLogProvider from
ProcessRecord{f73a1ed 7949:nl.my.app.debug/u0a119}
(pid=7949, uid=10119) requires android.permission.READ_CALL_LOG or
android.permission.WRITE_CALL_LOG
...
Caused by: java.lang.SecurityException: Permission Denial: opening provider...etc
I used this tutorial, and it DID work for about a year:
http://www.adityathakker.com/android-content-observer-react-on-content-change
Approximately since Android O the crashes started to appear. The javadoc of registerContentObserver does say something along these lines: Starting in O, all content notifications must be backed by a valid ContentProvider. So I was wondering if this would be the problem, and if so, how to solve it?
Anyway, why is it complaining about permissions for contacts, and why didn't this happen before? This doesn't make sense to me.
ps. I do use code which requires permission for contacts, which is called in the onChange of the ContentObserver, but even when I comment this piece of code the crash still occurs.
The problem lies with the update to Android O. Permissions are grouped together and since Android O permission behaviour was changed because of incorrect handling of permission requests.
In my example I had added the permissions READ_CALL_LOG/WRITE_CALL_LOG and CALL_PHONE to the manifest, but requested only CALL_PHONE at first startup of the app. This caused the permission group PHONE to be accepted, but neither of the call-log permissions. So when the registerContentObserver method was called, Android implicitly accepted it to be used because of accepting the group PHONE.
When my user upgraded from N to O, and registerContentObserver was called again, it would crash (justly). Solution: check for the READ_CALL_LOG/WRITE_CALL_LOG permisions before calling registerContentObserver.
Workaround for users on Android O who're still using the old - crashing- code: Manually turn off & on the specific permission in the Android settings of the app (so the PHONE permission group in this case). This causes all permissions in this group to be accepted (or at least those permissions in that group that are required by the app)

Screenshot Notification requiring permission when clicked, but not when using Notification Share action

This looks like a bug (in Marshmallow) but, regardless, it needs to be worked around anyway.
Nexus 6P (6.0.1). Two scenarios:
take a screenshot / click on the notification's Share action / share to your app
An ACTION_SEND intent is delivered to the app and the app is (seemingly) granted permission to grab the image (which is specified in mClipData, not mData)
take a screenshot / click on the notification itself / share to your app
An ACTION_VIEW intent is delivered to the app, but the app does not have permission (unless already granted READ_EXTERNAL_STORAGE) because attempting to grab the image (which is specified in mData, not mClipData) gives:
Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/1234 from pid=12345, uid=23456 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
Is there a way to work around this issue without resorting to the app itself requesting READ_EXTERNAL_STORAGE permission?
Yes if you open the image from the activity, not from the source/directory file. Or if you want to open from the source you need to add the READ_EXTERNAL_STORAGE to the android manifest.

Why do I have to call the other app before using grantUriPermission?

I'm little bit puzzled about grantUriPermission function. I'd like to use it to grant file access to another application via a FileProvider. Since FileProvider must be local (non-exported) for good reason, I must grant the other app temporary read/write permission. Documentation says:
Normally you should use Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION with the Intent being used to
start an activity instead of this function directly. If you use this
function directly, you should be sure to call revokeUriPermission(Uri,
int) when the target should no longer be allowed to access it.
Fair enough, since I don't need to open an activity nor explicitly start a service (the other app would just ask for that file when its time comes), I though I'm fine with just plain:
Uri newFileUri = FileProvider.getUriForFile(this, AUTHORITY, file);
grantUriPermission(OTHER_APP_PACKAGE_NAME, newFileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
To my surprise, I was still getting the security exception:
java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{42ee0b98 5878:example.com.myapplication3/u0a82} (pid=5878, uid=10082) that is not exported from uid 10081
After few experiments I found out that I must call the other app via an Intent at least once:
Intent intent = new Intent();
intent.setClassName(OTHER_APP_PACKAGE_NAME, OTHER_APP_SERVICE_NAME);
startService(intent);
As soon as I do this, I can do everything as expected -- I can remove this intent code, I can even reinstall both apps and it still works (!). It seems like there's a hidden requirement that the owner must call the other app at least once and its stored somewhere in the system.
Is this documented somewhere?
EDITED: first I thought I have to use Intent.FLAG_GRANT_READ_URI_PERMISSION flag, too but this seems to be not necessary.

Why does launchMode:singleTask cause SecurityExceptions when opening Intents?

I've recently set my Android app up to receive Intents so it can be used to open attachments from email apps.
This works fine when my app is not already running when the Intent is created, but when my app is paused in the background, attempting to read the content from the URI causes SecurityExceptions to be thrown:
E/AndroidRuntime(28250): java.lang.RuntimeException: Unable to resume activity
{com.[...]/com.[...].Main}: java.lang.SecurityException: Permission Denial:
reading com.google.android.gm.provider.MailProvider uri content://gmail-ls/
notateme#gmail.com/messages/134/attachments/0.1/BEST/false from pid=28250,
uid=10205 requires com.google.android.gm.permission.READ_GMAIL, or
grantUriPermission()
E/AndroidRuntime(28250): Caused by: java.lang.SecurityException: Permission
Denial: reading com.google.android.gm.provider.MailProvider uri content://
gmail-ls/notateme#gmail.com/messages/134/attachments/0.1/BEST/false from
pid=28250, uid=10205 requires com.google.android.gm.permission.READ_GMAIL,
or grantUriPermission()
This web post suggests that the problem is that my activity has android:launchMode="singleTask" set, and that the way to solve the problem is to create an intermediary Activity to handle the Intent.
That fix does indeed work for me, but I'd like to understand why my original Activity appeared to have the permission to read from the URI when it was created to handle the Intent, but not when it was resumed to handle the Intent.
Could anyone explain this for me?
You need to add READ_GMAIL permission in manifest.
<uses-permission android:name="com.google.android.gm.permission.READ_GMAIL" />
Refer this Manifest Permissions

Start Activity From Wallpaper Service (not preference related...)

I have a live Wallpaper. This live wallpaper has a settings page implemented from PreferenceActivity. Everything works as expected. So far, so good.
From my Wallpaper Settings page..I want to start another activity (a details activity...with info, bitmaps, links, etc...). When I start this activity I get a security exception error:
java.lang.SecurityException: Permission Denial: starting Intent {... } from ProcessRecord ... requires android.permission.BIND_WALLPAPER
The manifest has the required permission. I've tried putting this permission everywhere .. even in multiple locations (not just in the service tag in the manifest). I'm starting the Activity from the wallpaper settings page with a new intent, then calling startActivity.
Does anyone know why I'm getting the permission denial even when the permission is included? Can someone tell me how to start the activity correctly without getting a force close?
Much appreciated.

Categories

Resources