При разработке мобильных решений на платформе 1С часто возникает необходимость делать фотоснимки и сохранять их в информационную базу. Нередко разработчики используют вызов системного интента Android через объект ЗапускПриложенияМобильногоУстройства. Однако в процессе работы можно столкнуться с неприятной ситуацией: окно системной камеры открывается, кадр фиксируется, но при нажатии на кнопку подтверждения (галочку) ничего не происходит — камера не закрывается и не передает управление обратно в мобильное приложение 1С.
В этой статье мы подробно разберем, почему возникает такое поведение, как правильно формировать путь для сохранения снимка и какие альтернативные штатные средства платформы 1С предпочтительнее использовать.
Рассмотрим типовой пример вызова стороннего приложения камеры, с которым возникла ошибка:
НовВз = Новый ЗапускПриложенияМобильногоУстройства("android.media.action.IMAGE_CAPTURE");
НовВз.ДополнительныеДанные.Добавить("output", ФайлКартинки, "Uri");
Если НовВз.Запустить(Истина) <> 0 Тогда
Данные = Новый ДвоичныеДанные(ПутьКФайлуКартинки);
СсылкаФото = СоздатьНовыйФайл(Данные, "jpeg", "image", ТекВид, Ложь);
Иначе
Сообщить("Фото не сделано!");
КонецЕсли;
При передаче параметра output в качестве URI передавался путь следующего вида:
file:///storage/sdcard/ИмяФайла.jpeg
В такой конфигурации при нажатии на кнопку отмены управление штатно возвращается в 1С, но при подтверждении снимка кнопка перестает реагировать на нажатия. Проанализируем ключевые причины такого поведения операционной системы Android.
Выясним причину, из-за которой стороннее приложение камеры не может завершить свою работу:
/storage/sdcard/ на большинстве современных устройств Android не существует или заблокирован для прямой записи без прав суперпользователя. Если приложение камеры пытается записать байты снимка по несуществующему или недоступному пути, возникает внутреннее исключение ввода-вывода (IOException), из-за чего процесс камеры не может вернуть статус RESULT_OK.WRITE_EXTERNAL_STORAGE), операция сохранения блокируется системой.Разберем по шагам, как исправить путь к файлу при вызове системного намерения. Самым надежным решением является сохранение снимка в гарантированно существующий публичный каталог, например, Downloads или DCIM.
Сформируем корректный URI, указав путь к публичной папке загрузок:
ПутьКФайлу = "/sdcard/Download/" + ИмяФайла + ".jpg";
ФайлКартинки = "file://" + ПутьКФайлу;
// Проверяем существование файла или каталога перед запуском
ПроверяемыйФайл = Новый Файл(ПутьКФайлу);
НовВз = Новый ЗапускПриложенияМобильногоУстройства("android.media.action.IMAGE_CAPTURE");
НовВз.ДополнительныеДанные.Добавить("output", ФайлКартинки, "Uri");
Если НовВз.Запустить(Истина) <> 0 Тогда
Если ПроверяемыйФайл.Существует() Тогда
Данные = Новый ДвоичныеДанные(ПутьКФайлу);
// Выполняем сохранение данных в базу 1С
СсылкаФото = СоздатьНовыйФайл(Данные, "jpeg", "image", ТекВид, Ложь);
// Удаляем временный файл с диска после записи в базу
УдалитьФайлы(ПутьКФайлу);
КонецЕсли;
Иначе
Сообщить("Фото не сделано!");
КонецЕсли;
Важный момент: Убедитесь, что в настройках операционной системы Android (в разделе Настройки -> Приложения -> Разрешения) приложению 1С и приложению камеры предоставлен доступ к разделу «Память» (Хранилище) и «Камера».
Чтобы избежать проблем с различиями файловых путей на разных версиях Android и прошивках производителей, рекомендуется использовать штатный платформенный механизм 1С — менеджер СредстваМультимедиа.
Посмотрим на пример штатной реализации фотосъемки:
Если СредстваМультимедиа.ПоддерживаетсяФотоснимок() Тогда
ПараметрыСнимка = Новый ПараметрыСнимок;
ПараметрыСнимка.Качество = 80;
Результат = СредстваМультимедиа.СделатьФотоснимок(ПараметрыСнимка);
Если Результат <> Неопределено Тогда
ДанныеФото = Результат.ПолучитьДвоичныеДанные();
СсылкаФото = СоздатьНовыйФайл(ДанныеФото, "jpeg", "image", ТекВид, Ложь);
КонецЕсли;
Иначе
Сообщить("Фотосъемка не поддерживается на данном устройстве.");
КонецЕсли;
Штатный метод СредстваМультимедиа.СделатьФотоснимок() автоматически обрабатывает все нюансы взаимодействия с камерой Android, запрашивает необходимые разрешения и возвращает объект ДанныеМультимедиа, из которого двоичные данные извлекаются напрямую без ручного манипулирования путями файловой системы.