19

I have a simple app that access and writes data to external storage. Everything works fine until I go to Settings -> Apps -> App Info and clear data via "Clear data" button, then every call to getExternalCacheDir() starts returning null.

I have been developing on Nexus 7 running Android 4.2.2.

My manifest looks like:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.package"
    android:versionCode="5"
    android:versionName="1.3"
    xmlns:tools="http://schemas.android.com/tools">

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="17" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
...

Code snippet that does not work:

    Log.d(TAG, "getExternalStorageState() = " + Environment.getExternalStorageState());
    Log.d(TAG, "getExternalCacheDir() = " + c.getExternalCacheDir());
    Log.d(TAG, "getExternalFilesDir(null) = " + c.getExternalFilesDir(null));
    Log.d(TAG, "getExternalFilesDir(Environment.DIRECTORY_MOVIES) = " + c.getExternalFilesDir(Environment.DIRECTORY_MOVIES));

LogCat after the app is installed and executed:

05-15 11:26:45.948: DEBUG/HelperUtils(5541): getExternalStorageState() = mounted
05-15 11:26:45.948: DEBUG/HelperUtils(5541): getExternalCacheDir() =     /storage/emulated/0/Android/data/com.example.package/cache
05-15 11:26:45.948: DEBUG/HelperUtils(5541): getExternalFilesDir(null) = /storage/emulated/0/Android/data/com.example.package/files
05-15 11:26:45.948: DEBUG/HelperUtils(5541): getExternalFilesDir(Environment.DIRECTORY_MOVIES) = /storage/emulated/0/Android/data/com.example.package/files/Movies

LogCat after clearing data in App Info settings:

05-15 11:27:57.848: DEBUG/HelperUtils(5859): getExternalStorageState() = mounted
05-15 11:27:57.848: WARN/ContextImpl(5859): Unable to create external cache directory
05-15 11:27:57.848: DEBUG/HelperUtils(5859): getExternalCacheDir() = null
05-15 11:27:57.848: WARN/ContextImpl(5859): Unable to create external files directory
05-15 11:27:57.848: DEBUG/HelperUtils(5859): getExternalFilesDir(null) = null
05-15 11:27:57.848: WARN/ContextImpl(5859): Unable to create external files directory
05-15 11:27:57.848: DEBUG/HelperUtils(5859): getExternalFilesDir(Environment.DIRECTORY_MOVIES) = null
05-15 11:27:57.848: WARN/ContextImpl(5859): Unable to create external cache directory

After clearing data and executing the app getExternalCacheDir() method returns null even though Environment.getExternalStorageState() returns "mounted". Does anyone know what could be possibly wrong?

EDIT

With the help from Gjordis I have found out that Clear data button removes whole application temporary directory:

storage/sdcard0/Android/data/com.example.app/cache in Android/data

and I was not able to create it again via getExternalCacheDir() or manually (though I am able to create other directories under storage/sdcard0/Android/data/).

(Android/data/com.example.app is created again after the device is rebooted, but that is not the solution I am looking for)

Vivek Barai
  • 1,338
  • 13
  • 26
Ondřej Z
  • 5,094
  • 3
  • 24
  • 30
  • Does it work once you restart your process (e.g., swipe your app off the recent-tasks list, then re-start your app)? – CommonsWare May 15 '13 at 11:02
  • @CommonsWare: I tried to force stop the app and removing it from running services but without any progress. I am still not able to create cache directory in `Android/data` again. The only way to make it work again is to reboot the device - see edited question. – Ondřej Z May 15 '13 at 12:36
  • 2
    That feels like a bug, then. Alas, http://b.android.com is down at the moment, so I cannot confirm if anyone has filed a bug report about this behavior. Do you have a full project that serves as a reproducible test case that you could like to? (ZIP, pointer to GitHub repo, etc.) – CommonsWare May 15 '13 at 13:12
  • I cannot reproduce your results on a Nexus 7. Clear Data has no effect -- the results are the same as before. – CommonsWare May 15 '13 at 19:31
  • 1
    @CommonsWare: I created new simple version of the app (it creates temp cache dir and writes to it) and I could not reproduce that bug either. I guess it has something to do with worker fragment and AsyncTask that are responsible for writing to cache in the original app... Thanks for your time! – Ondřej Z May 16 '13 at 10:00
  • I've faced the same problem on my Nexus 5 (Android 5+). Only device rebooting resolved the problem( – pvllnspk Feb 21 '15 at 08:29

3 Answers3

11

I have encountered and solved this exact problem.

Clicking the Clear Data button causes Android to stop your app from running and delete the entire application-specific folder "mnt/sdcard/Android/data/your.package.name" .

However, I had a separate process that was started from Runtime.getRuntime().exec() that was still running and it was writing to this folder. This caused the folder to be stuck in a locked state and caused the same symptom you described when my app called getExternalCacheDir() . Running adb shell and then ls from within the /mnt/sdcard/Android/data folder showed that the folder was locked by a process. Running ps showed that my other process was still running.

The solution was to properly kill the other process that was still writing to my application's application-specific folder before calling getExternalCacheDir() .

Akib Bagwan
  • 138
  • 1
  • 2
  • 14
Robert
  • 146
  • 2
  • 5
  • I confirm, I had a second application that had a handle to an opened temp file in the cache directory of the first application, clearing data for the first app caused the folder to get stuck and couldn't access the cache folder. Above answer must be up-voted. :) – Arise Oct 06 '14 at 15:28
6

getExternalCacheDir() returns cache dir like the name says. If there is no cache, there is no directory for it either. This directory is used for temporary files you removed with remove data command. In cases where phone is low on space, it can remove these folders itself too. Atleast some maintenance applications do so.

getExternalFilesDir() returns the directory for space to save data.

Gjordis
  • 2,540
  • 1
  • 22
  • 32
  • 1
    Thanks Gjordis, you are right, "Clear data" removes not only cache directory but whole package directory in Android/data. From that point I am not able to create that directory again and I am forced to reboot the device. Any suggestions? – Ondřej Z May 15 '13 at 12:31
  • Well clear data is not usually mean to be used repeatedly. Only on uninstalls and failed configs etc. Are you sure your application was still not running. Restarting the app should recreate the /data/.. in my oppinion – Gjordis May 15 '13 at 12:38
-3

If you use getExternal*Cache*Dir(), it is in order to store TEMPORALY data that can be cleaned by the system. If other applications in front on the backstack needs resources, the systeme can clean your data because system need resources. if you want save your data persistently, use : File file = getExternalFilesDir(null); this is an external memory for storage persitent data (like a virtual sdcard).

Jarvis
  • 1,527
  • 12
  • 17
  • 2
    The OP's problem is not that *files from the cache directory* disappear, but the disappearance of the *cache directory itself*, rendering the app unworkable, because hi can not re-create the cache to work with. – vbence Feb 01 '15 at 11:41