Java.io.filenotfoundexception Storage Emulated 0 [HOT] Download (permission Denied)
How to Fix java.io.FileNotFoundException /storage/emulated/0/download/ (Permission denied) on Android
If you are developing an app that needs to read or write files from external storage on Android, you may encounter a java.io.FileNotFoundException with a message like "/storage/emulated/0/download/ (Permission denied)". This exception means that your app cannot access the file because it does not have the required permissions or because the file system does not allow it.
This exception can happen in various scenarios, such as when you try to open a file from a download folder, a camera folder, a WhatsApp folder, or any other folder that is not specific to your app. It can also happen when you try to create, modify, or delete a file on external storage.
java.io.filenotfoundexception storage emulated 0 download (permission denied)
Download Zip: https://www.google.com/url?q=https%3A%2F%2Ft.co%2F9VUnOw8Co1&sa=D&sntz=1&usg=AOvVaw2uCMIRqdLNrTMN_VBdD8oh
In this article, we will show you how to fix this exception by using different solutions that are compatible with different versions of Android. We will also provide some code snippets and screenshots to help you understand and implement these solutions.
Solution 1: Check and request storage permissions
One of the most common causes of java.io.FileNotFoundException on Android is that your app does not have the necessary permissions to access external storage. Android defines two types of permissions for accessing external storage: READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE. These permissions allow your app to read or write files from any location on external storage, respectively.
To use these permissions, you need to do two things:
Declare them in your app's manifest file
Request them at runtime if your app targets Android 6.0 (API level 23) or higher
To declare these permissions in your manifest file, add the following lines inside the tag:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
To request these permissions at runtime, you need to check if they are already granted by calling the checkSelfPermission() method of the ContextCompat class and passing the current context and the permission name as parameters. If the method returns PackageManager.PERMISSION_GRANTED, it means that the permission is already granted. Otherwise, you need to call the requestPermissions() method of the ActivityCompat class and passing the current activity, an array of permissions, and a request code as parameters. This will show a dialog to the user asking them to grant or deny the permissions. You can then handle the user's response by overriding the onRequestPermissionsResult() method of your activity and checking the grantResults array for the corresponding request code. Here is an example of how to do this:
// Define a constant for the request code private static final int REQUEST_CODE_STORAGE = 1; // Check and request storage permissions private void checkAndRequestStoragePermissions() // Check if the permissions are already granted if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) // Permissions are already granted, do nothing else // Permissions are not granted, request them ActivityCompat.requestPermissions(this, new String[]Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, REQUEST_CODE_STORAGE); // Handle the user's response to the permission request @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults); // Check if the request code matches the storage request code if (requestCode == REQUEST_CODE_STORAGE) // Check if the permissions are granted if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) // Permissions are granted, do your file operations else // Permissions are denied, show a toast or a dialog explaining why they are needed Toast.makeText(this, "Storage permissions are required to access files", Toast.LENGTH_SHORT).show();
Here is a screenshot of how the permission dialog looks like:
Note that you should only request the permissions that are necessary for your app's functionality and explain to the user why they are needed. You should also respect the user's choice and handle the case when they deny or revoke the permissions.
Solution 2: Use the android:requestLegacyExternalStorage attribute
Another possible cause of java.io.FileNotFoundException on Android is that your app is targeting Android 10 (API level 29) or higher and is using scoped storage by default. Scoped storage is a new feature that limits your app's access to external storage and only allows it to access its own app-specific directory and media files that belong to your app. This means that your app cannot access files from other directories or apps unless you use special methods or permissions.
If you want to opt out of scoped storage and use the legacy storage behavior that allows your app to access any file on external storage, you can use the android:requestLegacyExternalStorage attribute in your manifest file. This attribute tells the system that your app wants to use the old storage model and does not need to comply with scoped storage restrictions.
To use this attribute, add it inside the tag of your manifest file and set it to true:
<application ... android:requestLegacyExternalStorage="true"> ... </application>
Here is a screenshot of how your manifest file should look like:
Note that this attribute only works on Android 10 devices and does not affect devices running Android 9 (API level 28) or lower. Also, this attribute is not recommended for long-term use as it may be removed in future versions of Android. You should only use it as a temporary solution while you migrate your app to scoped storage.
Solution 3: Use the android:preserveLegacyExternalStorage attribute
If your app is targeting Android 11 (API level 30) or higher, you cannot use the android:requestLegacyExternalStorage attribute anymore as it has no effect on devices running Android 11 or higher. Instead, you can use another attribute called android:preserveLegacyExternalStorage in your manifest file. This attribute tells the system that your app wants to preserve the legacy storage behavior that was used on Android 10 devices when the android:requestLegacyExternalStorage attribute was set to true.
To use this attribute, add it inside the tag of your manifest file and set it to true:
<application ... android:preserveLegacyExternalStorage="true"> ... </application>
Here is a screenshot of how your manifest file should look like:
Note that this attribute only works on Android 11 devices and does not affect devices running Android 10 or lower. Also, this attribute has some limitations and may not work for all files or directories. For example, it does not work for files that are created by other apps using the MediaStore API or files that are located in the Android/data or Android/obb directories. You should only use this attribute as a temporary solution while you migrate your app to scoped storage.
Solution 4: Use the MANAGE_EXTERNAL_STORAGE permission
If you want to have full access to external storage on Android 11 devices and above, you can use a new permission called MANAGE_EXTERNAL_STORAGE. This permission grants your app the ability to read and write files from any location on external storage, including files that belong to other apps or directories that are not accessible by default. This permission also allows your app to access the internal storage of the device, which is normally protected by the system.
To use this permission, you need to do two things:
Declare it in your manifest file
Request it at runtime by launching a system settings screen
To declare this permission in your manifest file, add the following line inside the tag:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
To request this permission at runtime, you need to launch a system settings screen that shows a toggle for your app to enable or disable the permission. You can do this by creating an intent with the action Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION and passing your app's package name as data. You can then start the intent with startActivityForResult() and handle the result in onActivityResult(). Here is an example of how to do this:
// Define a constant for the request code private static final int REQUEST_CODE_MANAGE_STORAGE = 2; // Check and request manage storage permission private void checkAndRequestManageStoragePermission() // Check if the permission is already granted if (Environment.isExternalStorageManager()) // Permission is already granted, do nothing else // Permission is not granted, launch the system settings screen Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivityForResult(intent, REQUEST_CODE_MANAGE_STORAGE); // Handle the result of the permission request @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) super.onActivityResult(requestCode, resultCode, data); // Check if the request code matches the manage storage request code if (requestCode == REQUEST_CODE_MANAGE_STORAGE) // Check if the permission is granted if (Environment.isExternalStorageManager()) // Permission is granted, do your file operations else // Permission is denied, show a toast or a dialog explaining why it is needed Toast.makeText(this, "Manage storage permission is required to access files", Toast.LENGTH_SHORT).show();
Here is a screenshot of how the system settings screen looks like:
Note that this permission is very powerful and risky, and you should only use it if you have a valid use case that requires full access to external storage. You should also explain to the user why your app needs this permission and how they can revoke it if they want to. Moreover, this permission may not be approved by Google Play if your app does not comply with their policies and guidelines. You should always follow the best practices for accessing files on Android and use alternative methods whenever possible.
Solution 5: Use the ACTION_OPEN_DOCUMENT intent
If you want to access files from external storage without requiring any permissions, you can use a system file picker that allows your app to open files from any location that the user chooses. Android provides an intent called ACTION_OPEN_DOCUMENT that launches a file picker and returns a URI for the selected file. This URI can be used by your app to read or write the file with the help of a ContentProvider. This way, your app does not need to request any permissions or deal with scoped storage restrictions.
To use this intent, you need to create it with the action ACTION_OPEN_DOCUMENT and optionally specify a MIME type or a category to filter the files that can be selected. You can then start the intent with startActivityForResult() and handle the result in onActivityResult(). Here is an example of how to do this:
// Define a constant for the request code private static final int REQUEST_CODE_OPEN_DOCUMENT = 3; // Launch the file picker private void openDocument() // Create an intent with the action ACTION_OPEN_DOCUMENT Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); // Optionally, specify a MIME type or a category to filter the files that can be selected intent.setType("*/*"); // Any type of file //intent.setType("image/*"); // Only images //intent.addCategory(Intent.CATEGORY_OPENABLE); // Only files that can be opened // Start the intent and wait for the result startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT); // Handle the result of the file picker @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) super.onActivityResult(requestCode, resultCode, data); // Check if the request code matches the open document request code if (requestCode == REQUEST_CODE_OPEN_DOCUMENT) // Check if the result is OK and the data is not null if (resultCode == RESULT_OK && data != null) // Get the URI of the selected file Uri uri = data.getData(); // Do your file operations using the URI and a ContentResolver try // For example, read the file as a byte array ContentResolver resolver = getContentResolver(); InputStream inputStream = resolver.openInputStream(uri); byte[] bytes = IOUtils.toByteArray(inputStream); inputStream.close(); // Do something with the bytes catch (IOException e) e.printStackTrace(); else // Result is not OK or data is null, show a toast or a dialog explaining what went wrong Toast.makeText(this, "Failed to open file", Toast.LENGTH_SHORT).show();
Here is a screenshot of how the file picker looks like:
Note that this intent only works for opening files, not for creating or deleting them. If you want to create or delete files on external storage, you need to use other methods or permissions. You should also be careful when using the URI of the selected file, as it may not be valid or accessible forever. You should use the takePersistableUriPermission() method of the ContentResolver class to persist the permission to access the URI across device reboots. You should also use the FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION flags when starting the intent to grant your app temporary permission to read or write the file.
Conclusion
In this article, we have shown you how to fix java.io.FileNotFoundException /storage/emulated/0/download/ (Permission denied) on Android by using different solutions that are compatible with different versions of Android. We have also provided some code snippets and screenshots to help you understand and implement these solutions.
Here are some tips and best practices for working with files on Android:
Always check and request permissions before accessing external storage
Migrate your app to scoped storage as soon as possible and use app-specific directories or media files whenever possible
Use alternative methods or permissions only if you have a valid use case that requires full access to external storage
Explain to the user why your app needs certain permissions or access and respect their choice
Use system file pickers or intents to access files from external storage without requiring any permissions
Be careful when using URIs of files from external storage and persist or grant permissions as needed
FAQs
What is java.io.FileNotFoundException?
java.io.FileNotFoundException is an exception that occurs when an app tries to open, read, write, or delete a file that does not exist or cannot be accessed. It usually indicates that there is a problem with the file path, name, permissions, or system settings.
What is external storage on Android?
External storage on Android refers to a shared storage space that can be accessed by all apps and users on a device. It can be either a built-in memory (such as /sdcard) or a removable media (such as a micro SD card). External storage can store any type of files, such as images, videos, music, documents, etc.
What is scoped storage on Android?
Scoped storage on Android is a new feature that limits the access of apps to external storage and only allows them to access their own app-specific directories and media files that belong to them. Scoped storage aims to improve the privacy and security of users' data and reduce the clutter and confusion of external storage. Scoped storage is enforced by default on Android 10 and above, but apps can opt out or use alternative methods or permissions to access other files or directories.
What is the difference between READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions?
READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE are two types of permissions that allow apps to access external storage on Android. READ_EXTERNAL_STORAGE allows apps to read files from any location on external storage, while WRITE_EXTERNAL_STORAGE allows apps to write files to any location on external storage. Both permissions are considered dangerous and require explicit user consent at runtime if the app targets Android 6.0 (API level 23) or higher.
What is the difference between android:requestLegacyExternalStorage and android:preserveLegacyExternalStorage attributes?
android:requestLegacyExternalStorage and android:preserveLegacyExternalStorage are two attributes that allow apps to opt out of scoped storage and use the legacy storage behavior that grants them full access to external storage. android:requestLegacyExternalStorage works on Android 10 devices and tells the system that the app wants to use the old storage model. android:preserveLegacyExternalStorage works on Android 11 devices and tells the system that the app wants to preserve the legacy storage behavior that was used on Android 10 devices when the android:requestLegacyExternalStorage attribute was set to true. Both attributes are not recommended for long-term use as they may be removed in future versions of Android.