Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

API level 29 Intent.ACTION_GET_CONTENT returning wrong id from downloads folder

Tags:

android

I am trying to find the full file path for an URI returned from file picker intent. I have downloaded an image from internet which was saved in the browser default download folder. The problem is the id returned by DocumentsContract.getDocumentId(content_describer) is like "msf:254" instead of Long type id generally returned. The code is as following

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 101 && resultCode == Activity.RESULT_OK) {
        Uri content_describer = data.getData();
        String src = content_describer.getPath();
        try {
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());
            imgView.setImageBitmap(bitmap);
        }catch(Exception e){

        }

        Log.e("selected file", content_describer.toString());
        String filename = content_describer.getLastPathSegment();
        Log.e("selected path", filename);
        Log.e("authority",content_describer.getAuthority());


        if (content_describer.getAuthority().equals("com.android.externalstorage.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            final String[] split = docId.split(":");
            final String type = split[0];
            Log.e("npath", "getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);
            if ("primary".equalsIgnoreCase(type)) {
                if (split.length > 1) {
                    Log.e("nnpath1", Environment.getExternalStorageDirectory() + "/" + split[1]);
                    curFile = Environment.getExternalStorageDirectory() + "/" + split[1];
                } else {
                    Log.e("nnpath2", Environment.getExternalStorageDirectory() + "/");
                }
                // This is for checking SD Card
            } else {
                Log.e("nnpath3", "storage" + "/" + docId.replace(":", "/"));
                curFile = "storage" + "/" + docId.replace(":", "/");
            }
        }

        if (content_describer.getAuthority().equals("com.android.providers.downloads.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            Log.e("docid",docId);

            Uri ci = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));

            final String column = "_data";
            final String[] projection = {
                    column
            };
            Cursor cursor10 = getActivity().getApplicationContext().getContentResolver().query(ci, projection, null, null,
                    null);
            if (cursor10 != null && cursor10.moveToFirst()) {


                final int column_index = cursor10.getColumnIndexOrThrow(column);
                Log.e("imgpp", cursor10.getString(column_index));
                Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
                File fn = new File(cursor10.getString(column_index));
                Log.e("imgpp3", fn.getPath());
                curFile = fn.getPath();
            }
        }

        if (content_describer.getAuthority().equals("com.android.providers.media.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            Log.e("docid", docId);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{
                    split[1]
            };

            final String column = "_data";
            final String[] projection = {
                    column
            };
            Cursor cursor1 = getActivity().getApplicationContext().getContentResolver().query(contentUri, projection, selection, selectionArgs,
                    null);
            if (cursor1 != null && cursor1.moveToFirst()) {


                final int column_index = cursor1.getColumnIndexOrThrow(column);
                Log.e("imgpp", cursor1.getString(column_index));
                Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
                File fn = new File(cursor1.getString(column_index));
                Log.e("imgpp3", fn.getPath());
                curFile = fn.getPath();
            }
        }

        Log.e("final path",curFile);


    }
}

Please note if I pick the same image going via Image->Downwnload, the above code works normally but when same file is picked from Downloads folder, following error is thrown

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.flexi.app.android, PID: 15414
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196709, result=-1, data=Intent { dat=content://com.android.providers.downloads.documents/document/msf:253 flg=0x1 }} to activity {com.flexi.app.android/com.flexi.app.android.ProfileActivity}: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4830)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4871)
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2009)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7319)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
 Caused by: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
    at android.content.ContentResolver.query(ContentResolver.java:934)
    at android.content.ContentResolver.query(ContentResolver.java:872)
    at android.content.ContentResolver.query(ContentResolver.java:830)
    at com.flexi.app.android.fragments.ProfileImageFragment.onActivityResult(ProfileImageFragment.java:171)
    at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
    at com.flexi.app.android.ProfileActivity.onActivityResult(ProfileActivity.java:28)
    at android.app.Activity.dispatchActivityResult(Activity.java:8091)

The URI is reported as content://com.android.providers.downloads.documents/document/msf%3A253 Any idea what is msf? I have seen image, video, audo but noticed msf for first time.

like image 938
Vivek Khurana Avatar asked Oct 15 '22 09:10

Vivek Khurana


1 Answers

When you get "msf:xxx" in URI, use below solution:

if (id != null && id.startsWith("msf:")) {
                    final File file = new File(mContext.getCacheDir(), Constant.TEMP_FILE + Objects.requireNonNull(mContext.getContentResolver().getType(imageUri)).split("/")[1]);
                    try (final InputStream inputStream = mContext.getContentResolver().openInputStream(imageUri); OutputStream output = new FileOutputStream(file)) {
                        final byte[] buffer = new byte[4 * 1024]; // or other buffer size
                        int read;

                        while ((read = inputStream.read(buffer)) != -1) {
                            output.write(buffer, 0, read);
                        }

                        output.flush();
                        return file;
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    return null;
                }

I have fixed this issue and it's working 100% for msf. :)

Also Delete the temp file after the completion of your work:

private void deleteTempFile() {
        final File[] files = requireContext().getCacheDir().listFiles();
        if (files != null) {
            for (final File file : files) {
                if (file.getName().contains(Constant.TEMP_FILE)) {
                    file.delete();
                }
            }
        }
    }

Here TEMP_FILE value is "temp."

like image 133
SANAT Avatar answered Oct 29 '22 22:10

SANAT