Deleting a file using File.delete() and Uri - java

I am trying to delete a file, but the file is not being deleted and my application is not throwing any errors. Below is my code:
final File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + '/' + "howmany.txt");
Uri uri = Uri.fromFile(file);
Boolean k = new File(uri.getPath()).delete();
if(k){
Toast.makeText(getApplicationContext(), "DELETED", Toast.LENGTH_SHORT).show();
}
I put this code right after checking for permissions, and from my understanding, .delete() returns true if the action is completed, so if it is I want to display a toast but the toast is never displayed. The strangest thing is that I am not getting any errors, but it just isn't working.

You don't need to create a Uri of the file object and then create a file object from that Uri. Just delete the file object and get the boolean result from that. You also don't need to create the k boolean. You can just test the delete itself:
final File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + '/' + "howmany.txt");
if (file.delete())
Toast.makeText(getApplicationContext(), "DELETED", Toast.LENGTH_SHORT).show();

Related

Cannot take a photo programmatically on Android 11 - intent returns canceled status

Starting an intent:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
CurrentFile = new File(getTempFileString());
CurrentUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", CurrentFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, CurrentUri);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent, IMAGE_CAPTURE);
Used to work. It no longer does. My method that starts after the intent is:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
The resultCode used to be RESULT_OK but is now RESULT_CANCELED.
If I stop checking the resultCode and just go past this, I find that the photo doesn't exist.
Based on CommonsWare's comment I extracted the logs. Of the 654 lines generated during this operation, four seem relevant.
2020-10-12 11:03:04.301 1471-1763/? E/MediaProvider: Creating a non-default top level directory or deleting an existing one is not allowed!
2020-10-12 11:03:04.310 477-2112/? I/AppsFilter: interaction: PackageSetting{240e1c6 com.[my app package]/10151} -> PackageSetting{193734c com.android.camera2/10124} BLOCKED
2020-10-12 11:03:04.553 390-9884/? W/ServiceManager: Permission failure: android.permission.SYSTEM_CAMERA from uid=10124 pid=11746
2020-10-12 11:03:14.097 11746-11746/? E/CAM_StateSavePic: exception while saving result to URI: Optional.of(content://[my app package].provider/external_files/[The SD card path I asked for]/1602518584301.jpg)
I am asking the file to get saved here:
new File(Environment.getExternalStorageDirectory(), getString(a.getApplicationInfo().labelRes))
This seems to be the issue.
Truly #CommonsWare deserves the credit here. The issue was the getTempFileString() call in the source code. I was attempting to save the file to a temp path so I could delete it right after. The file only exists shortly. Google blocked access to this. The Camera application received an error about not being able to save to this path, however it did not throw an error or display a message. It just returned a result of RESULT_CANCELED back to my application. I fixed this by updating the path used to the local cache directory getExternalCacheDir() and am using a sub directory inside that.
Edit: Adding the code that worked for me. Removed app specific text, and the error handling to keep it short and simple.
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "My Application Directory");
if (!path.exists()) {
path.mkdir();
}
File imageFile = File.createTempFile("Your file Name", ".jpg", path);
Context context = getActivity().getBaseContext();
Uri uri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", imageFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, CurrentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
startActivityForResult(intent, IMAGE_CAPTURE); // IMAGE_CAPTURE = 0
you shouldn't use "getExternalStoragePublicDirectory()" because this is SHARED STORAGE behaviour and from (probably) 5 july 2021 all applications on the Play Store MUST target android SDK 30 and use Scoped Storage only (so you can't use "requestLegacyStorage", idk about "preserveLegacyStorage").
I suggest you to change the destination path to:
context.getExternalFilesDir(null).getPath();
Have a nice Day & a Nice Coding :D
This is a strange behaviour but if you use MediaStore.EXTRA_OUTPUT flag method onActivityResult() will always return null data and you are expected to look for your data at location you pointed out here:
CurrentUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", CurrentFile);
So there are two different ways of handling result you are looking for

File.exists() Method always returns true even when the file doesn't exist

