FileNotFoundException: open failed: EACCES (Permission denied) - java

In emulator (i use genymotion) it works fine, but when I run it on a real device (my phone is ASUS ZenFone Laser 5.0) throws a filenotfoundexception
java.io.FileNotFoundException: /storage/emulated/0/cam20160926_075819.jpg: open failed: EACCES (Permission denied)
imgBitmap = MediaStore.Images.Media.getBitmap(cr, selectedImage);
here's the method onActivityResult()
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case CAMERA_REQUEST:
if (resultCode == Activity.RESULT_OK){
Uri selectedImage = imageUri;
getActivity().getContentResolver().notifyChange(selectedImage, null);
ContentResolver cr = getActivity().getContentResolver();
Bitmap imgBitmap;
try {
imgBitmap = MediaStore.Images.Media.getBitmap(cr, selectedImage);
accountPhoto.setImageBitmap(imgBitmap);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Something went wrong while taking a photo", Toast.LENGTH_LONG).show();
Log.e("Camera", e.toString());
}
}
}
}
i read some related questions and solutions about this EACCES, and it seems the problem is on my permission:
<uses-feature android:name="android.hardware.camera2" android:required="true"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
am I missing something? thanks for responding

you have to request permission before you start your instructions because this permission is considered dangerous in Marshmallow:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RESULT);
}
else
{
//your code
}

I suspect WRITE_EXTERNAL_STORAGE overrides the READ_EXTERNAL_STORAGE read permission. If you look into the documentation you'll see that the former also permits reading from storage.
Try and remove the android:maxSdkVersion attribute and see if that works. I suspect that your device runs an SDK version > 18.
Check out this answer for more info: https://stackoverflow.com/a/15270626/425238

Related

Storage Permission Issue In android 10+ devices

i am trying to create a video player ,So I am trying to add the videos to the list
Storage permission is required to fetch the videos, so I took the permission with the below code.
But playstore was reject My app for this MANAGE EXTERNAL STORAGE permission.
But without this permission, I can't get storage permission on Android 10+ device.
To change the name of the video, delete the video and download the video permission is required , so please help me , please tell me how to get storage permission (/storage/Media/Videos , /storage/Download/)
My storage permission code :-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
android:requestLegacyExternalStorage="true"
Main activity code :-
private boolean checkPermission() {
if (SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager();
} else {
int result = ContextCompat.checkSelfPermission(PermissionActivity.this, READ_EXTERNAL_STORAGE);
int result1 = ContextCompat.checkSelfPermission(PermissionActivity.this, WRITE_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
}
}
private void requestPermission() {
if (SDK_INT >= Build.VERSION_CODES.R) {
try {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse(String.format("package:%s",getApplicationContext().getPackageName())));
startActivityForResult(intent, 2296);
} catch (Exception e) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivityForResult(intent, 2296);
}
} else {
//below android 11
ActivityCompat.requestPermissions(PermissionActivity.this, new String[]{WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2296) {
if (SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
// perform action when allow permission success
} else {
Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
}
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0) {
boolean READ_EXTERNAL_STORAGE = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean WRITE_EXTERNAL_STORAGE = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (READ_EXTERNAL_STORAGE && WRITE_EXTERNAL_STORAGE) {
// perform action when allow permission success
} else {
Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
}
}
break;
}
}
So please tell me how to take storage permission in Android10+ Devices and also below Android 10 devices with out using MANAGE EXTERNAL STORAGE permission , Please Help Me
Permissions have changed in Android 10+:
External storage access scoped to app files and media
By default, apps targeting Android 10 and higher are given scoped access into external storage, or scoped storage. Such apps can see the following types of files within an external storage device without needing to request any storage-related user permissions [..]
Source: Privacy changes in Android 10
On devices that run Android 10 or higher, you don't need any storage-related permissions to access and modify media files that your app owns, including files in the MediaStore.Downloads collection
Source: Storage Permissions
If you have
android:requestLegacyExternalStorage="true"
in application tag in manifest file then you are done for an Android Q/10 device.
It will behave as it behaved on before 10.
I do not understand why you would have any problem on Android 10.
On Android 11+ you should be able to see media files in the usual public directories.

Not able to get files from any Android folder

I am new in android and was trying to test something. I have this simple app, where I just want to read files from any android folder. Till now, I just checked how the paths are there which I came to know from the following
context.getExternalFilesDir(null);
&
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
The paths obtained are like
/storage/emulated/0/ then rest of the folders
I have done everything, asked for permission in the manifest file, and in the app too. I check that even though the permission is granted and folder path is also correct but the File.listFiles() is givingme null pointer exception.
Please take a look at the code below:
Permission in manfest file
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Code to get permission and try checking the files
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},101);
Toast.makeText(getApplicationContext(),
"No permission yet",
Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(),
"Permission already granted",
Toast.LENGTH_SHORT).show();
File dcimPath = new File("/storage/emulated/0/bluetooth"); //This path is correct
File[] files = dcimPath.listFiles(); // gives null pointer exception
Log.i("files length ",files.length+"");
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == 101){
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(getApplicationContext(),
"Permission granted",
Toast.LENGTH_SHORT).show();
File dcimPath = new File("/storage/emulated/0/bluetooth/");
File[] files = dcimPath.listFiles(); //gives error
Log.i("files length ",files.length+"");
}
else{
Toast.makeText(getApplicationContext(),
"Permission denied",
Toast.LENGTH_SHORT).show();
}
}
}
ERROR
Caused by: java.lang.NullPointerException: Attempt to get length of null array
Try adding this line to the Android Manifest File
android:requestLegacyExternalStorage="true"
This is used to read Shared Storage apart from the app's private storage. Read this if you are curious to know more...
Hope this helps. Feel free to ask for clarifications...

