Getting Permission error java.lang.SecurityExcepti

2020-03-11 06:31发布

问题:

I am facing issue in opening Email in MYApp when I made its launch mode to "singleInstance".

I have attached sample Android project which reads file name from email attachment and displays it on screen. Works fine in case of onCreate but throws error in onNewIntent when apps launch mode is singleInstance.

Launchmode.java

package your.namespace.launchmode;


public class LaunchModeActivity extends Activity {
    private static final int OPEN_ACT = 2;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    String name = getAttachmetName(getIntent());
    if(null != name)
    {
        TextView textv = (TextView) findViewById(R.id.attachmentnm);
        textv.setText(name);
    }
}

@Override
protected void onNewIntent(Intent savedInstanceState)
{
    super.onNewIntent(savedInstanceState);
    String name = getAttachmetName(savedInstanceState);
    if(null != name)
    {
        TextView textv = (TextView) findViewById(R.id.attachmentnm);
        textv.setText(name);
    }
}


private String getAttachmetName(Intent intent) {
    final Uri documentUri = intent.getData();
    if(null != documentUri){
    final String uriString = documentUri.toString();
    String documentFilename = null;


    final int mailIndexPos = uriString.lastIndexOf("/attachments");
    if (mailIndexPos != -1) {
        final Uri curi = documentUri;
        final String [] projection = new String[] {OpenableColumns.DISPLAY_NAME};
        final Cursor cursor = getApplicationContext().getContentResolver().query(curi, projection, null, null, null);
        if (cursor != null) {
            final int attIdx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
            if (attIdx != -1) {
                cursor.moveToFirst();
                documentFilename = cursor.getString(attIdx);                
            }
            cursor.close();
        }
    }
    return documentFilename;
    }
    return null;
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);

    if((resultCode == RESULT_OK) && (requestCode == OPEN_ACT))
    {
        Log.d("LaunchMode", "Second activity returned");
    }
}

}

AndroidManifest

<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="your.namespace.launchmode"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-permission android:name="com.google.android.gm.permission.READ_GMAIL"/>
    <uses-permission android:name="com.google.android.gm.permission.WRITE_GMAIL"/>
    <uses-permission android:name="com.google.android.providers.gmail.permission.READ_GMAIL"/>
    <uses-permission android:name="com.google.android.providers.gmail.permission.WRITE_GMAIL"/>
    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:launchMode="singleInstance"
            android:name=".LaunchModeActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter >
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <!-- docx -->
                <data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
                <!-- xlsx -->
                <data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
                <!-- pptx -->
                <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
                <data android:mimeType="application/vnd.ms-excel" />
                <data android:mimeType="application/msword" />
                <data android:mimeType="application/vnd.ms-powerpoint" />
                <data android:mimeType="text/plain" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Steps to reproduce 1)Install apk on device. 2)Go to gmail native app on device, open any attachment(office document) to view. 3)Choose LaunchMode app to complete action. 4)LaunchMode app will display file name on screen.

This works fine for first time (onCreate flow) but when this app is switch in background and again I try 2,3,4 steps.. app crashes with error

E/DatabaseUtils(30615): java.lang.SecurityException: Permission Denial: reading com.google.android.gm.provider.MailProvider uri content://gmail-ls/qoconnect@gmail.com/messages/5/attachments/0.2/BEST/false from pid=32657, uid=10058 requires com.google.android.gm.permission.READ_GMAIL
E/DatabaseUtils(30615):     at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:309)
E/DatabaseUtils(30615):     at android.content.ContentProvider$Transport.bulkQuery(ContentProvider.java:178)
E/DatabaseUtils(30615):     at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:111)
E/DatabaseUtils(30615):     at android.os.Binder.execTransact(Binder.java:339)
E/DatabaseUtils(30615):     at dalvik.system.NativeStart.run(Native Method)
D/AndroidRuntime(32657): Shutting down VM

I need to fix this as, I need to have single instance of Application and should get email attachment name too. Please let me know If I am missing something here.

My question here is why it work in flow of onCreate and it wont work in case of onNewIntent

Note: 1)Works fine with 2.x phones 2) Works fine with Single top launch mode. 3) Some updates on Gmail app.link here:

回答1:

You likely got a URI permission to read the file name when you received the intent and aren't using the permissions that you requested (READ_GMAIL and WRITE_GMAIL). The URI permission is valid only until your application finish()es, so you won't have it when you try to resume.

That's consistent with your experiences - it works when the intent is fresh, but not old ones. I think that WRITE_GMAIL is a signature permission and I am guessing that READ_GMAIL is as well. In that case, there is not much you can do. READ_ATTACHMENT might be a more appropriate permission for you to request.

More on URI permissions: http://developer.android.com/guide/topics/security/permissions.html#uri

Try removing the uses-permission tags from your manifest and see if you have the same experience. You can also try to examine the intent when you receive it by checking its flags.

checkCallingOrSelfUriPermission(documentUri , Intent.FLAG_GRANT_READ_URI_PERMISSION)

If you get 0 returned, you have been using URI permissions.



回答2:

Like skoke said, you can no longer read from GMail if the intent that gave your permission is not fresh, i.e., it must be the original activity intent. If your intent is from onNewIntent then it probably won't succeed.

My solution isn't beautiful but seems to be working. In my onResume I called a custom function to see if I could access the Gmail content. If not, I showed the user a message and asked them to close the app and try again. Hey, at least it doesn't crash.