Im trying to curb duplicate downloads by checking if the file a user is about to download already exists before I proceed to downloading it.
Im using the method File.exists() to check for this condition but it seems to be always returning true.
Below is my code:
File destination = new File(Environment.DIRECTORY_DOWNLOADS, "/" + playlistTitle + "/" + image.getImgTitle() + ".jpg");
if (!destination.exists()) {
downloadId = downloadImage(image.getImgURL(), image.getImgTitle(), playlistTitle);
downloadIds.add(downloadId);
}
If I go directly to that file path before its created, it seems to be empty, but the code above returns true regardless.
You can check few things here
first as expected we are getting the permission to read and write the storage media.
and you try also using below method for checking if a file can be read or not
if (!file.canRead()) {
return false;
}
if two above doesn't work then use this.
if (!file.isFile()) {
//file doesn't exist
}else{
//file exists
}
new File(Environment.DIRECTORY_DOWNLOADS, "/" + playlistTitle
That can only lead to a path that is not possible.
You should use instead
new File( Environment.getExternalPublicDirectory(
Environment.DIRECTORY_DOWNLOADS),......

Delete image thumbnail from gallery when it got hidden

this question has been asked before(not specifically like this) but there hasn't been an All Exclusive answer to it yet. so we are trying to find the best solution here. i'm developing an app and in my app i hide a directory named myPic by moving it's files to a directory called .myPic. when i hide my pictures it's thumbnails are still in gallery. i find 3 solution to this:
first solution:
using ACTION_MEDIA_MOUNTED broad cast like this:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
the problem with this code is that it takes hug resources and most importantly it is blocked since android 4.4. so using this method is not rational for adding 10 pictures to gallery. so it is not an All exclusive method. also using ACTION_MEDIA_SCANNER_SCAN_FILE doesn't work on android 4.4 either
second solution:
using MediaScannerConnection. so i created a for loop and pass the old address of every file that i hide. this is my MediaScannerConnection function:
private void scanFile(File file) {
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
the thing about MediaScannerConnection is that it only effect if the file exist. so lets say i have a picture called 1.jpg in myPic directory. using this class i can add 1.jpg to my gallery immediately but when i move 1.jpg to .myPic directory and i scan the old path of 1.jpg nothing happen. logcat says that this file doen't exsit. so MediaScannerConnection only add files to gallery. what if i pass the new path of 1.jpg to MediaScannerConnection? well it adds 1.jpg from .myPic directory to gallery and that is exactly not what i want. so again not an All Exclusive method
third solution:
using getContentResolver(). so for deleting thumbnails this method may be the ultimate solution. so i write the blow code. in every loop i retrieve the path of image and pass it to getContentResolver().delete(Uri.parse(path),null,null). here is the code:
File myPic = new File(Environment.getExternalStorageDirectory()+"/myPic");
File myPicHide = new File(Environment.getExternalStorageDirectory()+"/.myPic");
if (!(myPicHide.exists()) & !(myPicHide.isDirectory())) {
myPicHide.mkdirs();
};
if (myPic.isDirectory()) {
String[] childeren = myPic.list();
if (childeren.length > 0) {
for (int i = 0; i < childeren.length; i++) {
String fileName = childeren[i];
File from = new File(Environment.getExternalStorageDirectory()+"/myPic"+fileName);
File to = new File(Environment.getExternalStorageDirectory()+"/.myPic"+fileName);
from.renameTo(to);
try {
String path = from.toString();
getContentResolver().delete(Uri.parse(path),null,null);
} catch(Exception e) {
Log.d("Rename", "Error happened");
}
}
}
} else {
Toast.makeText(getApplicationContext(), "myPic directory not found", Toast.LENGTH_LONG).show();
}
but it's not working either and thumbnails of my files are still showed in galley. so am i using getContentResolver() in wrong way?? this might be the all Exclusive method for the situation where deleted files thumbnails show up in gallery. i have my files path and i need to only delete it from media store content provider.
update:
so turns out that using Uri.parse(path) in the third solution is wrong. image Uri is started with content:// and it can be retrieved by MediaScannerConnection. so i created a Uri called imageInGalleryUri and assign null value to it. using my scanFile function i changed it's value from time to time and pass it's value to getContentResolver(). here is the code:
boolean whereIsMediaState = true;
Uri imageInGalleryUri = null;
File myPic = new File(Environment.getExternalStorageDirectory()+"/myPic");
File myPicHide = new File(Environment.getExternalStorageDirectory()+"/.myPic");
if (!(myPicHide.exists()) & !(myPicHide.isDirectory())) {
myPicHide.mkdirs();
};
if (myPic.isDirectory()) {
String[] childeren = myPic.list();
if (childeren.length > 0) {
for (int i = 0; i < childeren.length; i++) {
String fileName = childeren[i];
File from = new File(Environment.getExternalStorageDirectory()+"/myPic"+fileName);
scanFile(from);
File to = new File(Environment.getExternalStorageDirectory()+"/.myPic"+fileName);
from.renameTo(to);
if (to.isFile()){
try {
getContentResolver().delete(imageInGalleryUri,null,null);}
catch(Exception e) {
Log.d("Rename", "Error happened");
}
}
}
} else {
Toast.makeText(getApplicationContext(), "myPic directory not found", Toast.LENGTH_LONG).show();
}
private void scanFile(File file) {
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
imageInGalleryUri = uri;
}
});
}
i tried the code but it only detect the first image and delete it from the gallery but does not effect the other images. i can't figure out why. any idea?
thank you for your help in advance
. before folder just make it invisible. But there is way to say don't use this folder at all to gallery.
Please try to put empty file called ".nomedia" file into your folder.

File object can't find the file when there is one

In my app After user clicks on a button ,the download manager starts to download a file from internet and saving it to the internal sd card using this code:
void startDownload()
{
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdirs();
download_req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(PersianReshape.reshape("Downloading"))
.setDescription(PersianReshape.reshape("currently downloading the file..."))
.setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory().getAbsolutePath() , packageId + ".sqlite");
download_ID = mgr.enqueue(download_req);
}
After it is downloaded, I plan to check its existance everytime app runs with this code:
String DatabaseAddress =
Environment.getExternalStorageDirectory().getAbsolutePath() +
"/ee.sqlite";
File file = new File(DatabaseAddress);
Log.d("PATH File: ", DatabaseAddress);
if (file.exists()){
Toast.makeText(getApplicationContext(), "found", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(), "not found", Toast.LENGTH_SHORT).show();
}
Now when I run this code it returns "not found" message whereas the file is already there (I checked its existance using a file manager).
the device I test on is nexus 7 and path used in saving the download file is: /storage/emulated/0/ee.sqlite
ee.sqlite is the filename of downloaded file.
/storage/emulated/0/ is the default path returned by app
Permissions added to manifest for this code are:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Q: Why does file.exists() returns false when there is a file?
UPDATE:
WHEN I USE HARDCODE
File temp = new File("/sdcard/storage/emulated/0/", "ee.sqlite");
it works but when I use Environment.getExternalStorageDirectory().getPath() it doesn't.
Just initialize the File like this:
Updated:
This is just because of the separator missing there:
public static File getExternalStorageDirectory() {
return EXTERNAL_STORAGE_DIRECTORY;
}
and EXTERNAL_STORAGE_DIRECTORY is:
private static final File EXTERNAL_STORAGE_DIRECTORY
= getDirectory("EXTERNAL_STORAGE", "/sdcard");
static File getDirectory(String variableName, String defaultPath) {
String path = System.getenv(variableName);
return path == null ? new File(defaultPath) : new File(path);
}
String baseDir = EXTERNAL_STORAGE_DIRECTORY ;
String fileName = "ee.sqlite";
// Not sure if the / is on the path or not
File file = new File(baseDir + File.separator + fileName);
if (file.exists()) {
Toast.makeText(getApplicationContext(), "found", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(), "not found", Toast.LENGTH_SHORT).show();
}
2nd Possibilites: As you are running it in emulator you have to make sure you have external storage enabled Like this:
In Eclipse, go to Window > Android SDK and AVD Manager. Select the appropriate AVD and then click Edit.
Make sure you have SD card support enabled. If you do not, click the "New" button and select the "SD Card Support" option.
Finally got it to work by changing the File object.
The solution is to change the File object to the following:
File file = new File(Environment.getExternalStorageDirectory().getPath() + dirName + File.separator , fileName);
where dirName is:
String dirName = Environment.getExternalStorageDirectory().getAbsolutePath();
and fileName is:
String fileName = "ee.sqlite";
so I could easily check whether file exist or not using my criteria function.
if (file.exists()){
Toast.makeText(getApplicationContext(), "found", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(), "not found", Toast.LENGTH_SHORT).show();
}
I like to thank #andru for helping me.

