File.renameTo return false - android

I want to rename my png file. Image current path like this:
/storage/emulated/0/Android/data/sample.png
I want to save this image under app's file directory. I give write external storage permission on runtime.
File toFileDir = new File(getFilesDir() + "images");
if(toFileDir.exists()) {
File file = new File("/storage/emulated/0/Android/data/sample.png");
File toFile = new File(getFilesDir() + "images/sample-1.png");
file.renameTo(toFile);
}
renameTo returns false. But I couldn't understand the reason.

Internal and external memory is two different file systems. Therefore renameTo() fails.
You will have to copy the file and delete the original
Original answer

You can try the following method:
private void moveFile(File src, File targetDirectory) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!src.renameTo(new File(targetDirectory, src.getName()))) {
// If rename fails we must do a true deep copy instead.
Path sourcePath = src.toPath();
Path targetDirPath = targetDirectory.toPath();
try {
Files.move(sourcePath, targetDirPath.resolve(sourcePath.getFileName()), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
throw new IOException("Failed to move " + src + " to " + targetDirectory + " - " + ex.getMessage());
}
}
} else {
if (src.exists()) {
boolean renamed = src.renameTo(targetDirectory);
Log.d("TAG", "renamed: " + renamed);
}
}
}

Related

Android New Image has strange numbers on the end of the file name

I'm writing a camera2 app in android and when I try to save the image, something adds extra numbers on the end of the filename before the '.jpg'
I have a feeling it's because of the createTempFile() method, but here's my code:
File createImageFile() throws IOException {
++image_id;
String timestamp = new SimpleDateFormat("yyyyMMdd").format(new Date());
String subFolder = "";
if(pref_session_unique_gallery.equals("yes")){
if(event_name != null){
subFolder = event_name;
} else {
subFolder = timestamp;
}
} else {
subFolder = "_GEN";
}
if(event_name == null){
imageFileName = "CPB_"+timestamp+"-"+image_id;
} else {
imageFileName = "CPB_"+event_name+"_"+timestamp+"-"+image_id;
}
imageStorageDirectory = Environment.getExternalStorageDirectory() + File.separator + "CPB" + File.separator + subFolder;
imageFinalFileName = imageFileName;
Toast.makeText(getApplicationContext(), imageStorageDirectory + "/" + imageFileName, Toast.LENGTH_LONG).show();
File storageDirectory = new File(imageStorageDirectory);
storageDirectory.mkdir();
File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
return image;
}
When I read the toast it gives me the correct path and filename that I am expecting, but when I look in my folder view, the picture has a lot of extra numbers on it.
For example, the picture name should be CPB_20160120-1.jpg but it currently reads CPB_20160120-1484291604.jpg If it makes a difference, the file was saved at 6:37 PM
two more examples:
should be: CPB_20160120-2.jpg
is: CPB_20160120-22140921986.jpg
should be: CPB_20160120-3.jpg
is: CPB_20160120-3-965716644.jpg
Not sure where those extra numbers are coming from when the file saves...
Those random numbers are explicitly generated by createTempFile(), as seen in the source code.
You probably don't want to use temporary files anyway, thus I'd recommend to create normal files:
File image = new File(storageDirectory, imageFileName + ".jpg");
According implementation of used method new file is created with extra random integer new File(tmpDirFile, prefix + Math.randomIntInternal() + suffix)
public static File createTempFile(String prefix, String suffix, File directory)
throws IOException {
// Force a prefix null check first
if (prefix.length() < 3) {
throw new IllegalArgumentException("prefix must be at least 3 characters");
}
if (suffix == null) {
suffix = ".tmp";
}
File tmpDirFile = directory;
if (tmpDirFile == null) {
String tmpDir = System.getProperty("java.io.tmpdir", ".");
tmpDirFile = new File(tmpDir);
}
File result;
do {
result = new File(tmpDirFile, prefix + Math.randomIntInternal() + suffix);
} while (!result.createNewFile());
return result;
}

mkdir return false in android?

This is my code
String DATA_PATH="/mnt/sdcard/";
String[] paths = new String[] { DATA_PATH, DATA_PATH + "tessdata/" };
for (String path : paths) {
File dir = new File(path);
if (!dir.exists()) {
if (!dir.mkdirs()) {
Log.v("", "ERROR: Creation of directory " + path + " on sdcard failed");
} else {
Log.v("", "Created directory " + path + " on sdcard");
}
}
}
I've tried using Environment.getExternalDirectory() but it still return false. The most confusing thing is it always said "ERROR: Creation of directory mounted on sdcard failed" on the logcat. How can the path changed into mounted? Can someone please give me a solution?
if the mobile is connected to the system then we are not able to create folders so remove it and run the application
Why are you using mkdirs in the first place ? You should just do:
File file = new File(Environment.getExternalStorageDirectory(), "tessdata");
if (!file.exists()) file.mkdir();
Also, make sure you have the WRITE_EXTERNAL_STORAGE permission in the manifest.

