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
Related
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);
}
}
}
I have been searching the internet to find a resolution to my answer, have gone through all the documentation, and have looked through multiple forums before posting my own question on this. I need to save information through a file because my function
#Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("PointCount", pointCount);
savedInstanceState.putInt("UpOneCost", upOne);
savedInstanceState.putInt("UpTwoCost", upTwo);
savedInstanceState.putInt("TimerTime", upgradeTime);
super.onSaveInstanceState(savedInstanceState);
Toast.makeText(this, "Saving", Toast.LENGTH_LONG).show();
}
onSaveInstanceState only works at specific intervals at which I'm not entirely clear on. However, I know it doesn't get called when the activity is destroyed. The function above is mySaveInstanceState function and below is my restoreInstanceState function
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Toast.makeText(this, "Restoring", Toast.LENGTH_LONG).show();
if(savedInstanceState != null){
pointCount = savedInstanceState.getInt("PointCount");
upOne = savedInstanceState.getInt("UpOneCost");
upTwo = savedInstanceState.getInt("UpTwoCost");
upgradeTime = savedInstanceState.getInt("TimerTime");
if(upgradeTime < 5500){
startTimer();
}
TextView pointCountText = (TextView)findViewById(R.id.myTextView1);
pointCountText.setText("Points: " + Integer.toString(pointCount));
TextView pointCountText2 = (TextView)findViewById(R.id.upgradeScreenPointText);
pointCountText2.setText("Points: " + Integer.toString(pointCount));
Button upButtonOne = (Button)findViewById(R.id.upButton1);
upButtonOne.setText("Cost: " + Integer.toString(upOne));
Button upButtonTwo = (Button)findViewById(R.id.upButton2);
upButtonTwo.setText("Cost: " + Integer.toString(upTwo));
TextView myTimerValue = (TextView)findViewById(R.id.myTimerValueText);
myTimerValue.setText("Current Time: " + Integer.toString(upgradeTime));
}
}
There is a bit of useless info in there but overall this doesn't run when I hit the back button on the android device, so after a bit of research, i decided I should just save it into a file directory. This is where I created a file in my android project file named "saveFile" It is a text file, and it is in the same directory as my mainActivity.java file in order to remove file scope complications. In an effort to reach this file I came to the conclusion of overriding the onDestroy() function and try
String fileName = "saveFile";
FileOutputStream outputStream;
#Override
protected void onDestroy() {
super.onDestroy();
outputStream.openFileOutput(fileName, Context.MAKE_PRIVATE);
}
At which point I was already stopped because it couldn't find the file. The documentation is not clear on where this file should go directory wise, and as far as creation and then writing it is also very vague. If anyone could give a very clear explanation as to how all of it works I would be very appreciative of it. Thank you =) Note some of the code may contain minor errors since I typed some of it instead of copy paste but the idea is there. The only error I receive in the editor is on the outputStream.openFileOutput() line, which says it can't find the file.
In order to do file operations you should specify complete file path.
Passing only the filename will throw FileNotFoundException.
You can do one of the following;
1. Save the file in app cache.
filePath = appContext.getCacheDir( ).getAbsolutePath( )+"yourFileName";
Save the file in app data directory.
filePath = Environment.getDataDirectory( ).getPath( ) + File.separator + "data" + File.separator + appContext.getPackageName( ) + File.separator+"yourFileName";
Save the file in some folder on SD card.
File sdCard = Environment.getExternalStorageDirectory( );
String filePath = sdCard.getAbsolutePath( ) + File.separator + BASE_FOLDER_ON_SD_CARD + File.separator+"yourFileName";
For the third option you may need to add WRITE_EXTERNAL_STORAGE permission in AndroidManifest.xml of your application.
Also, saving the file should happen in onStop() method of your activity and reading the file content should happen in onResume()
Use the file from stored location.
You can do like this.
private void writeToFile(String data) {
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("config.txt", Context.MODE_PRIVATE));
outputStreamWriter.write(data);
outputStreamWriter.close();
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
private String readFromFile() {
String ret = "";
try {
InputStream inputStream = openFileInput("config.txt");
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ( (receiveString = bufferedReader.readLine()) != null ) {
stringBuilder.append(receiveString);
}
inputStream.close();
ret = stringBuilder.toString();
}
}
catch (FileNotFoundException e) {
Log.e("login activity", "File not found: " + e.toString());
} catch (IOException e) {
Log.e("login activity", "Can not read file: " + e.toString());
}
return ret;
}
but for each object you have to create separate file with different name.
hope this will help you..
below is way to store data in android:
shared preferences(data will keep until user uninstall the app or clear the app cache in setting application manager)
sqlite(permanent storage)
create a file to store(permanent storage) or if your data doesn't need to store permanently you may just create a singleton class to store your data. the data stored will gone after user close the app.
public void Save(String fileName) {
try {
OutputStreamWriter out = new OutputStreamWriter(openFileOutput(fileName, 0));
out.write(EditText1.getText().toString());
out.close();
Toast.makeText(this, fileName + " saved!", Toast.LENGTH_SHORT).show();
} catch (Throwable t) {
Toast.makeText(this, "Exception: " + t.toString(), Toast.LENGTH_LONG).show();
}
}
I try to download audio from a URL. I use following sample download manager code from Github https://github.com/folee/Download_Mgr
My problem is If i cancel download, Incomplete mp3 file still there in SDcard. How can i remove Incomplete mp3 files?
#Override
public void onClick(View v) {
Intent downloadIntent = new Intent(DownloadValues.Actions.DOWNLOAD_SERVICE_ACTION);
switch (v.getId()) {
case R.id.btn_continue:
// mDownloadManager.continueTask(mPosition);
downloadIntent.putExtra(DownloadValues.TYPE, DownloadValues.Types.CONTINUE);
downloadIntent.putExtra(DownloadValues.URL, url);
mContext.startService(downloadIntent);
mViewHolder.continueButton.setVisibility(View.GONE);
mViewHolder.pauseButton.setVisibility(View.VISIBLE);
break;
case R.id.btn_pause:
// mDownloadManager.pauseTask(mPosition);
downloadIntent.putExtra(DownloadValues.TYPE, DownloadValues.Types.PAUSE);
downloadIntent.putExtra(DownloadValues.URL, url);
mContext.startService(downloadIntent);
mViewHolder.continueButton.setVisibility(View.VISIBLE);
mViewHolder.pauseButton.setVisibility(View.GONE);
break;
case R.id.btn_delete:
// mDownloadManager.deleteTask(mPosition);
downloadIntent.putExtra(DownloadValues.TYPE, DownloadValues.Types.DELETE);
downloadIntent.putExtra(DownloadValues.URL, url);
mContext.startService(downloadIntent);
removeItem(url);
break;
}
}
my file bath :
public class ConfigUtils {
public static void InitPath(Context ctx) {
File temFile = Environment.getExternalStorageDirectory();
if (temFile != null && temFile.canWrite() && Util.getAvailableExternalMemorySize() > 0) {
IMG_PATH = Environment.getExternalStorageDirectory().getPath() + "/DL_Mgr/Image/";
FILE_PATH = Environment.getExternalStorageDirectory().getPath() + "/DL_Mgr/Downloads/";
}
else {
IMG_PATH = ctx.getFilesDir() + "/Image/";
FILE_PATH = ctx.getFilesDir() + File.separator;
}
new File(IMG_PATH).mkdirs();
new File(FILE_PATH).mkdirs();
Log.i(TAG, "IMG_PATH-->" + IMG_PATH + "\n FILEPATH-->" + FILE_PATH);
}
}
I use this code for delete temp files but not work
case R.id.btn_delete:
File tempFile = new File(ConfigUtils.FILE_PATH + "filename".toString());
if(tempFile.exists()) {
tempFile.delete();
}
But it not work
EDIT:
WORKING CODE: (If download mp3 temp file remane like : "sample.mp3.download"
so ichanged code like this it work fine
File tempFile = new File(ConfigUtils.FILE_PATH + filename +".download".toString());
if(tempFile.exists()) {
tempFile.delete();
}
Before downloading starts. You must know where you are saving the file. So probably a absolute path or Uri pointing to a file in sdcard
that you are giving to Download manager to store your file at.
Incase of cancel. create a file object from that uri or absolute path and call delete on file object if exists.
Something like this
File tempFile = new File(uri.toString());
if(tempFile.exists()) {
tempFile.delete();
}
This should be simple. Google it out
I'm making a video downloader app and I've got no problems saving and deleting files downloaded by the app to external storage but any file transfered from my computer cannot be deleted by the app.
This is a real problem as it's one of the key features I want. Here's the code I'm using:
public boolean deleteDataFromStorage(Data toDelete) {
//The file object soon to be deleted
File f = null;
Log.e(TAG, "Deleting " + toDelete.fileName);
// Delete file from storage
try {
// Get file to delete
f = new File(Environment.getExternalStorageDirectory().getCanonicalPath() + DIRECTORY + toDelete.fileName);
} catch (IOException e) {
Log.e(TAG, e.toString());
// Print to stack trace
e.printStackTrace();
}
// Delete file
if(f.delete()) {
return true;
} else {
Log.e(TAG, "Failed to delete " + toDelete.fileName);
return false;
}
}
As the f.delete() function doesn't throw any exceptions I have no idea what the problem is. The only thing I can think of is that the app doesn't have the permission to delete a file created in windows and yet I have downloaded apps from the app store that have no problem deleting transfered files.
Any help would be greatly appreciated.
As per your comment, since f.isFile() and f.exists() returns false, your f is not a file, in other words, you're getting the path wrong.
Print to the logs f.getAbsolutePath(), check what it is, and then it should be easy to fix.
The issue I am having could be a hardware-related. In any case I'm stumped.
I have written some code (that I took and modified from: Writing Text File to SD Card fails) I've put the code below. It works fine on my Sony Ericcson X8. However, on the Sony Ericsson Arc, I can't find the file when I look for it on the phone! I went line by line through the code and there are no failures. It's as if it's on the phone and I'm just blind. I can even see in the debugger that the value of gpxfile is:
/mnt/sdcard/MyCompany/MyLog
But when I use windows explorer to look for the file, I certainly don't see the directory MyCompany. Is there some setting on the phone that (silently) prevents writing to the SD Card?
Here is the code:
public static boolean generateNoteOnSD(String sFileName, String sBody) {
try {
String auxSDCardStatus = Environment.getExternalStorageState() ;
if (!auxSDCardStatus.equals(Environment.MEDIA_MOUNTED)) {
Log.i(TAG, "generateNoteOnSD auxSDCardSTatus: " + auxSDCardStatus);
}
if (auxSDCardStatus.equals(Environment.MEDIA_MOUNTED)) {
File root = new File(Environment.getExternalStorageDirectory(), "Dexcom");
if (!root.exists()) {
root.mkdirs();
}
File gpxfile = new File(root, sFileName);
FileWriter writer = new FileWriter(gpxfile, true);
String currentTimeString = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
writer.append(currentTimeString + ", " + sBody +System.getProperty("line.separator") );
//writer.newLine();
writer.flush();
writer.close();
Log.d(TAG,"generateNoteOnSD: Saved to file: " + sBody);
return true;
} else {
return false;
}
} catch(IOException e) {
e.printStackTrace();
return false;
//importError = e.getMessage();
//iError();
}
}
In my case the problem was that I had the Xperia ARC attached to the laptop with a USB cable. Apparently, things don't work quite right if you do that. No problem with the X8, so I'm guessing that it's phone specific. Computer may be putting lock on the file thus preventing Android from updating file. Not sure why I don't get an error though.
Bottom line for future readers: Try disconnecting phone from computer.