Почему не сохраняется фото и зависает камера при подтверждении снимка в мобильном приложении 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке мобильных решений на платформе 1С часто возникает необходимость делать фотоснимки и сохранять их в информационную базу. Нередко разработчики используют вызов системного интента Android через объект ЗапускПриложенияМобильногоУстройства. Однако в процессе работы можно столкнуться с неприятной ситуацией: окно системной камеры открывается, кадр фиксируется, но при нажатии на кнопку подтверждения (галочку) ничего не происходит — камера не закрывается и не передает управление обратно в мобильное приложение 1С.

В этой статье мы подробно разберем, почему возникает такое поведение, как правильно формировать путь для сохранения снимка и какие альтернативные штатные средства платформы 1С предпочтительнее использовать.

Анализ исходного кода и проявление проблемы

Рассмотрим типовой пример вызова стороннего приложения камеры, с которым возникла ошибка:


НовВз = Новый ЗапускПриложенияМобильногоУстройства("android.media.action.IMAGE_CAPTURE");
НовВз.ДополнительныеДанные.Добавить("output", ФайлКартинки, "Uri");

Если НовВз.Запустить(Истина) <> 0 Тогда 
    Данные = Новый ДвоичныеДанные(ПутьКФайлуКартинки);
    СсылкаФото = СоздатьНовыйФайл(Данные, "jpeg", "image", ТекВид, Ложь);
Иначе
    Сообщить("Фото не сделано!");
КонецЕсли;

При передаче параметра output в качестве URI передавался путь следующего вида:

file:///storage/sdcard/ИмяФайла.jpeg

В такой конфигурации при нажатии на кнопку отмены управление штатно возвращается в 1С, но при подтверждении снимка кнопка перестает реагировать на нажатия. Проанализируем ключевые причины такого поведения операционной системы Android.

Причины сбоя при подтверждении фотоснимка

Выясним причину, из-за которой стороннее приложение камеры не может завершить свою работу:

  1. Некорректный или несуществующий путь к файлу. Прямой путь /storage/sdcard/ на большинстве современных устройств Android не существует или заблокирован для прямой записи без прав суперпользователя. Если приложение камеры пытается записать байты снимка по несуществующему или недоступному пути, возникает внутреннее исключение ввода-вывода (IOException), из-за чего процесс камеры не может вернуть статус RESULT_OK.
  2. Ограничения прав доступа (Runtime Permissions). Начиная с Android 6.0 Marshmallow, доступ к файловой системе требует динамических разрешений. Если у приложения камеры или самого мобильного клиента 1С нет права на запись во внешнее хранилище (WRITE_EXTERNAL_STORAGE), операция сохранения блокируется системой.
  3. Отсутствие целевого каталога. Если указать путь к вложенной папке, которая еще не была предварительно создана в файловой системе, штатные камеры большинства прошивок не создают директории автоматически, что приводит к сбою сохранения.
  4. Особенности прошивки устройства. Некоторые вендорные приложения камеры (в частности, в прошивках ASUS ZenUI) не обрабатывают нестандартные пути без явного указания общедоступных каталогов.

Способ 1. Исправление пути к общедоступной директории

Разберем по шагам, как исправить путь к файлу при вызове системного намерения. Самым надежным решением является сохранение снимка в гарантированно существующий публичный каталог, например, Downloads или DCIM.

Сформируем корректный URI, указав путь к публичной папке загрузок:


ПутьКФайлу = "/sdcard/Download/" + ИмяФайла + ".jpg";
ФайлКартинки = "file://" + ПутьКФайлу;

// Проверяем существование файла или каталога перед запуском
ПроверяемыйФайл = Новый Файл(ПутьКФайлу);

НовВз = Новый ЗапускПриложенияМобильногоУстройства("android.media.action.IMAGE_CAPTURE");
НовВз.ДополнительныеДанные.Добавить("output", ФайлКартинки, "Uri");

Если НовВз.Запустить(Истина) <> 0 Тогда 
    Если ПроверяемыйФайл.Существует() Тогда
        Данные = Новый ДвоичныеДанные(ПутьКФайлу);
        // Выполняем сохранение данных в базу 1С
        СсылкаФото = СоздатьНовыйФайл(Данные, "jpeg", "image", ТекВид, Ложь);
        
        // Удаляем временный файл с диска после записи в базу
        УдалитьФайлы(ПутьКФайлу);
    КонецЕсли;
Иначе
    Сообщить("Фото не сделано!");
КонецЕсли;

Важный момент: Убедитесь, что в настройках операционной системы Android (в разделе Настройки -> Приложения -> Разрешения) приложению 1С и приложению камеры предоставлен доступ к разделу «Память» (Хранилище) и «Камера».

Способ 2. Использование встроенного объекта «СредстваМультимедиа»

Чтобы избежать проблем с различиями файловых путей на разных версиях Android и прошивках производителей, рекомендуется использовать штатный платформенный механизм 1С — менеджер СредстваМультимедиа.

Посмотрим на пример штатной реализации фотосъемки:


Если СредстваМультимедиа.ПоддерживаетсяФотоснимок() Тогда
    ПараметрыСнимка = Новый ПараметрыСнимок;
    ПараметрыСнимка.Качество = 80;
    
    Результат = СредстваМультимедиа.СделатьФотоснимок(ПараметрыСнимка);
    Если Результат <> Неопределено Тогда
        ДанныеФото = Результат.ПолучитьДвоичныеДанные();
        СсылкаФото = СоздатьНовыйФайл(ДанныеФото, "jpeg", "image", ТекВид, Ложь);
    КонецЕсли;
Иначе
    Сообщить("Фотосъемка не поддерживается на данном устройстве.");
КонецЕсли;

Штатный метод СредстваМультимедиа.СделатьФотоснимок() автоматически обрабатывает все нюансы взаимодействия с камерой Android, запрашивает необходимые разрешения и возвращает объект ДанныеМультимедиа, из которого двоичные данные извлекаются напрямую без ручного манипулирования путями файловой системы.

← На главную