save to file stopped working

First of all here's the code so everybody knows what we're dealing with:
try
{
// now save to external files
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
String fileName = CONSTANTS.SETTINGS.MANAGER.DEFAULT_FILE_NAME + "." + this.format.value();
File saveDir = new File(CONSTANTS.SETTINGS.MANAGER.EXTERNAL_PUBLIC_DIR + File.separator + this.projectName);
if (saveDir.mkdirs() || saveDir.isDirectory())
{
File saveFile = new File(saveDir.getAbsolutePath() + File.separator + fileName);
File saveFileRoot = new File(CONSTANTS.SETTINGS.MANAGER.EXTERNAL_PUBLIC_DIR + File.separator + "Survey-" + projectName + ".xml");
LayerManager.getInstance().setDate(new Date());
switch (format)
{
case XML:
{
if (CONSTANTS.DEBUGGING_MODE)
{
SLog.d(CONSTANTS.SETTINGS.MANAGER.LOGTAG, "Writing user file into " + saveFile.getAbsolutePath());
}
xmlSerializer.write(LayerManager.getInstance(), saveFile);
xmlSerializer.write(LayerManager.getInstance(), saveFileRoot);
}
break;
case JSON:
{
FileWriter saveWriter = new FileWriter(saveFile);
try
{
if (CONSTANTS.DEBUGGING_MODE)
{
SLog.d(CONSTANTS.SETTINGS.MANAGER.LOGTAG, "Writing user file into " + saveFile.getAbsolutePath());
}
String content = gson.toJson(LayerManager.getInstance());
saveWriter.write(content);
}
finally
{
saveWriter.flush();
saveWriter.close();
}
}
break;
default:
{
SLog.e(CONSTANTS.ACTIVITY.MAIN.LOGTAG, "No user save requested.");
}
break;
}
// send event to update media scanner
FileSaved event = new FileSaved();
EventBus.getDefault().post(event);
}
else
{
SLog.e(CONSTANTS.ACTIVITY.MAIN.LOGTAG, "Could not write into save projectName");
return false;
}
}
else
{
return false;
}
}
catch (Exception e)
{
e.printStackTrace();
}
return true;
}
This works perfectly on an android 4.1.2 device API 16.
The code creates a new diretory, named any value projectName holds, in the "external_public_dir" <= saveDir
Then, depending on format xml/json, in both cases the file is written in the newly created directory.
As a test the file is also directly written to external_public_dir.
When you attach the device to your (windows) computer the files/directories are where they should be.
However, when this code is run on a device with Android 4.4.4 API 19 the two directories are not recognized anymore by windows... .
The two 'files' test & test2 should be folders containing an xml file each.
And the following makes the problem even more confusing:
1)The Android File explorer DOES recognize the directories...
2)As you can see, the other file created by saveFileRoot does appear in windows explorer...
I am stumped, any suggestions or tips would be very helpful!
Thanks in advance

file.mkdirs() not working

