获取邮件附件名称时,在3.x Android设备上出现java.lang.SecurityException:Permission Denial错误

11

当我将应用程序的启动模式设置为“singleInstance”时,我在MYApp中打开电子邮件时遇到了问题。

我附加了一个示例Android项目,该项目从电子邮件附件中读取文件名并将其显示在屏幕上。在onCreate的情况下运行正常,但是当应用程序的启动模式为singleInstance时,在onNewIntent中会抛出错误。

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

// 这是 Android 应用程序中的一个文件名,通常用来声明应用程序的组件、权限和元数据信息。
<?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>

重现步骤: 1)在设备上安装apk。 2)进入设备上的gmail原生应用程序,打开任何附件(office文档)进行查看。 3)选择LaunchMode应用程序以完成操作。 4)LaunchMode应用程序将在屏幕上显示文件名。

第一次(onCreate流程)这样做是没问题的,但是当该应用程序切换到后台并再次尝试第二步、第三步和第四步时,应用程序会崩溃并出现错误。

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

我需要修复这个问题,我需要一个应用程序的单个实例并且还需要获取电子邮件附件名称。 如果我漏掉了什么,请告诉我。

我的问题是为什么它在onCreate流程中运行良好,而在onNewIntent流程中无法正常工作。

注意: 1)在2.x手机上运行良好 2)在Single top启动模式下运行良好。 3)Gmail应用程序有一些更新。链接在此处:

2个回答

5
当你收到意图并且没有使用你请求的权限(READ_GMAILWRITE_GMAIL)时,你可能会得到一个URI许可来读取文件名。URI许可仅在应用程序结束之前有效,因此在尝试恢复时您将无法获得它。
这与您的经验一致 - 当意图是新鲜的时候它能够工作,但旧的则不行。我认为WRITE_GMAIL是一个签名权限,而READ_GMAIL也可能是。在这种情况下,你所能做的就不多了。READ_ATTACHMENT可能是你请求的更合适的权限。
关于URI许可的更多信息:http://developer.android.com/guide/topics/security/permissions.html#uri 尝试从你的清单中删除uses-permission标签,并查看是否有相同的体验。你还可以尝试检查接收到的intent的标志。
checkCallingOrSelfUriPermission(documentUri , Intent.FLAG_GRANT_READ_URI_PERMISSION)

如果您收到返回值为0,则表示您一直在使用URI权限。

0

就像skoke所说的那样,如果授权的意图不是新鲜的,即必须是原始的活动意图,那么您将无法从GMail中读取。 如果您的意图来自onNewIntent,那么它可能不会成功。

我的解决方案并不美观,但似乎有效。在我的onResume中,我调用了一个自定义函数来查看是否可以访问Gmail内容。 如果不能,我会向用户显示一条消息,并要求他们关闭应用程序并重试。 嘿,至少它不会崩溃。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接