Получение ошибки разрешения java.lang.SecurityException: отказ в разрешении на устройствах Android 3.x при получении имени вложения электронной почты

Я столкнулся с проблемой открытия электронной почты в MYApp, когда я сделал его режим запуска «singleInstance».

Я приложил пример проекта Android, который считывает имя файла из вложения электронной почты и отображает его на экране. Работает нормально в случае onCreate, но выдает ошибку в onNewIntent, когда режим запуска приложений — 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");
    }
}

}

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 на устройстве, откройте любое вложение (офисный документ) для просмотра. 3) Выберите приложение LaunchMode для завершения действия. 4) Приложение LaunchMode отобразит имя файла на экране.

Это отлично работает в первый раз (поток onCreate), но когда это приложение переключается в фоновом режиме, и я снова пытаюсь выполнить 2,3,4 шага... приложение вылетает с ошибкой

E/DatabaseUtils(30615): java.lang.SecurityException: Permission Denial: reading com.google.android.gm.provider.MailProvider uri content://gmail-ls/[email protected]/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) Отлично работает с режимом запуска с одной вершины. 3) Некоторые обновления в приложении Gmail.ссылка здесь:


person tumbudu    schedule 25.02.2012    source источник


Ответы (2)


Вероятно, вы получили разрешение URI на чтение имени файла, когда получили намерение и не используете запрошенные разрешения (READ_GMAIL и WRITE_GMAIL). Разрешение URI действует только до тех пор, пока ваше приложение не finish()es, поэтому при попытке возобновить его у вас не будет.

Это согласуется с вашим опытом — это работает, когда намерение свежее, а не старое. Я думаю, что 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.

person skoke    schedule 30.07.2012

Как сказал skoke, вы больше не можете читать из GMail, если намерение, которое дало ваше разрешение, не является свежим, т. Е. Это должно быть исходное намерение действия. Если ваше намерение исходит от onNewIntent, то оно, вероятно, не удастся.

Мое решение некрасиво, но, похоже, работает. В моем onResume я вызвал пользовательскую функцию, чтобы узнать, могу ли я получить доступ к содержимому Gmail. Если нет, я показывал пользователю сообщение и просил закрыть приложение и повторить попытку. Эй, по крайней мере, он не падает.

person NSouth    schedule 27.11.2014