i want to write to a file in the sdcard of my phone.i used the below code to do this.
private CSVWriter _writer;
private File _directory;
public String _fileTestResult;
private String PATH_FILE_EXPORT = "/applications/foru/unittestframework/";
public ExportData(){
_writer=null;
_directory = new File(Environment.getExternalStorageDirectory () +PATH_FILE_EXPORT);
if(!_directory.exists())
_directory.mkdirs();
}
public void exportResult(String testcaseNum,String testcase,String status){
try {
if(_directory.exists()){
//do something
}
but mkdirs() is not working.so i could not excecute following code in the if condition.please help me.
note:i have given the permission in manifest file.
EDIT:
i am using this file write option for storing the result of automation testing using robotium.i have created a normal project and tried to create directory in sdcard.but the same code when i am using in this testproject it is not working.why like that?dont unit testing framework support this?
have you add the correct permission in your manifest ?
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Edit : ok, i just read your note for permission.
If it's help you this is my sdcard cache code :
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
String evtDir = "";
if(evt > 0){
evtDir = File.separator + evt;
}
cacheDir = new File(
android.os.Environment.getExternalStorageDirectory()
+ File.separator
+ "Android"
+ File.separator
+ "data"
+ File.separator
+ Application.getApplicationPackageName()
+ File.separator + "cache"
+ evtDir);
}else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
Try below code
try {
File root = Environment.getExternalStorageDirectory();
if (root.canWrite()) {
imagefolder = new File(root,
mycontext.getString(R.string.app_name));
imagefolder.mkdirs();
}
} catch (Exception e) {
Log.e("DEBUG", "Could not write file " + e.getMessage());
}
Try with:
if(!_directory.exists())
_directory.mkdir();
Also check this - Creating a directory in /sdcard fails

file.isDirectory() always false in android with the path

ANSWER:
Needed the call to getExternalFilesDir(p); like so:
String p = thepathblah;
File path=context.getExternalFilesDir(p);
EDIT EDIT:
While I knew the Environment.DIRECTORY_PICTURES was returning just Pictures/ I figured this worked because in android I assumed the file pointer was already pointing to your application space (sorta like in c#). So in this:
String p = Environment.DIRECTORY_PICTURES + "/" + s.getClient().getFirstName()+s.getClient().getLastName() +
"/" + s.getPackage().getName() +
(mSession.getSessionDate().getMonth()+1) +
mSession.getSessionDate().getDate() +
(mSession.getSessionDate().getYear()+1900);
I thought was getting the full path, in fact I was writing a file out to this with no issues. It turns out though to delete individual files (and load them) I needed a fuller path which ended up being:
String p = Environment.DIRECTORY_PICTURES + "/" + s.getClient().getFirstName()+s.getClient().getLastName() +
"/" + s.getPackage().getName() +
(mSession.getSessionDate().getMonth()+1) +
mSession.getSessionDate().getDate() +
(mSession.getSessionDate().getYear()+1900);
File dir = new File("/sdcard/Android/data/com.software.oursoftware/files/"+p);
Not sure if I can take it that the above link is valid for all Honeycomb devices or not, specifically the /sdcard/Android/data/packagespace/files/
Is this safe to use this or do I have to do something more dynamic for honeycomb devices???
EDIT: This is my little test function code to just write something to a folder...
String p = Environment.DIRECTORY_PICTURES + "/" + s.getClient().getFirstName()+s.getClient().getLastName() + "/" + s.getPackage().getName() + (mSession.getSessionDate().getMonth()+1) + mSession.getSessionDate().getDate() + (mSession.getSessionDate().getYear()+1900);
File path = mContext.getExternalFilesDir(p);
File file = new File(path, "DemoPicture.jpg");
try {
// Very simple code to copy a picture from the application's
// resource into the external file. Note that this code does
// no error checking, and assumes the picture is small (does not
// try to copy it in chunks). Note that if external storage is
// not currently mounted this will silently fail.
InputStream is = getResources().openRawResource(R.drawable.ic_contact_picture);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(mContext,
new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String arg0, Uri arg1) {
Log.i("ExternalStorage", "Scanned " + arg0 + ":");
Log.i("ExternalStorage", "-> uri=" + arg1);
}
});
} catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.w("ExternalStorage", "Error writing " + file, e);
}
Then the way I try to delete this folder:
String p = Environment.DIRECTORY_PICTURES + "/" + firstName+lastName +"/" + pName+pDate;
File dir=new File(p);
deleteRecursive(dir);
results in
Pictures/ShaneThomas/Portrait882011/
Which can write a file, tested that, but if I try to say:
void deleteRecursive(File dir)
{
Log.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
if (dir.isDirectory())
{
String[] children = dir.list();
for (int i = 0; i < children.length; i++)
{
File temp = new File(dir, children[i]);
if(temp.isDirectory())
{
Log.d("DeleteRecursive", "Recursive Call" + temp.getPath());
deleteRecursive(temp);
}
else
{
Log.d("DeleteRecursive", "Delete File" + temp.getPath());
boolean b = temp.delete();
if(b == false)
{
Log.d("DeleteRecursive", "DELETE FAIL");
}
}
}
dir.delete();
}
}
The dir.isDirectory is always false!? I got this delete file/directories code off stack overflow but am puzzled as to why its not working?
and I do have this set:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
There are several reasons for File.isDirectory() to return false:
The path points to file (obviously), and not to directory.
The path is invalid (i.e. there is no such file/directory exists).
There is not enough permissions granted to your application to determine whether path points to directory.
In general, if isDirectory() returns true, you've got path that points to directory. But if isDirectory() returns false, then it might be or might not be a directory.
In your particular case, the path most likely does not exist. You need to call dir.mkdirs() to create all directories in the path. But since you need that to only recursively delete them, then there is no point in calling dir.mkdirs() just to remove that directory after that.
I think you want to add
dir.mkdirs() right after File dir=new File(p). mkdirs() is the method responsible for actually creating a directory, not new File().
Ok it's answered, but sometimes the issue fires because of sample reasone:permission :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
if you forgot this permission you will always get false result.

Categories

Resources