7

In our application we need to read attachments from email clients and upload it to server. For default android email client everything works fine,but for gmail application facing

java.lang.SecurityException: Permission Denial: opening provider   com.google.android.gm.provider.MailProvider from ProcessRecord (pid=11298, uid=10068) requires com.google.android.gm.permission.READ_GMAIL or com.google.android.gm.permission.WRITE_GMAIL

Have even tried giving Gmail read write permissions but did not work.

Observations are

It is working fine for Nexus but for samsung devices 4.2 and 4.1,working fine initially if activity is created for first time,but if activity is in background throwing above said exceptions.

Trying to get attachment file name using below code.

    Cursor cursor = getContentResolver().query(openIntent.getData(),
            new String[] { MediaStore.MediaColumns.DISPLAY_NAME }, null,
            null, null);

    cursor.moveToFirst();
    int nameIndex = cursor
            .getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
    if (nameIndex >= 0) {
        NCUtil.clickedImageTitle = cursor.getString(nameIndex);
        path = cursor.getString(nameIndex);
    }
    cursor.close();

My Manifest file

        <activity
        android:name="com.ncomputing.vspacemobile.NCMainActivity"
        android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
        android:excludeFromRecents="true"
        android:launchMode="singleTask"
        android:screenOrientation="sensorPortait"
        android:theme="@android:style/Theme.NoTitleBar"
        android:windowSoftInputMode="adjustPan" >

        <!-- For email attachments -->
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />

            <data android:mimeType="application/pdf" />
            <data android:mimeType="application/msword" />
            <data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
            <data android:mimeType="application/vnd.ms-excel" />
            <data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
            <data android:mimeType="application/vnd.ms-powerpoint" />
            <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
            <data android:mimeType="text/plain" />
            <data android:mimeType="text/comma-separated-values" />
            <data android:mimeType="application/rtf" />
        </intent-filter>
    </activity>

User permissions

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

Please let us know how can i make it work,i need the activity launch mode as singleTask and access the attachments.

Remmyabhavan
  • 1,689
  • 5
  • 36
  • 65
  • See this answer: http://stackoverflow.com/a/11724114/1110183 – Alex van den Hoogen Apr 01 '14 at 12:02
  • Have seen the link and tried uri permission check.Its always returning permission denied when the activity is in background.If the permission was granted for that particular attahment oncreate of the activity,it works fine.But if we are trying to open an attachment for the first time when the activity is in background throws permission denial exception. – Remmyabhavan Apr 01 '14 at 12:15
  • Try adding permissions at run time rather than through the manifest file. May be this can ease out the situation for you. – Parth Kapoor Apr 08 '14 at 10:30

3 Answers3

5

The intent filter requires both content and file scheme types, with the mimetype application/octetstream

<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="file" android:pathPattern=".*\\.inform" android:mimeType="application/octet-stream"/>
<data android:scheme="content" android:pathPattern=".*\\.inform" android:mimeType="application/octet-stream"/>

as per the Android documentation, "If a scheme is not specified for the intent filter, all the other URI attributes are ignored." With the scheme and URI attributes removed, the only other way to filter the intents is using Mime type, and we all know that custom file extensions do not have registered mime types.

For reference, URI are of the form:

scheme://host:port/path
pathPrefix
pathPattern

So without a scheme, all of that drops. After discovering the above, I tried the obvious -- use a " * " for the scheme, and even tried " .* ". Neither of those worked. I hope someone else can build off my trials. But I believe it has to do with selecting the correct scheme. Unfortunately, the only schemes I know of are http https content and file, and none of the above are the magic bullet.

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/*" host="*" android:pathPattern=".*.ext" android:scheme="content" />
</intent-filter>

This intent will cause gmail to display the Download / Preview buttons. In fact, this will also cause your app to open when .ext files are sent as attachments to the regular email client as well.

Source:

Android get attached filename from gmail app Intent filter to download attachment from gmail apps on Android

Community
  • 1
  • 1
Hassaan Rabbani
  • 2,469
  • 5
  • 30
  • 55
3

Android's ActivityManager automatically clears per-URI permissions when the task of the called application is finished. As per-URI permission are typically granted by setting Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, the task is cleared when it goes in the background (so that you don't open the attachment viewer if start Gmail again from the launcher). See docs for details.

This is by design and there is no way to 'make it work'. You have to build your app to place nicely with this permission granting scheme. You could read the whole attachment when the app is started, dump to a temporary file/DB and continue uploading in the background by using a service.

Not sure what app you are building, but generally an app that uploads your attachments to a third-party's server sounds like a terrible idea from a privacy and security standpoint.

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
  • If that is the case how come it is working in Nexus 4.3 and Nexus 4.4.I would like to display the content of the attachment in my application as a viewer.I cannot read the whole attachment as i would have no idea as which gmail attachment the user would like to read.My activity is singleTask and i would like to have only one instance of it.Is there any way that i can achieve this. – Remmyabhavan Apr 02 '14 at 04:45
  • Not clear what is and what is not working? Maybe behaviour changed in 4.3 and 4.4, but the general rule is the same. Also not sure why going in the background is a problem, if this is a viewer app? Generally, the user will tap an attachment, they will be presented with a list of viewer apps, if they select your app, you will get an intent with the data and temporary permission to read it. Why do you need single task? It doesn't make much sense for a viewer. – Nikolay Elenkov Apr 02 '14 at 05:55
0

To read email attachments you need these permissions......

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.email.permission.READ_ATTACHMENT" />

Notes: READ_EXTERNAL_STORAGE is assumed from WRITE_EXTERNAL_STORAGE but it is best to add it as best practice. INTERNET: App might be pulling from a provider that needs the internet because this is email.

Tip: Keep your code clean an easy by making a separate class for each mime type.

    <activity
        android:name=".KmlReader"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:label="@string/title_activity_map"
        android:parentActivityName="com.gosylvester.bestrides.ImageTextListViewActivity"
        android:theme="@style/Theme.AppCompat" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.gosylvester.bestrides.ImageTextListViewActivity" />

        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.DEFAULT" />

            <data android:mimeType="application/vnd.google-earth.kml+xml" />
        </intent-filter>
    </activity>
Harshit Rathi
  • 1,862
  • 2
  • 18
  • 25
danny117
  • 5,581
  • 1
  • 26
  • 35