getExternalCacheDir() возвращает null после очистки данных

У меня есть простое приложение, которое обращается к внешнему хранилищу и записывает данные во внешнее хранилище. Все работает нормально, пока я не перехожу в «Настройки» -> «Приложения» -> «Информация о приложении» и не очищаю данные с помощью кнопки «Очистить данные», после чего каждый вызов getExternalCacheDir() начинает возвращать значение null.

Я разрабатывал Nexus 7 под управлением Android 4.2.2.

Мой манифест выглядит так:

<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
...

Фрагмент кода, который не работает:

    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 после установки и запуска приложения:

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 после очистки данных в настройках App Info:

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

После очистки данных и выполнения метода приложения getExternalCacheDir() возвращается значение null, хотя Environment.getExternalStorageState() возвращает значение «смонтировано». Кто-нибудь знает, что может быть не так?

ИЗМЕНИТЬ

С помощью Gjordis я обнаружил, что кнопка Очистить данные удаляет весь временный каталог приложения:

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

и я не смог создать его снова через getExternalCacheDir() или вручную (хотя я могу создать другие каталоги под storage/sdcard0/Android/data/).

(Android/data/com.example.app создается снова после перезагрузки устройства, но это не то решение, которое я ищу)


person Ondřej Z    schedule 15.05.2013    source источник
comment
Работает ли это после перезапуска процесса (например, вычеркните свое приложение из списка недавних задач, а затем перезапустите приложение)?   -  person CommonsWare    schedule 15.05.2013
comment
@CommonsWare: я пытался принудительно остановить приложение и удалить его из запущенных служб, но безрезультатно. Я все еще не могу снова создать каталог кеша в Android/data. Единственный способ заставить его снова работать - перезагрузить устройство - см. Отредактированный вопрос.   -  person Ondřej Z    schedule 15.05.2013
comment
Тогда это похоже на ошибку. Увы, b.android.com в данный момент не работает, поэтому я не могу подтвердить, подавал ли кто-нибудь отчет об ошибке. об этом поведении. У вас есть полноценный проект, который служит воспроизводимым тестовым примером, который вы хотели бы использовать? (ZIP, указатель на репозиторий GitHub и т. д.)   -  person CommonsWare    schedule 15.05.2013
comment
Я не могу воспроизвести ваши результаты на Nexus 7. Очистка данных не действует — результаты такие же, как и раньше.   -  person CommonsWare    schedule 15.05.2013
comment
@CommonsWare: я создал новую простую версию приложения (оно создает каталог временного кеша и записывает в него), и я также не смог воспроизвести эту ошибку. Я предполагаю, что это как-то связано с рабочим фрагментом и AsyncTask, которые отвечают за запись в кеш в исходном приложении... Спасибо за ваше время!   -  person Ondřej Z    schedule 16.05.2013
comment
Я столкнулся с той же проблемой на своем Nexus 5 (Android 5+). Решила проблему только перезагрузка устройства(   -  person pvllnspk    schedule 21.02.2015


Ответы (3)


Я столкнулся и решил эту точную проблему.

Нажатие кнопки Очистить данные приводит к тому, что Android останавливает запуск вашего приложения и удаляет всю папку приложения "mnt/sdcard/Android/data/your.package.name" .

Однако у меня был отдельный процесс, запущенный из Runtime.getRuntime().exec(), который все еще работал и записывался в эту папку. Это привело к тому, что папка застряла в заблокированном состоянии и вызвала тот же симптом, который вы описали, когда мое приложение вызвало getExternalCacheDir() . Запуск adb shell, а затем ls из папки /mnt/sdcard/Android/data показал, что папка заблокирована процессом. Запуск ps показал, что мой другой процесс все еще работает.

Решение состояло в том, чтобы правильно убить другой процесс, который все еще писал в папку, специфичную для моего приложения, перед вызовом getExternalCacheDir() .

person Robert    schedule 20.08.2014
comment
Подтверждаю, у меня было второе приложение, у которого был дескриптор открытого временного файла в каталоге кеша первого приложения, очистка данных для первого приложения приводила к зависанию папки и не могла получить доступ к папке кеша. Ответ выше должен быть одобрен. :) - person Arise; 06.10.2014

getExternalCacheDir() возвращает каталог кеша, как следует из названия. Если кэша нет, то и каталога для него нет. Этот каталог используется для временных файлов, которые вы удалили с помощью команды удаления данных. В случаях, когда на телефоне мало места, он также может сам удалить эти папки. По крайней мере, некоторые приложения для обслуживания делают это.

getExternalFilesDir() возвращает каталог для места для сохранения данных.

person Gjordis    schedule 15.05.2013
comment
Спасибо Gjordis, вы правы, Clear data удаляет не только каталог кеша, но и весь каталог пакета в Android/data. С этого момента я не могу снова создать этот каталог и вынужден перезагрузить устройство. Какие-либо предложения? - person Ondřej Z; 15.05.2013
comment
Хорошо четкие данные обычно не предназначены для многократного использования. Только при удалении, неудачных конфигурациях и т. Д. Вы уверены, что ваше приложение все еще не запущено. По моему мнению, перезапуск приложения должен воссоздать /data/.. - person Gjordis; 15.05.2013

Если вы используете getExternal*Cache*Dir(), это делается для того, чтобы хранить ВРЕМЕННО данные, которые могут быть очищены системой. Если другим приложениям в бэкстеке нужны ресурсы, система может очистить ваши данные, потому что системе нужны ресурсы. если вы хотите постоянно сохранять свои данные, используйте: File file = getExternalFilesDir(null); это внешняя память для хранения постоянных данных (например, виртуальная SD-карта).

person Jarvis    schedule 15.05.2013
comment
Проблема ОП заключается не в том, что файлы из каталога кеша исчезают, а в исчезновении самого каталога кеша, что делает приложение неработоспособным, потому что он не может повторно создать кеш. работать с. - person vbence; 01.02.2015