为什么我对位于 /data/user_de/ 的文件的权限被拒绝

Why I have Permission denied on a file located in /data/user_de/

我想获取彩信的附件内容,如图片或Video/audio。 首先我做这个

static void getMmsContent(Context context, ArrayList<Mms> mmsArrayList) {
        try {
            for (Mms unMms : mmsArrayList) {

                ContentResolver contentResolver = context.getContentResolver();
                Uri uri = Uri.parse("content://mms/part");
                String selection = Telephony.Mms.Part.MSG_ID + "=" + unMms.getId();

                Cursor query = contentResolver.query(uri, null, selection, null, null);

                if (query != null && query.moveToFirst()) {
                    do {
                        String name = query.getString(query.getColumnIndex("name"));
                        String type = query.getString(query.getColumnIndex("ct"));
                        String txt = query.getString(query.getColumnIndex(Telephony.Mms.Part.TEXT));
                        String data = query.getString(query.getColumnIndex(Telephony.Mms.Part._DATA));

                        if (!type.equals("application/smil")) {
                            String[] dataMms = {name, type, txt, data};
                            getContent(context, dataMms, unMms);
                        }
                    } while (query.moveToNext());
                }
                if (query != null) {
                    query.close();
                }
            }
        } catch (Exception e) {
            Log.d("Exception", e.toString());
        }
    }

这一行给出了附加内容所在位置的路径。

String data = query.getString(query.getColumnIndex(Telephony.Mms.Part._DATA));

/data/user_de/0/com.android.providers.telephony/app_parts/PART_1555841710097_Screenshot_20190421-121445_Chrome1.jpg

所以现在我想将图像转换为位图以将其添加到 zip 文件中。

static private void getContent(Context context, String[] dataMms, Mms unMms){
        if (dataMms[1].equals("text/plain")) {
            unMms.setCorps(dataMms[2]);
        } else {
            if ("image/jpeg".equals(dataMms[1]) || "image/bmp".equals(dataMms[1]) ||
                    "image/gif".equals(dataMms[1]) || "image/jpg".equals(dataMms[1]) ||
                    "image/png".equals(dataMms[1])) {
                unMms.setTypeContenu(dataMms[1]);

                Bitmap bitmap = null;
                InputStream is = null;
                try {
                    File source = new File(dataMms[3]);
                    is = new FileInputStream(source);
                    bitmap = BitmapFactory.decodeStream(is);
                } catch (IOException e) {
                    Log.d("Exception", e.toString());
                } finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            Log.d("Exception", e.toString());
                        }
                    }
                }
                if (bitmap != null) {
                    File file = new File(context.getApplicationInfo().dataDir + "/files/", dataMms[0]);
                    OutputStream Fout = null;
                    try {
                        Fout = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, Fout);
                        Fout.flush();
                        Fout.close();
                    } catch (FileNotFoundException e) {
                        Log.d("Exception", e.toString());
                    } catch (IOException e) {
                        Log.d("Exception", e.toString());
                    }

                }
            }
        }
    }

但是我的代码在 new FileInputStream(source) 上抛出异常;

我知道了

D/Exception: java.io.FileNotFoundException: /data/user_de/0/com.android.providers.telephony/app_parts/PART_1547316880687_Resized_20190112_191438_9422.jpeg (Permission denied)

我有权限,我需要用户权限。

<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

所以我在 CommonsWare 的评论之后更改了我的代码:

static private void getContent(Context context, String[] dataMms, Mms unMms) {
        if (dataMms[1].equals("text/plain")) {
            unMms.setCorps(dataMms[2]);
        } else {
            if ("image/jpeg".equals(dataMms[1]) || "image/bmp".equals(dataMms[1]) ||
                    "image/gif".equals(dataMms[1]) || "image/jpg".equals(dataMms[1]) ||
                    "image/png".equals(dataMms[1])) {
                unMms.setTypeContenu(dataMms[1]);
                Uri partURI = Uri.parse("content://mms/part/" + dataMms[4]);
                InputStream is = null;
                Bitmap bitmap = null;
                try {
                    is = context.getContentResolver().openInputStream(partURI);
                    bitmap = BitmapFactory.decodeStream(is);
                } catch (IOException e) {
                    Log.d("Exception", e.toString());
                } finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            Log.d("Exception", e.toString());
                        }
                    }
                }
                if (bitmap != null) {
                    File file = new File(context.getApplicationInfo().dataDir + "/files/", dataMms[0]);
                    OutputStream Fout = null;
                    try {
                        file.createNewFile();
                        Fout = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, Fout);
                        Fout.flush();
                        Fout.close();
                    } catch (FileNotFoundException e) {
                        Log.d("Exception", e.toString());
                    } catch (IOException e) {
                        Log.d("Exception", e.toString());
                    }
                }
            }
        }
    }

棘手的部分是:

Uri partURI = Uri.parse("content://mms/part/" + dataMms[4]);

我的 dataMms[4] 是 MMS 部分的 ID,我从放在 getMmsContent() 的这一行得到它:

String id = query.getString(query.getColumnIndex("_id"));

此列提供部件的 ID。

但是 Android 开发者文档中没有提及此专栏:https://developer.android.com/reference/android/provider/Telephony.Mms.Part.html

所以我在 getMmsContent() 中列出了包含此代码的列,我找到了它:

for (int i = 0; i < query.getColumnCount(); i++) {
    Log.i("Column", query.getColumnName(i)); 
    }

现在可以使用了!