Ошибка получения разрешения java.lang.SecurityException: отказ в разрешении на устройствах Android 3.x при получении имени вложения электронной почты - PullRequest
10 голосов
/ 25 февраля 2012

Я столкнулся с проблемой при открытии электронной почты в 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");
    }
}

}

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>

Шаги для воспроизведения 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/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

Мне нужно исправить это, так как мне нужно иметь один экземпляр Application и также получить имя вложения электронной почты. Пожалуйста, дайте мне знать, если я что-то здесь упускаю.

Мой вопрос здесь - почему он работает в потоке onCreate, и он не будет работать в случае onNewIntent

Примечание: 1) Отлично работает с 2.x телефонами 2) Отлично работает с режимом запуска Single top. 3) Некоторые обновления в приложении Gmail. ссылка здесь:

Ответы [ 2 ]

5 голосов
/ 30 июля 2012

Вы, вероятно, получили 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.

0 голосов
/ 27 ноября 2014

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...