Why does launchMode:singleTask cause SecurityExceptions when opening Intents? - android

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

Related

Permission Denial when using ContentResolver

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.

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)

Pass Uri through from ACTION_GET_CONTENT through activity to service

I have a simple app that allows a user to upload data to my service. The user specifies one or more files by a initiating an ACTION_GET_CONTENT or ACTION_IMAGE_CAPTURE, or by receiving a ACTION_SEND. The Uri(s) from getParcleableExtra or getParcleableArrayListExtra are added to an array in UploadActivity, where the get/capture/send intents are received. Some of the Uris are opened with ContentResolver.openInputStream(Uri), or various Cursors to get metadata. This succeeds without any errors. When the user wants to upload the files, the Uris are added to a intent that starts UploadService with putParcleableArrayListExtra. Then startService and finish() are called, closing the activity. UploadService is a IntentService which uploads the files over HTTP. All Uris are opened with Cursors querying their size for the progress bar. They are then, in serial, opened with openInputStream again, then uploaded to the server.
This works perfectly with only 1 Uri. If I have more than 1 Uri, openInputStream throws a SecurityException:
java.lang.SecurityException: Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/document/primary%3Aempty.txt from pid=6062, uid=10300 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1627)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146)
at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:692)
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1111)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:948)
at android.content.ContentResolver.openInputStream(ContentResolver.java:668)
at tk.mii8303.yumeko.YetAnotherURI$OtherURI.Open(YetAnotherURI.java:73)
at tk.mii8303.yumeko.UploadService.onHandleIntent(UploadService.java:119)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.os.HandlerThread.run(HandlerThread.java:61)
I don't see why I should need MANAGE_DOCUMENTS if I already have called the same method on the file earlier in my app and had it succeed.
I have tried calling
takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
grantUriPermission("tk.mii8303.yumeko.UploadService", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
on each Uri before putting them in the intent to no avail.
How do I pass Uris and their permissions to my service?

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.

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