I am developing an android app. I want to download files from Firebase Storage to the internal storage and be able to play them afterwards (audio files). I use getFilesDir() to achieve that.
Everything works fine on the emulator. My audio directory is located at
/data/user/0/com.package.name/files/audio/
The problem occurs on some Huawei devices (phone and tablet) with Android API 28.
I get the error, that my audio folder can't be found at the location mentioned above and with the device file explorer I can clearly see that there is no data/user/ folder but instead the system still uses the old /data/data/com.package.name/ directories.
So my question is:
does someone have an idea why getFilesDir() is not giving me the right path and how I could fix this without hardcoding the path.
Here is some code, I have also tried to call exists() on the root folder, with no success.
String filename = document.getId() + ".m4a";
String rootPath = getFilesDir().getAbsolutePath();
File root = new File(rootPath);
//not working
if(!root.exists()){
rootPath = "/data/data/" + getPackageName() + File.separator + "files"
+ File.separator + "voice" + File.separator;
}
//
String folderPath = rootPath + File.separator + "voice" + File.separator;
File subFolder = new File(folderPath);
if(!subFolder.exists()){
subFolder.mkdir();
}
final File localFile = new File(subFolder, filename);
final StorageReference voiceRef = uploadsRef.child("voice").child(filename);
voiceRef.getFile(localFile);
getFilesDir() can and does return different absolute paths based on what device you're running on or even what user (for devices that support multiple users) is running your app (that's the user/0 you're seeing).
As long as you're operating on the directory returned by getFilesDir() or subdirectories of it (such as your new File(getFilesDir(), "voice") directory), everything will work on every device.
I was confused why getFilesDir() creates file in correct directory but not found them when need to delete, getFilesDir().getPath() worked for me.
The getFilesDir() method returns an abstract file path that will change based on the storage system.
You can get the /data/data/com.package.name/files pathway by using getCanonicalFile(). In Kotlin it would look something like this:
val filePath = context.filesDir.canonicalFile
This gives you the path name specific to the device.
Related
I've stumbled upon an issue that has been puzzling me. I'm writing an app that creates mp3 files on the external storage. The thing is, if I manually go to the created directory on the phone and delete the file, whenever I try to the create the same file it throws this error:
java.io.FileNotFoundException: /storage/emulated/0/Ringtones/sound1.mp3: open failed: EEXIST (File exists)
Selecting other sounds to be created works just fine, but after I manually delete them they can't be created again due to that issue.
I've already tried deleting the file right after indicating the path and before FileOutputStream but didn't work.
Any tips?
Cheers.
You need to acknowledge the media database before trying to create another copy of the same file. So you need to call this before copying:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(folder path in which your file was)));
Edit: The above answer is deprecated! Please use the following method:
File file = new File(outputPath + fileName);
String filePath = file.toString();
String mimeType = "video/mp4";
MediaScannerConnection.scanFile(this, new String[]{filePath}, new String[]{mimeType}, null);
Example of outputPath and fileName:
String outputPath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "My App Name") + "/";
String fileName = "break dance" + ".mp4";
So the File file should be the path of the media you want to update either because it's just deleted or it's newly added, to be visible in Gallery.
Found the answer, following user blackapps' tip. I also changed the directory, as I was using a deprecated reference. Now it is working as intended for sdk 30.
When i am trying to move file from fileDirectory1 to fileDirectory2 .. Is there any way to move or copy that file from one path to another in one FTP server.Please anyone can help me.
Here is my sample code:
String existingfile = file.getFilename();
String newfile =file.getFilename();
String fileDirectory1 = clients.getFtpFolder() + "/" + "unprocessed" + "/";
String fileDirectory2 = clients.getFtpFolder() + "/" + "processed" + "/";
sftpChannel.cd(fileDirectory1);
if (sftpChannel.get(newfile) != null){
sftpChannel.rename(fileDirectory1 + newfile ,
fileDirectory2 + newfile );
sftpChannel.cd(fileDirectory2);
sftpChannel.rm(existingfile );
}
Console:
Caused by:2: No such file
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2846)
I have tried How to move file from directory A to directory B in remote server?
Move a directory in remote server to another location in the same remote server using jsch
You can try ChannelSftp#rename:
sftpChannel.rename(oldPath, newPath);
Note that oldPath and newPath can be a relative path to your current remote working directory or a absolute remote path.
Edited:
Seems you use sftpChannel.cd(fileDirectory1) to change your working directory to fileDirectory1 and suppose newfile is inside that directory, you can have a try with something like
sftpChannel.rename(filename, destFilePath);
Note that filename is a file name and destFilePath is the remote file path of the destination. I have used it before and it works fine.
You code will be something like:
sftpChannel.rename(newfile, fileDirectory2 + newfile);
in your code. Hope this can help
After reading that is it possible to create a relative filepath name using "../" I tried it out.
I have a relative path for a file set like this:
String dir = ".." + File.separator + "web" + File.separator + "main";
But when I try setting the file with the code below, I get a FileNotFoundException.
File nFile= new File(dir + File.separator + "new.txt");
Why is this?
nFile prints: "C:\dev\app\build\..\web\main"
and
("") file prints "C:\dev\app\build"
According to your outputs, after you enter build you go up 1 time with .. back to app and expect web to be there (in the same level as build). Make sure that the directory C:\dev\app\web\main exists.
You could use exists() to check whether the directory dir exist, if not create it using mkdirs()
Sample code:
File parent = new File(dir);
if(! parent.exists()) {
parents.mkdirs();
}
File nFile = new File(parent, "new.txt");
Note that it is possible that the file denoted by parent may already exist but is not a directory, in witch case it would not be possible to use it a s parent. The above code does not handle this case.
Why wont you take the Env-Varable "user.dir"?
It returns you the path, in which the application was started from.
System.getProperty(user.dir)+File.separator+"main"+File.separator+[and so on]
I'm uploading images using Spring and Hibernate. I'm saving images on the server as follows.
File savedFile = new File("E:/Project/SpringHibernet/MultiplexTicketBooking/web/images/" + itemName);
item.write(savedFile);
Where itemName is the image file name after parsing the request (enctype="multipart/form-data"). I however need to mention the relative path in the constructor of File. Something like the one shown below.
File savedFile = new File("MultiplexTicketBooking/web/images/" + itemName);
item.write(savedFile);
But it doesn't work throwing the FileNotFoundException. Is there a way to specify a relative path with File in Java?
Try printing the working directory from your program.
String curDir = System.getProperty("user.dir");
Gets you that directory. Then check if the directories MultiplexTicketBooking/web/images/ exist in that directory.
Can't count the number of times I've been mistaken about my current dir and spent some time looking for a file I wrote to...
It seems the server should offer functionality as might be seen in the methods getContextPath() or getRealPath(String). It would be common to build paths based on those types of server related and reproducible paths. Do not use something like user.dir which makes almost no sense in a server.
Update
ServletContext sc=request.getSession().getServletContext();
File savedFile = new File(sc.getRealPath("images")+"\\" + itemName);
Rather than use "\\" I'd tend to replace that with the following which will cause the correct file separator to be used for each platform. Retain cross-platform compatibility for when the client decides to swap the MS/ISS based server out for a Linux/Tomcat stack. ;)
File savedFile = new File(sc.getRealPath("images"), itemName); //note the ','
See File(String,String) for details.
You could get the path of your project using the following -
File file = new File("");
System.out.println("" + file.getAbsolutePath());
So you could have a constants or a properties file where you could define your path which is MultiplexTicketBooking/web/images/ after the relative path.
You could append your path with the path you get from file.getAbsolutePath() and that will be the real path of the file. - file.getAbsolutePath() + MultiplexTicketBooking/web/images/.
Make sure the folders after the Project path i.e. MultiplexTicketBooking/web/images/ exist.
You can specify the path both absolute and relative with File. The FileNotFoundException can be thrown because the folder might be there. Try using the mkdirs() method first in to create the folder structure you need in order to save your file where you're trying to save it.
Im trying to build a directory called "images" on the SD card on android. This is my code but its not working? Can anyone give me some advice?
File picDirectory = new File("mnt/sdcard/images");
picDirectory.mkdirs();
Update: Since Android 10,11 Storage updates, Google has restricted Storage access through standard programming language file operations.
For applications targeting only Android 10 (API 29) and above, you need to declare "requestLegacyExternalStorage="true" " in your android manifest file to use programming language based file operations.
<application
android:requestLegacyExternalStorage="true"
....>
==========
You want to be sure you are correctly finding the address of your SDCard, you can't be sure its always at any particular address. You will want to do the following!
File directory = new File(Environment.getExternalStorageDirectory()+File.separator+"images");
directory.mkdirs();
Let me know if this works for you!
You will also need the following line in your AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I use this to know the result:
File yourAppDir = new File(Environment.getExternalStorageDirectory()+File.separator+"yourAppDir");
if(!yourAppDir.exists() && !yourAppDir.isDirectory())
{
// create empty directory
if (yourAppDir.mkdirs())
{
Log.i("CreateDir","App dir created");
}
else
{
Log.w("CreateDir","Unable to create app dir!");
}
}
else
{
Log.i("CreateDir","App dir already exists");
}
you can use this :
File directory = new File(Environment.getExternalStorageDirectory() + "/images");
directory.mkdirs();
Environment.getExternalStorageDirectory() is deprecated. So you should use this:
File directory = new File(this.getExternalFilesDir(null).getAbsolutePath() + "/YourDirectoryName");
directory.mkdirs();
One thing that is worth noting is if you always get false from the mkdirs(), try to unplug your device from pc, and see if it could create folders. At least I tried, it worked for me, currently I'm looking for ways to fix this problem.
To create specific root directory and its sub folder i use this code
String root = Environment.getExternalStorageDirectory().toString();//get external storage
File myDir = new File(root + "/grocery"+"/photo/technostark");//create directory and subfolder
File dir=new File(root + "/grocery"+"/data");//create subfolder
myDir.mkdirs();
dir.mkdirs();
To create file inside sd card you have to use Environment.getExternalStorageDirectory()
/**
* Creates a new directory inside external storage if not already exist.
*
* #param name The directory name
*/
public static void createNewDirectory(String name) {
// create a directory before creating a new file inside it.
File directory = new File(Environment.getExternalStorageDirectory(), name);
if (!directory.exists()) {
directory.mkdirs();
}
}
Following two important parameter which helps you to create directory
1. directory.mkdirs() :
Creates the directory named by this file, creating missing parent
directories if necessary.
2. directory.mkdir() :
Creates the directory named by this file, assuming its parents exist.
For more you can how getExternalStorageDirectory() works please see link
This should help.
First get the path of the external storage:
File root=Environment.getExternalStorageDirectory();
Then:
File picDirectory = new File(root.getAbsolutePath(), "mnt/sdcard/images");
picDirectory.mkdirs();