简体   繁体   English

API 级别 29 Intent.ACTION_GET_CONTENT 从下载文件夹返回错误 ID

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

I am trying to find the full file path for an URI returned from file picker intent.我正在尝试查找从文件选择器意图返回的 URI 的完整文件路径。 I have downloaded an image from internet which was saved in the browser default download folder.我从 Internet 下载了一张图片,该图片保存在浏览器默认下载文件夹中。 The problem is the id returned by DocumentsContract.getDocumentId(content_describer) is like "msf:254" instead of Long type id generally returned.问题是 DocumentsContract.getDocumentId(content_describer) 返回的 id 类似于 "msf:254" 而不是通常返回的 Long 类型的 id。 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? URI 报告为 content://com.android.providers.downloads.documents/document/msf%3A253 知道什么是 msf 吗? I have seen image, video, audo but noticed msf for first time.我看过图像、视频、audo,但第一次注意到 msf。

When you get "msf:xxx" in URI, use below solution:当您在 URI 中获得“msf:xxx”时,请使用以下解决方案:

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.我已经解决了这个问题,它对 msf 100% 有效。 :) :)

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."这里的 TEMP_FILE 值为“temp”。

I found the way from comment section.我从评论部分找到了方法。 Thanks to @blackapps.感谢@blackapps。

 val inputStream = context!!.contentResolver.openInputStream(data.data!!)
 val docFile =File("${activity!!.cacheDir}/doc_${sharedPreferences.getString("applno", "")}.pdf")
 if (!docFile.exists()) {
        docFile.createNewFile()
 }

copyStreamToFile(inputStream,!,docFile) copyStreamToFile(inputStream,!,docFile)

private fun copyStreamToFile(inputStream: InputStream, outputFile: File) {
    inputStream.use { input ->
        val outputStream = FileOutputStream(outputFile)
        outputStream.use { output ->
            val buffer = ByteArray(4 * 1024) // buffer size
            while (true) {
                val byteCount = input.read(buffer)
                if (byteCount < 0) break
                output.write(buffer, 0, byteCount)
            }
            output.flush()
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM