How to read a file directly from external download directory on Android 10 (Q)

徘徊边缘 提交于 2020-08-08 09:35:09

问题


I am trying to read a file from the download folder on Android Q by doing this:

        File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        File f = new File(downloadDir, "some-existing-file");
        if(!f.exists()) {
            throw new IllegalStateException();
        }

        Uri furi = Uri.fromFile(f);
        try {
            ParcelFileDescriptor des = getContentResolver().openFileDescriptor(
                    furi, "r", null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

I also set android:requestLegacyExternalStorage="true" in the manifest, and requested WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE runtime permissions.

The file exists but when trying to open the file descriptor, an exception arises: java.io.FileNotFoundException: open failed: EACCES (Permission denied).

I read the changes made in Android Q storage, but could not figure out how can I just read the file without having user interaction.

Thanks!


回答1:


From Android 6 (Marshmallow) some of critical permissions should be granted at runtime by the user so he/she will know what things can your app access.
this link is all what you need

EDIT
add these to manifest

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


then add this code to your oncreate method

if (android.os.Build.VERSION.SDK_INT >= 23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
                PackageManager.PERMISSION_GRANTED)) {
            ActivityCompat.requestPermissions(
                    this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    2000);
        }


this will popup the user a dialog to agree permissions. if the user agrees onRequestPermissionsResult method will be called, so override onRequestPermissionsResult like this

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && requestCode == 2000) {
        //do what you want with files
    }
}


just pay attention that I set request code to 2000. it's optional.




回答2:


This method was deprecated in API level 29. To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

Copied from Android documents.docs




回答3:


After too many hours of trying to figure out what the hell is going on, I managed to find a solution.

I addded to the manifest:

android:requestLegacyExternalStorage="true"

When rebuilding and reinstalling directly from Android Studio, the build system or android runtime does not register a change in the manifest, and the request for requestLegacyExternalStorage does not register.

I fixed it by completely uninstalling the app: adb uninstall com.example.app and installing it again from android studio.



来源:https://stackoverflow.com/questions/60855299/how-to-read-a-file-directly-from-external-download-directory-on-android-10-q

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!