Как исправить ошибку android.os.FileUriExposedException при фотосъемке в мобильном приложении 1С на Android 7 и выше?

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

Разработка мобильных приложений на платформе 1С:Предприятие часто сопряжена с необходимостью глубокого взаимодействия с аппаратными функциями смартфона, такими как камера. Однако при переходе на новые версии операционной системы Android (начиная с 7.0 Nougat и выше) разработчики часто сталкиваются с тем, что ранее стабильно работающий код внезапно вызывает аварийное завершение работы приложения. Одной из самых распространенных ошибок является android.os.FileUriExposedException.

В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем технические ограничения безопасности современных Android-устройств и найдем оптимальное решение, которое позволит вашему мобильному приложению корректно делать снимки на любой версии ОС.

Суть проблемы: почему "падает" мобильное приложение?

Рассмотрим классическую ситуацию. Разработчик использует объект ЗапускПриложенияМобильногоУстройства, чтобы вызвать штатное системное приложение камеры через действие android.media.action.IMAGE_CAPTURE. Это делается для того, чтобы получить больше контроля над процессом съемки, например, использовать автофокус или вспышку, которые в старых версиях мобильной платформы 1С были недоступны в штатных методах.

Типичный код, который вызывает ошибку на Android 7.0+, выглядит следующим образом:


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

На устройствах с Android 5.0 или 6.0 этот код работает безупречно. Однако на Android 7.0 система выдает ошибку: android.os.FileUriExposedException: file:///sdcard/MobileData/temp.jpg exposed beyond app through clipdata.item.geturi(). Давайте проанализируем причину этого поведения.

Техническая причина: StrictMode и безопасность Uri

Начиная с API level 24 (Android 7.0), Google ввела политику безопасности StrictMode, которая запрещает передачу именных ссылок на файлы через протокол file:// между различными приложениями. Когда мы передаем в камеру путь к файлу в виде Uri, мы фактически передаем прямой адрес в файловой системе. Если приложение-получатель (в данном случае камера) не имеет явных прав доступа к папке вашего приложения, оно не сможет записать туда файл, а система безопасности Android превентивно блокирует такую передачу, вызывая исключение.

Для корректной передачи файлов в современных ОС Android требуется использовать протокол content:// и специальный компонент FileProvider. Однако в рамках разработки на встроенном языке 1С прямая настройка FileProvider в манифесте приложения и формирование защищенных ссылок крайне затруднены, так как это требует низкоуровневого взаимодействия с Java API.

Решение проблемы: Переход на встроенные средства мультимедиа

Многие разработчики использовали внешние интенты (вызовы сторонних приложений) только потому, что штатный метод 1С СредстваМультимедиа.СделатьФотоснимок долгое время имел ограниченный функционал (отсутствие управления вспышкой, разрешением и т.д.). Однако прогресс не стоит на месте.

Проанализируем современные возможности платформы 1С (начиная с версии 8.3.13 и выше). В этих версиях разработчики 1С значительно расширили возможности объекта СредстваМультимедиа. Теперь использование внешних программ камеры становится избыточным и даже вредным из-за проблем с безопасностью Android.

Пошаговая инструкция по реализации фотосъемки

Разберем, как правильно реализовать фотосъемку, используя современные возможности платформы, которые гарантированно работают на Android 7, 8, 10 и выше.

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

Шаг 2. Использование параметров съемки. Чтобы решить проблему со вспышкой, на которую жаловались многие разработчики, используем объект ПараметрыСнятияФотоснимка. Посмотрим на пример кода:


// Проверим, поддерживается ли фотосъемка на устройстве
Если СредстваМультимедиа.ПоддерживаетсяФотоснимок() Тогда
    
    // Создаем объект параметров
    ПараметрыФото = Новый ПараметрыСнятияФотоснимка;
    
    // Устанавливаем использование вспышки
    // Доступные значения: Авто, Включена, Выключена
    ПараметрыФото.ИспользованиеВспышки = ИспользованиеВспышкиМобильногоУстройства.Авто;
    
    // Устанавливаем разрешение (необязательно)
    // Можно выбрать высокое для качественных фото или низкое для экономии трафика
    ПараметрыФото.Разрешение = РазрешениеВидеоФотосъемки.Высокое;
    
    // Вызываем метод съемки
    ДанныеСнимка = СредстваМультимедиа.СделатьФотоснимок(ПараметрыФото);
    
    Если ДанныеСнимка <> Неопределено Тогда
        // Получаем двоичные данные картинки
        ДвоичныеДанныеКартинки = ДанныеСнимка.ПолучитьДвоичныеДанные();
        // Дальнейшая логика сохранения в базу или файл
    КонецЕсли;
    
КонецЕсли;

Преимущества штатного метода перед внешним вызовом

  1. Совместимость: Платформа 1С сама берет на себя взаимодействие с FileProvider и формирование правильных content:// ссылок внутри нативного кода. Вам не нужно беспокоиться об ошибке FileUriExposedException.
  2. Стабильность: Ваше приложение не закрывается (не переходит в фоновый режим) полностью, что снижает риск того, что ОС Android "прибьет" процесс 1С из-за нехватки памяти, пока открыта камера.
  3. Скорость разработки: Вам не нужно обрабатывать возврат из внешнего приложения и искать файл на диске. Вы получаете объект ДанныеМультимедиа сразу в коде.

Оптимизация производительности и "медленной" работы

Некоторые разработчики отмечают, что штатный метод СделатьФотоснимок работает медленнее, чем прямое обращение к IMAGE_CAPTURE. Выясним причину: часто задержка возникает не в момент срабатывания затвора, а в момент передачи огромного массива данных из нативного слоя Android во внутреннюю память 1С.

Чтобы ускорить работу, воспользуйтесь следующими советами:

Таким образом, решением проблемы FileUriExposedException является отказ от низкоуровневых манипуляций с интентами в пользу штатных механизмов платформы 1С версии 8.3.13 и выше. Это не только исправляет ошибку, но и делает код более надежным и переносимым между различными моделями смартфонов.

← На главную