Search code examples
javaandroidandroid-permissionspermission-deniedmms

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


I want to get the attached content of MMS like Image or Video/audio. First I make this

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());
        }
    }

This line give me the path to the location of the attached content.

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

So now i want to transform the image to a Bitmap to add it to a zip file.

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());
                    }

                }
            }
        }
    }

But my code Throw a Exception on new FileInputStream(source);

I got this

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

I have the permissions and i have require the user permission.

<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"/>

Solution

  • So i change my code after the comment of CommonsWare to this :

    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());
                        }
                    }
                }
            }
        }
    

    The tricky part is this :

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

    my dataMms[4] is the id of the MMS Part, I get it from this line I put on getMmsContent() :

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

    This column give me the id of the part.

    But there is no mention about this column in Android Developer documentation : https://developer.android.com/reference/android/provider/Telephony.Mms.Part.html

    So I listed the columns with this code in getMmsContent() and I found it :

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

    Now It's working !