How to convert a string to a URI without throwing exceptions

I had to convert a Uri to a string so that I could serialize that Uri.
Intent openFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
openFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
openFileIntent.setType("audio/mpeg");
startActivityForResult(openFileIntent, PICK_MP3_FILE);
...then on activity result...
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_MP3_FILE)
{
if (resultCode == RESULT_OK)
{
try
{
if (data != null)
{
Uri mp3AudioFile;
if ((mp3AudioFile = data.getData()) != null)
{
myObject.setMp3Path(mp3AudioFile.getPath());
myObject.Save();
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
}
}
I closed the app and opened again. When I try to open that Uri with:
Uri uri = Uri.parse(myObject.getMp3Path();
I get an error:
java.lang.SecurityException: Permission Denial: reading com.android.providers.downloads.DownloadStorageProvider uri content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Faudio.mp3 from pid=601, uid=10107 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
My Manifest has the following permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
We need to provide persistent Uri permission.
JAVA
Intent openFileIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
openFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
openFileIntent.setType("audio/mpeg");
startActivityForResult(openFileIntent, PICK_MP3_FILE);
Also, a note worth mentioning is persistent permission is available only to Intent.ACTION_OPEN_DOCUMENT and NOT Intent.ACTION_GET_CONTENT whereas the latter one is like a one-time thing.
To do that I used getPath().
You should use toString() instead.
String scheme = uri.toString();
Uri uri = Uri.parse(scheme);
The permission denial issue needs to be dealt with the first time you receive a URI.
private val pickImage = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
// you will get result here in result.data
val uri = result.data?.data!!
requireActivity().contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
// Do something else with the URI. E.g, save the URI as a string in the database
}
}

java.io.IOException: Permission denied when using Camera on Andoid?

I have confirmed that the permissions are correct for Camera access, however on the later OS versions (perhaps API 25 and above) the camera does not open, it just gives the errror in debug console;
W/System.err: java.io.IOException: Permission denied
This is the method;
public void cameraClicked(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File tempFile = new File(Environment.getExternalStorageDirectory().getPath()+ "/photoTemp.png");
try {
tempFile.createNewFile();
Uri uri = Uri.fromFile(tempFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(takePictureIntent, 2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It does work on Android 7 and below.
EDIT - The following code is now opening the camera correctly, however once the photo is taken it progresses to the next screen but does not show the captured image... Just a black image.
public void cameraClicked(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path=this.getExternalCacheDir()+"file.png";
File file=new File(path);
Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",file);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(takePictureIntent, 2);
}
W/System.err: java.io.IOException: Permission denied
This happened because you create file to external storage over Android8/9/10.
If your targetSdk is 23 or higher, you should request permissions
dynamically. to know more : Requesting Permissions at Run Time
to get File path you can use
Context.getExternalFilesDir()/Context.getExternalCacheDir() for
example String path=Context.getExternalCacheDir()+"file.text"; File
file=new File(path) it doesnt need permission if the filepath is
"Android/data/app package/file name"
As in the Android Documentation, you need to write to the external storage, you must request the WRITE_EXTERNAL_STORAGE permission in your manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
If you use API 23 (Marshmallow) and above, you need to Requesting Permissions at Run Time because it's a Dangerous Permission.
if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...);
} else {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
requestPermissionLauncher.launch(
Manifest.permission.REQUESTED_PERMISSION);
}
Reference source link
reference
make file to external
Edit answer
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 0:
if (resultCode == Activity.RESULT_OK){
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
SaveImage(thumbnail);
}
break;
}
}
private static void SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().getAbsolutePath();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
String fname = "Image-"+ Math.random() +".jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
I also faced this issue before, seems like adding this inside the Application tag under AndroidManifest.xml file solve the problem for me:
<application
...
android:requestLegacyExternalStorage="true">
</application>

How can I delete an external folder with Android?

I have been searching for it but theres no any answer to my problem. I am programming an app and I want to delete an external folder. For example /storage/emulated/0/MyFolder, there is a lot of ways to create and read files from a internal app folder and an external app folder, but I dont know how to acces to files in "/storage/emulated/0/...".
Thanks.
public static void deleteDir(Context ctx) {
try {
File myFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator
+ "MyFolder");
}
if (myFile.exists()) {
deleteRecursive(myFile);
}
}catch (Exception ignored){
Log.e("Delete error File: %s",ignored.getMessage());
}
}
private static void deleteRecursive(File myFile) {
if (myFile.isDirectory())
for (File child : myFile.listFiles())
deleteRecursive(child);
Log.e("MyFolder Files Deleted!!! : %s", myFile.delete());
}
Add this lines to app manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Update
- As mentioned by CommonsWare runtime permission request needed for Android 6+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
} else {
deleteDir(context);
}
Your Activity
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 101:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
deleteDir(context);
}
}
}
new File("/storage/emulated/0/MyFolder").delete();
# your manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Update: As mentioned by CommonsWare hardcoded filesystem paths might be invalid for some versions of Android.
new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/MyFolder").delete();

Categories

Resources