При разработке мобильных приложений на платформе 1С для устройств под управлением Android разработчики часто сталкиваются с проблемой сохранения файлов в каталоги, которые доступны обычным файловым менеджерам или другим приложениям. Давайте рассмотрим эту проблему подробнее, выясним её причины и проанализируем возможные решения и обходные пути.
Суть проблемы: Недоступность каталогов для сохранения файлов
Представьте ситуацию: вы разрабатываете мобильное приложение на платформе 1С и используете стандартные методы для сохранения файлов, например, с помощью функции ПолучитьФайлССервераАсинх и объекта ПараметрыДиалогаПолученияФайлов():
ПолучитьФайлССервераАсинх(АдресВоВременномХранилище, "Наименование.Расширение", новый ПараметрыДиалогаПолученияФайлов());
Ожидается, что после вызова этого метода или использования Новый ДиалогВыбораФайла() в режиме РежимДиалогаВыбораФайла.Сохранение или РежимДиалогаВыбораФайла.ВыборКаталога, пользователю будет предложен системный диалог выбора каталога, где он сможет указать любую удобную для него папку, такую как "Загрузки", "Документы" или "Изображения". Однако на практике, особенно на современных версиях Android (начиная с Android 11 и выше, например, Android 12), мы сталкиваемся со следующими сложностями:
Диалог выбора файла или каталога действительно появляется, но он показывает исключительно внутренние папки приложения 1С, что значительно затрудняет копирование файлов и каталогов между Клиентом и Сервером. Эти папки обычно расположены в изолированном хранилище приложения и недоступны для просмотра или управления через стандартные файловые менеджеры Android.
Попытки указать в параметрах диалога системные каталоги, используя функции РабочийКаталогДанныхПользователя() или КаталогДокументов(), не приводят к желаемому результату, хотя на десктопных версиях выгрузка внешних отчетов и обработок в произвольные папки работает корректно. Диалог всё равно предлагает внутренние, недоступные папки.
Парадоксально, но функция ПоместитьФайлНаСерверАсинх, которая используется для выбора файла на устройстве и его загрузки, часто работает корректно со стандартными каталогами, позволяя пользователю выбирать файлы из общедоступных мест. Это создаёт впечатление непоследовательности в поведении.
Сохранение файла во временный каталог приложения (например, через КаталогВременныхФайлов()) и последующее его открытие, например, для просмотра изображения, действительно возможно. Однако, даже после открытия, стандартные средства просмотра фотографий или другие системные утилиты не позволяют легко скопировать или переместить этот файл в общедоступное место, что делает такой подход неполноценным решением.
В чем же причина такого поведения и как с этим бороться, используя стандартные методы?
Основная причина: Политика безопасности Android Scoped Storage
Ключевая причина возникновения описанных проблем кроется в значительно усиленной политике безопасности операционной системы Android, известной как Scoped Storage (ограниченное хранилище). Эта политика была введена Google для повышения конфиденциальности пользователей и улучшения безопасности данных приложений.
Что такое Scoped Storage?
Внедрение и обязательность: Scoped Storage был представлен в Android 10, а с Android 11 (API уровня 30) его использование стало обязательным для всех новых приложений и обновлений, публикуемых в Google Play. Это означает, что любое приложение, нацеленное на Android 11 или выше, должно соответствовать этой политике.
Изолированные каталоги: По умолчанию, каждое приложение теперь имеет ограниченный доступ к файловой системе устройства. Оно может свободно читать и записывать файлы только в свои собственные, изолированные каталоги. Эти каталоги обычно расположены по пути /data/data/<имя_приложения>/files или /Android/data/<имя_приложения>/files и недоступны для других приложений или стандартных файловых менеджеров без специальных разрешений. Именно эти внутренние папки и показывает диалог выбора файла 1С.
Доступ к медиафайлам: Приложения могут также получать доступ к определенным типам медиафайлов (изображения, видео, аудио), которые они сами создали, через MediaStore API. Для доступа к медиафайлам, созданным другими приложениями, требуются явные разрешения пользователя и использование MediaStore API.
Защита конфиденциальности: Цель Scoped Storage — предотвратить несанкционированный доступ к данным приложений, минимизировать цифровой след приложения на устройстве и защитить конфиденциальность пользователя. Приложения больше не могут свободно просматривать все файлы на устройстве.
Отмена `requestLegacyExternalStorage`: В ранних версиях Android 10 был доступен флаг манифеста requestLegacyExternalStorage, который позволял приложениям временно обходить ограничения Scoped Storage. Однако, начиная с Android 11, этот флаг игнорируется системой, и приложениям приходится полностью адаптироваться к новой модели.
Разрешение "Доступ ко всем файлам" (MANAGE_EXTERNAL_STORAGE)
Вы упомянули, что включили функциональность "Доступ ко всем файлам" в мобильном приложении 1С. Это разрешение соответствует разрешению Android MANAGE_EXTERNAL_STORAGE. Давайте разберем его особенности:
Строгое регулирование Google Play: Разрешение MANAGE_EXTERNAL_STORAGE является очень мощным и предоставляет приложению полный доступ ко всему внешнему хранилищу устройства. Google Play строго регулирует выдачу этого разрешения. Оно предназначено только для приложений, для которых широкий доступ к файлам является основной функциональностью.
Примеры разрешенных приложений: К таким категориям относятся файловые менеджеры, приложения для резервного копирования и восстановления, антивирусные программы, приложения для управления документами, утилиты шифрования/дешифрования файлов.
Требования к публикации: Если ваше приложение не относится к одной из этих основных категорий, даже если вы запросите и включите это разрешение, Google Play может отклонить ваше приложение при публикации или удалить его из магазина. Для получения этого разрешения необходимо заполнить специальную форму декларации разрешений в Play Console, подробно объясняя необходимость такого широкого доступа.
Не панацея для 1С-приложений: Для большинства бизнес-приложений на 1С, которые не являются файловыми менеджерами по своей сути, получение разрешения MANAGE_EXTERNAL_STORAGE будет затруднительным и, скорее всего, не будет одобрено Google Play. Поэтому мы не можем рассматривать его как универсальное решение для сохранения файлов.
Взаимодействие 1С с файловой системой Android
Функции 1С, такие как ПолучитьФайлССервераАсинх, ПараметрыДиалогаПолученияФайлов(), или Новый ДиалогВыбораФайла() в режиме выбора каталога, вероятно, используют системные диалоги Android. Однако из-за политики Scoped Storage эти диалоги по умолчанию ограничиваются:
Внутренними папками приложения, к которым у него есть полный доступ.
Медиа-коллекциями, которые приложение имеет право изменять (если оно создало эти медиафайлы).
Это объясняет, почему вы видите только внутренние папки, а не общедоступные каталоги. Функция ПоместитьФайлНаСерверАсинх, наоборот, работает с файлами, которые пользователь сам выбирает из файловой системы. В этом сценарии система Android предоставляет приложению временный доступ к выбранному пользователем файлу, что соответствует более современным политикам безопасности.
Возможные подходы и решения
Теперь, когда мы понимаем корень проблемы, давайте рассмотрим возможные подходы к её решению или обходу.
1. Использование старой версии мобильной платформы 1С
Некоторые разработчики обнаружили, что откат к более старым версиям мобильной платформы 1С может временно решить проблему, поскольку эти версии могли быть скомпилированы с более низким уровнем API Android, который не требовал строгого соблюдения Scoped Storage.
Суть подхода:
Как указал один из участников форума (Сообщение 7), использование сборки под мобильную платформу, например, версии 8.3.16 (при этом сервер мобильного клиента может быть более новой версии, например, 8.3.22.2283), позволяло сохранять файлы без сбоев на протяжении длительного времени, даже на Android 11.
Как это применить:
Если ваша текущая мобильная платформа, например, 8.3.24.40, вызывает проблемы, рассмотрите возможность создания сборки мобильного приложения с более старой версией мобильной платформы 1С.
Установите соответствующую версию мобильной платформы на вашем компьютере для разработки и сборки APK.
Соберите ваше мобильное приложение с использованием этой старой платформы.
Протестируйте полученный APK на целевых устройствах Android, чтобы убедиться, что сохранение файлов работает как ожидалось.
Преимущества:
Может быстро решить проблему сохранения файлов в общедоступные каталоги, если это критично для вашей бизнес-логики.
Не требует значительных изменений в коде 1С.
Недостатки:
Ограниченный срок действия: Этот метод является временным "костылём". Google Play постоянно ужесточает требования к минимальному уровню API. Рано или поздно, старая версия платформы перестанет проходить проверку при публикации в Google Play, или возникнут проблемы совместимости с новыми версиями Android.
Уязвимости безопасности: Использование старых версий платформы может нести риски безопасности, так как они могут содержать необнаруженные уязвимости, которые уже были исправлены в более новых версиях.
Ограниченная функциональность: Вы можете потерять доступ к новым функциям и улучшениям, которые были добавлены в более новых версиях мобильной платформы 1С.
Непредсказуемость: Нет гарантии, что даже старые версии платформы будут стабильно работать на самых свежих версиях Android в долгосрочной перспективе, поскольку сама ОС постоянно меняется.
2. Ручной перенос файлов пользователем из внутренней папки
Это не программное решение, а скорее обходной путь для конечного пользователя, который может потребоваться в безвыходной ситуации.
Суть подхода:
Даже если мобильное приложение 1С сохраняет файлы во внутреннюю папку, некоторые пользователи на Android 12 и выше могут получить к ней доступ через стандартный "Диспетчер файлов" или аналогичные приложения. Обычно эти папки находятся по пути Android/data/<имя_пакета_приложения_1С>.
Как это применить:
Сохраните файл во временный или внутренний каталог приложения 1С. Для этого можно использовать КаталогВременныхФайлов() или другие функции, возвращающие внутренние пути.
Информируйте пользователя, что файл сохранен во внутреннем хранилище приложения и ему потребуется вручную переместить его.
Пользователь должен открыть свой файловый менеджер. На некоторых устройствах Android, чтобы увидеть папку Android/data, нужно специально нажать "просмотреть" или предоставить файловому менеджеру дополнительные разрешения.
Пользователь находит папку вашего приложения в Android/data/ (например, Android/data/com.e1c.myapplication/files/, если это ваше приложение).
Из этой папки пользователь вручную копирует или перемещает нужный файл в общедоступные каталоги, такие как "Загрузки", "Документы" или "Изображения".
Преимущества:
Не требует изменений в коде 1С, если сохранение во внутреннюю папку уже работает.
Предоставляет пользователю возможность в конечном итоге получить доступ к файлу.
Недостатки:
Неудобство для пользователя: Это многошаговый и неочевидный процесс, который может быть сложным для неподготовленных пользователей.
Зависимость от файлового менеджера: Доступ к папке Android/data может отличаться или быть ограничен в зависимости от версии Android и используемого файлового менеджера.
Не автоматизированное решение: Не является программным способом решения проблемы.
3. Взаимодействие с нативными Android API (Storage Access Framework и MediaStore)
Это наиболее правильный и "современный" подход для сохранения файлов в общедоступные каталоги на Android, соответствующий рекомендациям Google. Однако он требует глубокой интеграции или использования расширений.
Суть подходов:
Storage Access Framework (SAF): SAF позволяет приложению взаимодействовать с поставщиками документов, предоставляемыми другими приложениями (например, локальным хранилищем, облачными сервисами). Приложение не получает прямой доступ к файловой системе; вместо этого оно запрашивает у пользователя разрешение на работу с файлом или папкой через системный диалог выбора. Пользователь сам выбирает место сохранения файла.
MediaStore API: Этот API предназначен специально для работы с медиафайлами (изображениями, видео, аудио) и документами. Он позволяет приложению добавлять файлы в медиаколлекции устройства, после чего эти файлы становятся доступны другим приложениям (галереям, плеерам) и файловым менеджерам. MediaStore также предоставляет механизмы для получения доступа к файлам, созданным другими приложениями, с разрешения пользователя.
Как это применить (потенциально, через расширения 1С):
Сохраните файл из временного хранилища 1С.
Вам потребуется разработать внешнюю компоненту или расширение для мобильной платформы 1С (или использовать готовую многофункциональную компоненту для мобильной платформы). Эта компонента должна быть написана на нативном языке Android (Java/Kotlin) и использовать SAF или MediaStore API.
В компоненте вы инициируете системный диалог выбора файла/каталога (например, через Intent.ACTION_CREATE_DOCUMENT для SAF) или добавляете файл в MediaStore (например, через ContentResolver.insert()).
Пользователь взаимодействует с системным диалогом, выбирая, куда сохранить файл.
После того как пользователь выбрал место, нативная компонента получает URI (Uniform Resource Identifier) выбранного места и записывает туда данные файла из 1С.
Преимущества:
Соответствие требованиям Google: Это полностью соответствует современным политикам безопасности Android и требованиям Google Play.
Удобство для пользователя: Пользователь получает стандартный, привычный диалог выбора места сохранения.
Надежность: Решение будет стабильно работать на всех современных версиях Android.
Недостатки:
Сложность реализации: Требует разработки нативной компоненты на Java/Kotlin, что выходит за рамки стандартной разработки на 1С.
Время и ресурсы: Разработка, тестирование и поддержка такой компоненты требует значительных усилий и специфических знаний.
Зависимость от платформы 1С: На данный момент (версия 8.3.24) мобильная платформа 1С не предоставляет прямых встроенных механизмов для работы с SAF/MediaStore API для сохранения файлов в произвольные общедоступные каталоги.
4. Сохранение во временный каталог приложения и вызов сторонних приложений
Этот подход частично решает задачу просмотра, но не сохранения в общедоступные папки.
Суть подхода:
Сохраните файл во временный каталог приложения 1С, а затем используйте метод ЗапускПриложениеМобильногоУстройства, чтобы открыть его с помощью стандартного просмотрщика или другого приложения.
Как это применить:
ИмяФайлаНаУстройстве = КаталогВременныхФайлов() + "ИмяМоегоФайла.Расширение";
// Предположим, файл уже записан по этому пути.
ЗапускПриложениеМобильногоУстройства(ИмяФайлаНаУстройстве);
Преимущества:
Позволяет пользователю просмотреть или обработать файл с помощью установленных на устройстве приложений.
Просто в реализации на 1С.
Недостатки:
Файл остается во временном хранилище: После просмотра файл всё ещё находится в изолированной временной папке приложения.
Проблемы с копированием/сохранением: Как вы уже заметили, даже если просмотрщик откроется, он может не иметь функции "Сохранить как..." или "Копировать в...", которая позволила бы перенести файл в общедоступное место. Это связано с тем, что просмотрщик получает временный доступ к файлу, но не к папке, где он расположен.
Не решает проблему сохранения: Это решение для просмотра/обработки, но не для постоянного сохранения в общедоступной директории.
5. Передача файлов через веб-сервисы
Если цель не просто локально сохранить файл, а обменяться им с другим устройством (например, с компьютером или другим мобильным устройством), можно использовать веб-сервисы.
Суть подхода:
Вместо сохранения файла на самом мобильном устройстве в общедоступном каталоге, мобильное приложение 1С может отправить файл на внешний сервер (через веб-сервис или HTTP-запрос). С этого сервера файл затем может быть загружен на другие устройства.
Как это применить:
Сохраните файл из временного хранилища 1С.
Используйте объект HTTPЗапрос или ВебСервис для отправки файла на ваш сервер.
На сервере реализуйте механизм приема файла и его сохранения.
С других устройств пользователи могут подключиться к серверу и загрузить нужный файл.
Преимущества:
Полностью обходит ограничения Android: Файл не хранится на устройстве в общедоступном каталоге.
Централизованное хранение: Файлы хранятся на сервере, что удобно для управления и резервного копирования.
Кроссплатформенность: Файлы доступны с любого устройства, имеющего доступ к серверу.
Недостатки:
Требует наличия сервера: Необходимо иметь настроенный веб-сервер и реализовать логику обмена файлами.
Зависимость от сети: Требуется активное интернет-соединение для обмена файлами.
Не решает задачу локального сохранения: Если пользователю нужен прямой доступ к файлу на мобильном устройстве без сети, этот метод не подходит.
Заключение
Проблема с выбором каталога для сохранения файлов в мобильном приложении 1С на Android (особенно на версиях 11 и выше) — это прямое следствие эволюции операционной системы Android в сторону усиления безопасности и конфиденциальности пользовательских данных. Политика Scoped Storage кардинально изменила подходы к работе с файловой системой.
Мы видим, что на данный момент универсального и простого решения, полностью реализуемого средствами 1С и соответствующего всем требованиям Android, нет. Разработчикам приходится выбирать между:
Временными обходными путями (использование старых версий платформы).
Неудобными для пользователя ручными действиями.
Сложными в реализации, но правильными архитектурно решениями (разработка нативных расширений, использующих SAF/MediaStore API).
Изменением логики работы с файлами, перенося их на серверное хранение.
Фирма "1С", вероятно, продолжит адаптировать свою мобильную платформу к меняющимся требованиям Google. В перспективе стоит ожидать появления встроенных механизмов, которые позволят более удобно работать с современными Android API для управления файлами. До тех пор, разработчикам предстоит выбирать наиболее подходящий "костыль" или инвестировать в разработку нативных расширений.