Всем привет.
Насчёт дублирования снимка (своя директория + стандартная), если кому ещё надо. Просто чтобы сэкономить ваше время.
Сразу скажу, что проконтролировать этот баг на всех девайсах невозможно и универсального решения похоже нет.
Почему это происходит.
Всё зависит от системного приложения работы с камерой. Даже если мы явно отправим ему путь для сохранения снимка, например даже вот так (вариант от
httpdispatch):
Код: Выделить всё
mUploadImageFile = getNextFileName("upload_");
// this is a hack for some
// devices taken from here
// http://thanksmister.com/2012/03/16/android_null_data_camera_intent/
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE,
mUploadImageFile.getName());
values.put(MediaStore.Images.Media.DATA,
mUploadImageFile.getAbsolutePath());
Intent intent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getActivity()
.getContentResolver()
.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, REQUEST_CAMERA);
системное приложение (существенное множество их разновидностей) создаст дефолтный снимок ещё и в своей дефолтной директории.
Как бы можно было это обойти.
1. Удалить дубликат снимка в onActivityResult, вытащив Uri из intent.getData().
Может не получиться по следующим причинам:
- Ещё одно множество системных приложений просто возвращает NULL в intent.getData() (по идее это нормально, если вы явно указываете MediaStore.EXTRA_OUTPUT, но возможны исключения в обе стороны).
- В intent.getData() может оказаться URI, который мы сами туда положили (то есть мы удалим не копию, а снимок из нужной нам директории).
2. На SOF часто советуют удалять последний по дате снимок из дефолтной галереи, например, вот так:
Код: Выделить всё
public void deleteLastCapturedImage() {
String[] projection = {
MediaStore.Images.ImageColumns.SIZE,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATA,
BaseColumns._ID
};
Cursor c = null;
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
try {
if (u != null) {
c = managedQuery(u, projection, null, null, null);
}
if ((c != null) && (c.moveToLast())) {
ContentResolver cr = getContentResolver();
int i = cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=" + c.getString(c.getColumnIndex(BaseColumns._ID)), null);
Log.v(LOG_TAG, "Number of column deleted : " + i);
}
} finally {
if (c != null) {
c.close();
}
}
}
и просто выполнить этот метод в onActivityResult, когда убедимся, что нужный снимок есть в нашей директории.
Этим методом я пользоваться не советую по причине того, что очередное множество системных приложений реагирует на MediaStore.ACTION_IMAGE_CAPTURE, на удивление, так как нам надо и не создаёт в дефлтной директории копию нашего снимка. Отследить появление копии программно, в принципе, можно (проверять дату последнего файла в галерее, например), но не знаю, стоит ли на столько уродовать код.
Что же делать?
Как вариант, можно не указывать явный путь для сохранения, то есть опустить строку:
Код: Выделить всё
intent.putExtra(MediaStore.EXTRA_OUTPUT, generateFileUri());
Затем вытащить uri сохранённого файла в onActivityResult, скопировать снимок из дефолтной директории в нужную и удалить оригинал. Но бывало так, что intent.getData() и в такой ситуации показывал мне NULL. То есть, может и не работать.
Я, например, не хочу больше мучиться с нативным приложением и планирую использовать кастомную обработку камеры (уроки 132-134). Это и полезнее, и можно гораздо эффективнее фиксить баги
Если кто-то нашёл универсальное решение для описанной проблемы - буду рад, если поделитесь )