new File(path) always actually creates a file on android?

I am trying to check if a file exits on android sd card...so i do:
File f=new File(sdpath + "/" + DATABASE_NAME); //
if(!f.exits()) {
...create new file..
}
else {
...do something...
}
Every time this actually creates the directory or file on the sd card.
I know it doesnt exist, and when the new File is executed it is created and it shouldnt ?
I read all across google that new File doesnt create an actual file on the file system , but in my case it does...
Any alternatives to checking if a File/directory exits without using new File..
Edit 1: Well I'd just like to add (after 4 years :)) that this problem occurred only on two devices at the time i was writing the post and never again, one of them was HTC Desire C with android 4.0 and the other was some Huawei with android 2.x, cant remember anymore.
For some strange reason it turned out that new File created a directory every time...
instead of checking if (!f.exists()), I changed it to checking if (!f.isFile())
In that case i create a new file and it works good, the next time i run it the file is already on the sd card...
The way that worked was nearly like yours:
File f = new File(Environment.getExternalStorageDirectory(), "a directory");
if(!f.exists){
// do something
}
and to check whether a file exists or not is almost the same way:
File f = new File(Environment.getExternalStorageDirectory() + "/a directory/" + "a file");
if(!f.exists){
// do something
}
I hope it can help you out, because it didn't create a file or directory in my app. It just checked the path.
this may helps you, try like
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//handle case of no SDCARD present
} else {
File file = new File(Environment.getExternalStorageDirectory()
+File.separator
+"myDirectory" //folder name
+File.separator
+"myFile.example"); //file name
if(file.exists()){
Toast.makeText(MainActivity.this, "Not Create ", 12).show();
}else{
file.mkdirs();
Toast.makeText(MainActivity.this, "Create ", 12).show();
}
}
Try this
File[] files = filedir.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
Toast.makeText(this, "directory", Toast.LENGTH_LONG).show();
} else {
if (file2.getName().equals(DATABASE_NAME)) {
Toast.makeText(this, "File found",Toast.LENGTH_LONG).show();
}
else{Toast.makeText(this, "File not found",Toast.LENGTH_LONG).show();
}
}
}

Categories