I want to create a private folder for my app data. This folder has to be deleted automatically when the app is removed from the device. According to http://developer.android.com/training/basics/data-storage/files.html, I have to create a private folder. How can I achieve this. My code below. Folder is not deleted when the app is removed.
public static String getAppFilePath(Context context) {
String path = "";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
path = Environment.getExternalStorageDirectory()
.getAbsolutePath();
path += "/myFolder";
} else {
ContextWrapper c = new ContextWrapper(context);
path = c.getFilesDir().getPath();
}
File ret = new File(path);
if (!ret.exists()) {
ret.mkdirs();
}
return path;
}
you are doing it wrong.
from the documentation you pointed:
If you want to save files that are private to your app, you can
acquire the appropriate directory by calling getExternalFilesDir()
and passing it a name indicating the type of directory you'd like.
Each directory created this way is added to a parent directory that
encapsulates all your app's external storage files, which the system
deletes when the user uninstalls your app.
For example, here's a method you can use to create a directory for an
individual photo album:
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
If none of the pre-defined sub-directory names suit your files, you
can instead call getExternalFilesDir() and pass null. This returns the
root directory for your app's private directory on the external
storage.
Remember that getExternalFilesDir() creates a directory inside a directory that is deleted when the user uninstalls your app. If the
files you're saving should remain available after the user uninstalls
your app—such as when your app is a camera and the user will want to
keep the photos—you should instead use
getExternalStoragePublicDirectory().
so basically you need to use getExternalFilesDirfunction in the example above to get it deleted when app in uninstalled.
according to documentation for getExternalFilesDir()
Parameters
type The type of files directory to return. May be null for
the root of the files directory or one of the following constants for
a subdirectory: DIRECTORY_MUSIC, DIRECTORY_PODCASTS,
DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS,
DIRECTORY_PICTURES, or DIRECTORY_MOVIES.
so apart from predefined types you can use null for root of the directory.
In simple words you cannot.
It is not possible as you cannot handle event after uninstalling the App.
Related
I am trying to use Android's internal helpers to get a path from the system for my file first and then put my files where the system wants. Because tomorrow they might change their minds.
I made a simple program to explore this subject. Here is my code;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String path = letsMakeAfile(this, "myFile.txt");
}
private static String letsMakeAfile(Context context, String nameOfFile) {
String strOfFinalPath ="";
//ask the system what path to use...
String strOfContextPath = context.getFilesDir() + "/";
//line above doesnt work without ' + "/" ' or something on the end
//line above records this path: /data/user/0/com.example.filesexperimenting/files/
//this appears to be an invalid path unless "user" is a hidden directory
Log.d("IDIOT", "strOfContextPath: "+ strOfContextPath);
try
{
File file = new File(strOfContextPath, nameOfFile);
if (file.exists() == false) {
file.mkdirs();
//after this line "makes dirs" is file automatically still made and dropped in?
letsMakeAfile(context, nameOfFile);
//I assume not so Ive made a recursive call
}
else
;
//escape recursion....
strOfFinalPath = file.getAbsolutePath();
//Here I record the path where I hope the file is located
Log.d("IDIOT", "strOfFinalPath: "+ strOfFinalPath);
}
catch (Exception e) {
e.printStackTrace();
Log.d("IDIOT", "CATCH ERROR: "+ e.getLocalizedMessage());
}
//runs without a catch
return strOfFinalPath;
}
}
Logcat:
2019-04-09 09:59:22.901 16819-16819/? D/IDIOT: strOfContextPath: /data/user/0/com.example.filesexperimenting/files/
2019-04-09 09:59:22.901 16819-16819/? D/IDIOT: strOfFinalPath: /data/user/0/com.example.filesexperimenting/files
Ultimately I am getting a path of /data/user/0/com.example.filesexperimenting/files/ from context.getFilesDir() which appears to be an invalid path unless "user" is a hidden directory (then why can I see root?). In Device File Explorer under data the only other directories are app, data and local
What am I missing? I'll assume its something with file.makedirs()
Full disclosure, I am a student and there is not a lot out there on this so your replies, while obvious to you at your experience level, should help others. I have some experience with Java and more with C++ but Android is new to me. Thanks in advance!
So, in talking outside of StackExchange it appears that using java.io like I am trying to in the example can cause some problems because of the preset file directories that may be locked or restricted that Java io might not know about.
Android has it's own method openFileOutput(String name, int mode) that has the ability to create the app resource file and directory it belongs in.
Description copied from class: android.content.Context
Actions:
~Open a private file associated with this Context's application package for writing.
~Creates the file if it doesn't already exist.
~No additional permissions are required for the calling app to read or write the returned file.
Params:
~name – The name of the file to open; can not contain path separators.
~mode – Operating mode.
Returns: The resulting FileOutputStream.
Throws: java.io.FileNotFoundException
If you want to be able to navigate to the location of your saved files through the file explorer (either in Android Studio or the Files app on the phone) you should use Context.getExternalFilesDir().
Context.getFilesDir() returns a directory not accessible by anyone BUT the creating application. So if you would like to see what is in this file you would need to open it with the same application that wrote it. IE: Print the contents to the screen after you save it in your app.
Context.getExternalFilesDir() returns a directory completely accessible by anyone and any application. So files created and saved in this external directory can be seen by Android Studio's file explorer as the OP has screenshot or by any application installed on the phone.
What is nice about both of these methods is that as long as you are only accessing files you have created you never need to ask the user for storage permissions Read or Write. If you would like to write to someone else's external files dir then you do.
Source
Check if sdcard is mounted or not.
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
///mounted
}
Get the path of sd card
File dir= new File(android.os.Environment.getExternalStorageDirectory());
walkdir(dir);
ArrayList<String> filepath= new ArrayList<String>();
//list for storing all file paths
public void walkdir(File dir) {
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
// if its a directory need to get the files under that directory
walkdir(listFile[i]);
} else {
// add path of files to your arraylist for later use
//Do what ever u want
filepath.add( listFile[i].getAbsolutePath());
}
}
}
}
Try using this:
context.getFilesDir().getParentFile().getPath()
I have a Samsung Galaxy S6. I'm currently working on a test application where I would like quick access to a folder with my files.
Using the provided "My Files" Application, it specifies that all those folders are in the "Internal Storage" folder.
I know that internal storage is private, but I want to create a folder in the default folder that windows accesses when the phone is plugged in.
For example, the following code does not create the directory in the correct location.
File storage = new File("/testappplication");
if(!storage.exists()) {
storage.mkdir();
System.out.println("Folder Created");
}
I just want to know the path where to create the folder. Many other applications have storage here, so I know its possible.
You can't create a directory inside the internal storage of the device. Except you've a root access for the app.
So, the following code won't work:
File storage = new File("/testappplication");
Because it tell the app to create a testappplication in the root folder.
You can only create the directory inside your app private folder within the following path:
String path = getFilesDir().getAbsolutePath();
And make the folder using the path.
Or you can use something like this:
File folder = new File(context.getFilesDir(), "testappplication");
if (!folder.exists()) {
folder.mkdirs();
} else {
// folder is exist.
}
Read more at Saving Files
First just for trial make runtime permmision and then try the following code
private void createInternalFile() {
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()+"/"+getApplicationContext()
.getPackageName()+"/File/profile");
if (!mediaStorageDir.exists()) {
mediaStorageDir.mkdirs();
} }
then check your internal storage in which you will find a folder whose name is your package name
After a while later I found the answer to this question.
public void createDirectory() {
File file = new File(Environment.getExternalStorageDirectory(), "/test");
if (!file.exists()) {
file.mkdirs();
Log.w("DEBUG", "Created default directory.");
}
}
This is how you create it code wise. The reason it wasn't creating was due to Samsungs weird permissions.
Make sure you have the storage permission enabled in Settings -> Apps -> App Name -> Permissions. I needed to turn it on so it would create the folder.
I am working on a big project with a reasonably big code base. What I want to ask you is hints on how to reliably check where I have to provide a solution to adapt for android 6.0 . What i have used is Analyze > Inspect Code , it does a static analysis of the code and than shows missing checks in the section :
Android > Constant and Resource Type Mismatches. It looks somewhat not the right place to find those problems and that is why I am asking to make sure I am using the right thing and am looking at the right thing, plus I am a bit confused because I have parts of code which write files and i am not getting notified about permissions checks there(is it a normal behaviour?!)
public static boolean write(String folderName, String filename, Object objToWrite) {
// serialize cardModel
FileOutputStream file = null;
ObjectOutputStream o = null;
File dirFile = AppController.getInstance().getApplicationContext().getDir(folderName, Context.MODE_PRIVATE);
try {
// Create archiveDir
File mypath = new File(dirFile, filename);
file = new FileOutputStream(mypath, false);
o = new ObjectOutputStream(file);
o.writeObject(objToWrite);
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
o.close();
file.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
Should I get a warning for Write permission here ?
Another thing that makes me ask is this issue that i have posted on google regarding an Android Studio bug:
Android Studio Bug
Not every write to a file needs a permission - only the one to external storage - this function might also write to the app file space - this needs no permission. Depends on the parameters
Interestingly enough, the definition of what "external storage" vs "internal storage" has changed quite a bit since Android Lollipop. What does this mean?
This call will require you to have storage permissions in the external public directory:
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
However, if you do the following, you won't need STORAGE Permissions.
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
According to Google:
`If none of the pre-defined sub-directory names suit your files, you can instead call getExternalFilesDir() and pass null. This returns the root directory for your app's private directory on the external storage.
Remember that getExternalFilesDir() creates a directory inside a directory that is deleted when the user uninstalls your app. If the files you're saving should remain available after the user uninstalls your app—such as when your app is a camera and the user will want to keep the photos—you should instead use getExternalStoragePublicDirectory().
Regardless of whether you use getExternalStoragePublicDirectory() for files that are shared or getExternalFilesDir() for files that are private to your app, it's important that you use directory names provided by API constants like DIRECTORY_PICTURES. These directory names ensure that the files are treated properly by the system. For instance, files saved in DIRECTORY_RINGTONES are categorized by the system media scanner as ringtones instead of music.
`
I'm not trying to write into the external sd at /mnt/sdcard. I'm trying to create a folder for may app files and have them accesible by others.
I have an app called Libra that generates .csv files when exporting data and all af it goes to /Libra/ folder. I want my app to do the same.
As far as I've seen there's external storage which is the sd and internal which is a non public place for the app.
How can I make a dir at the root of the android file system as Libra does ?
If I ask for the external storage I get the following non desired locations :
Environment.getExternalStorageDirectory()
/storage/emulated/0/ (in my Nexus)
/mnt/sdcard (in the emulator)
If I try to make the folder in an absolute path /MyDiary It returns Error creating folder
File folder = new File("/MyDiary");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
if (success) {
Toast.makeText(getBaseContext(), "Already exists", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getBaseContext(), "Error creating directory", Toast.LENGTH_LONG).show();
return;
}
If I try to check if the Libra folder does exists, it says it doesn't exist:
File folder = new File("/Libra");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
if (success) {
Toast.makeText(getBaseContext(), "Libra exists", Toast.LENGTH_LONG).show();
}
Note: I've got the manifest permissions to write in external storage.
The root is a ramdisk. And the folder in it some are created by init.rc. Only init.rc have permission to create the folder in the ramdisk.
If you create the folder by init.rc, you still need init.rc help to mount a true stroage device on the new folder.
Repack like The init.rc file regenerated on restart
First of all you need root access Permissions to write.
You can see whether it has created folder there or not using rootexplorer app.
Try this after getting root access.
I don't think that's the right way to create a File in the Android OS.
From http://developer.android.com/training/basics/data-storage/files.html:
If you want to save public files on the external storage [I've read your advice, but I think this way you can access files from multiple apps, if that's what you want], use the getExternalStoragePublicDirectory() method to get a File representing the appropriate directory on the external storage. The method takes an argument specifying the type of file you want to save so that they can be logically organized with other public files, such as DIRECTORY_MUSIC or DIRECTORY_PICTURES. For example:
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
try first getting superuser permission to your app.Run linux commands for making folder and files into which you want to write data(You can do this with only linux commands)just at 1st run of your app.Then you can write data to files by getting FileOutputStream("filename") object.Leave ur remarks if it worked or not.
partial code for above procedures is
Process p=Runtime.getRuntime().exec("su");
OutputStream o=p.getOutputStream();
o.write("mkdir foldername\n".getBytes());
o.write("cd foldername\n".getBytes());
o.write("cat > filename\n".getBytes());
o.write("exit\n".getBytes());
o.flush();
p.waitFor();
I am writing an Android mediaPlayer app, so I want to scan through all files on the entire phone (i.e. sdcard and phone memory). I can read from the sdcard, but not the root of it. That is, I can just read from the path /sdcard/[folder]/ and it works fine, but if I go to /sdcard/ the app crashes. How can I access all the files on the sdcard, as well as the files on the phone itself?
Never use the /sdcard/ path. it is not guaranteed to work all the time.
Use below code to get the path to sdcard directory.
File root = Environment.getExternalStorageDirectory();
String rootPath= root.getPath();
From rootPath location, you can build the path to any file on the SD Card. For example if there is an image at /DCIM/Camera/a.jpg, then absolute path would be rootPath + "/DCIM/Camera/a.jpg".
However to list all files in the SDCard, you can use the below code
String listOfFileNames[] = root.list(YOUR_FILTER);
listOfFileNames will have names of all the files that are present in the SD Card and pass the criteria set by filter.
Suppose you want to list mp3 files only, then pass the below filter class name to list() function.
FilenameFilter mp3Filter = new FilenameFilter() {
File f;
public boolean accept(File dir, String name) {
if(name.endsWith(".mp3")){
return true;
}
f = new File(dir.getAbsolutePath()+"/"+name);
return f.isDirectory();
}
};
Shash