【问题标题】:Android unable to open Gmail attachmentsAndroid 无法打开 Gmail 附件
【发布时间】:2014-09-25 10:36:20
【问题描述】:

我想用我的应用打开 pdf 附件。

我已经设置了意图过滤器

<intent-filter android:label="@string/label" >
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="application/pdf" />
            <data android:mimeType="image/*" />
        </intent-filter>
        <intent-filter android:label="@string/label" >
            <action android:name="android.intent.action.SHARE" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="application/pdf" />
            <data android:mimeType="image/*" />
        </intent-filter>

它在 Android 4.4 设备上运行良好,但在 4.2.2 上我得到以下异常:

java.lang.SecurityException: Permission Denial: opening provider com.google.android.gm.provider.MailProvider from ProcessRecord{2120ac60 21661:com.some.app.package/u0a10113} (pid=21661, uid=10113) requires com.google.android.gm.permission.READ_GMAIL or com.google.android.gm.permission.WRITE_GMAIL

我已尝试添加所有这些权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.android.email.permission.READ_ATTACHMENT"/>
<uses-permission android:name="com.google.android.gm.permission.READ_GMAIL"/>
<uses-permission android:name="com.google.android.gm.permission.READ_CONTENT_PROVIDER"/>

奇怪的是,如果我尝试加载相同的附件,而不是使用 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"/>

还是不行

EDIT2:

这就是我触发异常的方式:

public static byte[] getBytesFromUri(Uri uri, Context appCtx) {

    ByteArrayOutputStream byteBuffer = null;
    InputStream inputStream = null;

    try {
        inputStream = appCtx.getContentResolver().openInputStream(uri); //crash here
        byteBuffer = new ByteArrayOutputStream();
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }
        inputStream.close();
        inputStream=null;
        return byteBuffer.toByteArray();
    } catch (IOException e) {
        log.e(TAG, "error retrieving bytearray from uri "+uri);
        e.printStackTrace();
    }

    return null;
}

EDIT3:

这是我获取文件 uri 的方式:

Uri fileUri = null;
    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        fileUri = intent.getData();
        intent.setData(null);
    } else if (Intent.ACTION_SEND.equals(intent.getAction())) {
        fileUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
        intent.removeExtra(Intent.EXTRA_STREAM);
    }

编辑 4 对于greenapps: 这是uri:

gmail

content://gmail-ls/gmail.account@gmail.com/messages/76/attachments/0.1/BEST/false

电子邮件

 file:///storage/emulated/0/Android/data/com.android.email/cache/test_file.pdf

所以 uris 是不同的,但它们也在 4.4 设备上并且仍然有效

【问题讨论】:

  • 使用 GMail 或 Mail 应用程序的 getBytesFromUri(Uri uri, 中的 uri 是否不同?
  • @greenapps 不,完全一样的逻辑
  • the same logic ?你是什​​么意思?它应该是相同的 uri。
  • 对不起,我看错了,所以是的 uris 是不同的(请参阅我的 EDIT4)
  • com.android.email.permission.ACCESS_PROVIDER

标签: android gmail attachment


【解决方案1】:

使用以下代码: 意图过滤器

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

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="application/octet-stream" />

            <data android:host="*" />
            <data android:scheme="smb" />
            <data android:scheme="http" />
            <data android:scheme="https" />
            <data android:pathPattern=".*\\.pdf" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="application/octet-stream" />

            <data android:host="*" />
            <data android:scheme="smb" />
            <data android:scheme="http" />
            <data android:scheme="https" />
            <data android:mimeType="application/pdf" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="application/octet-stream" />

            <data android:host="*" />
            <data android:scheme="file" />
            <data android:scheme="content" />
            <!-- Workaround to match files in paths with dots in them, like /sdcard/my.folder/test.pdf -->
            <data android:pathPattern=".*\\.pdf" />
            <data android:pathPattern=".*\\..*\\.pdf" />
            <data android:pathPattern=".*\\..*\\..*\\.pdf" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="application/octet-stream" />

            <data android:host="*" />
            <data android:scheme="file" />
            <data android:scheme="content" />
            <data android:mimeType="application/pdf" />
        </intent-filter>

在 Activity 类中,使用 CONTENT RESOLVER

URI 转换为数据
 TextView fileNameTextView;
private File file;

 Intent intent = getIntent();
    InputStream is = null;
    FileOutputStream os = null;
    String fullPath = null;

    try {
        String action = intent.getAction();
        if (!Intent.ACTION_VIEW.equals(action)) {
            return;
        }

        Uri uri = intent.getData();
        String scheme = uri.getScheme();
        String name = null;

        if (scheme.equals("file")) {
            List<String> pathSegments = uri.getPathSegments();
            if (pathSegments.size() > 0) {
                name = pathSegments.get(pathSegments.size() - 1);
            }
        } else if (scheme.equals("content")) {
            Cursor cursor = getContentResolver().query(uri, new String[] {
                    MediaStore.MediaColumns.DISPLAY_NAME
            }, null, null, null);
            cursor.moveToFirst();
            int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
            if (nameIndex >= 0) {
                name = cursor.getString(nameIndex);
            }
        } else {
            return;
        }

        if (name == null) {
            return;
        }

        int n = name.lastIndexOf(".");
        String fileName, fileExt;

        if (n == -1) {
            return;
        } else {
            fileName = name.substring(0, n);
            fileExt = name.substring(n);
          /*  if (!fileExt.equals(".gcsb")) {
                return;
            }*/
        }

        fullPath = ""/* create full path to where the file is to go, including name/ext */;

        String filenm = fileName + fileExt;
        file = new File(getCacheDir(), filenm);



        is = getContentResolver().openInputStream(uri);
        os = new FileOutputStream(file.getPath());

        byte[] buffer = new byte[4096];
        int count;
        while ((count = is.read(buffer)) > 0) {
            os.write(buffer, 0, count);
        }
        os.close();
        is.close();


        fileNameTextView.setText(fullPath);
        pdfView.fromFile(file)
        .enableSwipe(true) // allows to block changing pages using swipe
        .swipeHorizontal(false)
        .enableDoubletap(true)
        .password("123456")
        .defaultPage(0)
        .load();
        Log.e("TAG", "===onfile path: "+file.getAbsolutePath() );
        Log.e("TAG", "===onFile name: "+file.getName() );


    } catch (Exception e) {
        if (is != null) {
            try {
                is.close();
            } catch (Exception e1) {
            }
        }
        if (os != null) {
            try {
                os.close();
            } catch (Exception e1) {
            }
        }
        if (fullPath != null) {
            File f = new File(fullPath);
            f.delete();
        }
    }

【讨论】:

    猜你喜欢
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 2014-10-21
    • 1970-01-01
    相关资源
    最近更新 更多