簡體   English   中英

API 級別 29 Intent.ACTION_GET_CONTENT 從下載文件夾返回錯誤 ID

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

我正在嘗試查找從文件選擇器意圖返回的 URI 的完整文件路徑。 我從 Internet 下載了一張圖片,該圖片保存在瀏覽器默認下載文件夾中。 問題是 DocumentsContract.getDocumentId(content_describer) 返回的 id 類似於 "msf:254" 而不是通常返回的 Long 類型的 id。 代碼如下

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


    }
}

請注意,如果我通過圖像->下載選擇相同的圖像,上面的代碼可以正常工作,但是當從下載文件夾中選擇相同的文件時,會拋出以下錯誤

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)

URI 報告為 content://com.android.providers.downloads.documents/document/msf%3A253 知道什么是 msf 嗎? 我看過圖像、視頻、audo,但第一次注意到 msf。

當您在 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;
                }

我已經解決了這個問題,它對 msf 100% 有效。 :)

完成工作后還要刪除臨時文件:

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

這里的 TEMP_FILE 值為“temp”。

我從評論部分找到了方法。 感謝@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)

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