I read through the Android documentation of the cache (see Data Storage Documentation) but I didn't got how I can clean the whole folder.
So how can I delete the cache-folder of my app? It's in this path:
/Android/data/de.stepforward/cache/
Put this code in onDestroy() to clear app cache:
void onDestroy() { super.onDestroy();
try {
trimCache(this);
// Toast.makeText(this,"onDestroy " ,Toast.LENGTH_LONG).show();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void trimCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
You can use the code referenced here:
https://stackoverflow.com/a/7600257/327011
File cacheDir = context.getCacheDir();
File[] files = cacheDir.listFiles();
if (files != null) {
for (File file : files)
file.delete();
}
Kotlin:
You can make use of File.deleteRecursively() from the standard library to remove all sub directories as well
To delete the whole cache directory of the app:
context.cacheDir.deleteRecursively()
To delete a specific directory in the cache including its sub directories
File(context.cacheDir, "child directory name").deleteRecursively()
Thanks for the suggestion #elyeante
Rather than rolling your own utility methods, you may want to consider using the apache commons FileUtils library. It contains a lot of useful File manipulation methods and makes operations like this very trivial.
Here are the JavaDocs
And here is an example:
try {
FileUtils.deleteDirectory(context.getCacheDir());
} catch (IOException e) {
Log.e(LOGTAG,"Error deleting cache dir", e);
}
Alternately, rather than deleting the whole cache directory, you may want to create subdirectories within the app's cache directory for specific data. Than you can delete those specific directories when required (e.g. on user logout).
From the documentation:
Saving cache files
If you'd like to cache some data, rather than store it persistently,
you should use getCacheDir() to open a File that represents the
internal directory where your application should save temporary cache
files.
When the device is low on internal storage space, Android may delete
these cache files to recover space. However, you should not rely on
the system to clean up these files for you. You should always maintain
the cache files yourself and stay within a reasonable limit of space
consumed, such as 1MB. When the user uninstalls your application,
these files are removed.
Create a method to recurse through the folder and delete them, if that's what you want to do.
Related
Plzzz help me with this. Already late searching for the solution:
I want to list each and every Folder and file which is in the Android Phone's Internal Memory and External Memory.
The below code only gets list of files in one single directory.. But I'm unable to understand how would I list all the folders and files from internal and external memory.
..... List files = getListFiles(new File("YOUR ROOT")); ....
private List getListFiles(File parentDir) {
ArrayList inFiles = new ArrayList();
File[] files = parentDir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
inFiles.addAll(getListFiles(file));
} else {
if(file.getName().endsWith(".csv")){
inFiles.add(file);
}
}
}
return inFiles; }
Any help?
Look at the File object. It gives you methods to get all the files in a directory, tells you whether a file is a directory, and many other things.
You could easily do a recursive tree walk of the directory system. You probably will run into permissions issues, though, unless you have "rooted" your device.
I finally found this somewhere else.. This is how it's done (fully functional code)
public void walk(File root) {
File[] list = root.listFiles();
for (File f : list) {
if (f.isDirectory()) {
Log.d("realcrazy", "Dir: " + f.getAbsoluteFile());
walk(f);
}
else {
Log.d("realcrazy2", "File: " + f.getAbsoluteFile());
}
}
}
I've the sequent trouble. My app should read a list of files and show their name to the user.
When the app is launched for the first time i need to create a specific folder for the app?
then how can i check if it's empty?
Assuming you created the directory in the internal storage, you can get the number of child objects in the directory like this
File dir = context.getDir("somePath", Context.MODE_PRIVATE);
File[] children = dir.listFiles();
if(children.length > 0)
{
// the directory is not empty
}
else
{
// the directory is empty.
}
This is just a quick sample code. The better way would be to exclude the self and parent aliases using a custom FileFilter with dir.listFiles(), as I'm not sure they will always be excluded from the resulting list.
The following code will check if a folder already exists and if not creates one and warns you if error creating one:
// check if appfolder is created and if not through an
// exception
File path = new File("yourDir");
if (!path.exists()) {
if (!path.mkdirs()) {
try {
throw new IOException(
"Application folder can not be created. Please check if your memory is writable and healthy and then try again.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
} else {
Log.i("app", "directory is: " + path.getPath());
}
exists() checks if a path exists or not and path.exists() simply creates one for you.
I am trying to load a plugin implementation of an interface from a jar file which is in the /assets directory of my .apk file. The only way I've been able to get this to work is by extracting the jar file to private external storage and then passing that file to the DexClassLoader.
That works, but why should the jar have to exist in two places (the .apk and private external storage)? The DexClassLoader has to have a file path as its argument.
Is there a way to give it a direct path to the file that is in the /assets folder so that I don't have to use up external storage for an extra copy of what's already present?
Here are the relevant code snippets:
// somewhere in my main Activity ...
final File aExtractedDexFile = new File(getDir("dex", Context.MODE_PRIVATE),
LIBRARY_DEX_JAR);
extractDexTo(aExtractedDexFile);
loadLibraryProvider(aExtractedDexFile);
and
/** Extract the jar file that contains the implementation class.dex and place in private storage */
private void extractDexTo(File tJarInternalStoragePath) {
BufferedInputStream aJarInputStream = null;
OutputStream aDexOutputStream = null;
try {
aJarInputStream = new BufferedInputStream(getAssets().open(LIBRARY_DEX_JAR));
aJarOutputStream = new BufferedOutputStream(new FileOutputStream(tJarInternalStoragePath));
byte[] buf = new byte[BUF_SIZE];
int len;
while ((len = aJarInputStream.read(buf, 0, BUF_SIZE)) > 0)
{
aJarOutputStream.write(buf, 0, len);
}
aJarOutputStream.close();
aJarInputStream.close();
} catch (IOException e) {
if (aDexOutputStream != null) {
try {
aJarOutputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (aJarInputStream != null) {
try {
aJarInputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
and
/** Use DexClassLoader to load the classes from LibraryProvider */
private void loadLibraryProvider(File tFile) {
// Internal storage where the DexClassLoader writes the optimized dex file to.
final File aOptimizedDexOutputPath = getDir("outdex", Context.MODE_PRIVATE);
// Initialize the class loader with the secondary dex file.
DexClassLoader cl = new DexClassLoader(tFile.getAbsolutePath(),
aOptimizedDexOutputPath.getAbsolutePath(),
null,
getClassLoader());
Class<?> aLibProviderClazz = null;
try {
// Load the library class from the class loader.
aLibProviderClazz = cl.loadClass(LIBRARY_PROVIDER_CLASS);
sLibraryProvider = (LibraryInterface) aLibProviderClazz.newInstance();
} catch (Exception exception) {
// Handle exception gracefully here.
exception.printStackTrace();
}
}
Is there a way to give it a direct path to the file that is in the /assets folder so that I don't have to use up external storage for an extra copy of what's already present?
The answer is No. I suppose you follow this blog posted by official source implementing your code. if there is a better way of doing things, the bloger should recommend it in his blog.
Reason why you need optimizedDirectory is explained in the API:
This class loader requires an application-private, writable directory to cache optimized classes.
Also note that assets directory is not writable in apk, so it can't be done with purely assets directory.
Reason why you need copy jar file is a little bit subtle, mentioned in the blog:
First, it has to be copied to a storage location whose path can be supplied to the class loader.
Everything (folders/files) embedded within apk archive is not exposable (or interpretable) to the underlying file system at runtime. In another word, dexPath required in both DexClassLoader and PathClassLoader's constructor need a solid path string like /data/data/com.example/dex/common-lib.jar that represents the file in file system.
I'm facing a problem in the following code. What I'm trying to do is delete a folder and all of it's contents. Sometimes it works and sometimes it doesn't.
boolean success = false;
String directory = Environment.getExternalStorageDirectory().toString();
directory += "/.SID/Downloads/DC0601";
File path = new File(directory);
File[] files;
try
{
files = path.listFiles();
if (files == null)
{
success = path.delete();
}
else
{
for (int i = 0; i < files.length; i ++)
{
File currentFile = files[i];
if (currentFile != null)
currentFile.delete();
}
success = path.delete();
}
}
catch (Exception e)
{
success = false;
Log.e("deleteData Exception: ", e.toString());
}
What's happening here is that in some cases, the directory 'DC0601' does exist and does contain files on the sdcard, but when this code runs, success is returned as false because 'files' is null. Why is it null?!!
I simply can't understand it. If I completely shut down the app and then run it, it can detect the files and the directory and can successfully delete them. Otherwise if I've been using the app for a while and then run the code, it thinks that directory and those files aren't there.
Has anyone faced similar issues with delete()?
I see you're grabbing the external storage directory, but I don't see you checking it's state.
What does Environment.getExternalStorageState() return?
Should you be using
Environment.getExternalStorageDirectory().getPath()
I've never actually used .toString().
I have an application that needs to read images from a folder created by the application on the sdcard(sdcard/"foldername"/"filename.jpg". I have no idea what the names of the files are because the user specifies the names of the files. I need to read the images from the folder and make something like the default image viewer. Im thinking read them into a grid view first but 1) cant figure out how to dynamically read them from a folder 2) how would I implement the image options like the default viewer? If there was a way to open the default viewer on a certain folder that would help.
any input would be amazing been working on it for a while.
Thanks
Here's how you can get a list of folders off of the memory card:
String state = Environment.getExternalStorageState();
if(state.contentEquals(Environment.MEDIA_MOUNTED) || state.contentEquals(Environment.MEDIA_MOUNTED_READ_ONLY))
{
String homeDir = Environment.getExternalStorageDirectory();
File file = new File(homeDir);
File[] directories = file.listFiles();
}
else
{
Log.v("Error", "External Storage Unaccessible: " + state);
}
This code is from the top of my head, so some syntax may be off a bit, but the general idea should work. You can use something like this to filter down the folders to only folders that contain images:
FileFilter filterForImageFolders = new FileFilter()
{
public boolean accept(File folder)
{
try
{
//Checking only directories, since we are checking for files within
//a directory
if(folder.isDirectory())
{
File[] listOfFiles = folder.listFiles();
if (listOfFiles == null) return false;
//For each file in the directory...
for (File file : listOfFiles)
{
//Check if the extension is one of the supported filetypes
//imageExtensions is a String[] containing image filetypes (e.g. "png")
for (String ext : imageExtensions)
{
if (file.getName().endsWith("." + ext)) return true;
}
}
}
return false;
}
catch (SecurityException e)
{
Log.v("debug", "Access Denied");
return false;
}
}
};
Then, change the first example to:
File[] directories = file.listFiles(filterForImageFolders);
That should return only directories that contain images. Hopefully this helps some!