Команда мобильного приложения для Android должна выполнить два действия:
1. Записать PDF-документ в произвольное место.
2. Открыть форму мобильного клиента с определенным текстом, темой и (главное) с вложенным файлом, записанным в предыдущем пункте.
Я действовал следующим образом: получал директорию для записи через DocumentsDir() и записывал файл в неё, после чего вызывал следующий код:
FilePath здесь — это путь к файлу, образованный из ответа DocumentsDir() и имени файла.
Код хорошо работает до 6-го android'а включительно, но начиная с 7-го его вызов приводит к аварийному завершению приложения с ошибкой FileUriExposedException. Насколько я понял, причина в том, что с 7-й версии разработчики больше не допускают использования схемы обращения file:// в intent'ах — необходимо использовать content://. Между тем, DocumentsDir() возвращает только путь по схеме file://.
Вопрос: как можно решить эту проблему?
Я пытался получить ссылку по схеме content:// для файла, записанного в директорию приложения, но не понял, как это можно сделать — не нашел подходящих intent'ов или встроенного в 1С метода. Примеры в поиске в основном предлагают создавать свой экземпляр класса FileProvider, что видится мне невозможным изнутри 1С.
Также пытался писать файл в директории, которые возвращает метод КаталогБиблиотекиМобильногоУстройства() — этот метод возвращает ссылки по схеме content://, но в предлагаемые им директории записать файл, по-видимому, нельзя.
На случай, если кто-то будет искать решение проблемы: следует использовать объект СредстваПочты и проверить актуальность версии платформы (собрал на 8.3.12.67).
(1) В Android, что бы отправить вложенный файл, нужно записать его в общие папки, ну что бы и приложение и почтовый клиент имели к нему доступ. А что бы туда писать, нужно получить разрешение. На старых версиях API достаточно было прописать в манифесте разрешение WRITE_EXTERNAL_STORAGE. Но начиная с Android 6 нужно в явном виде запрашивать разрешение на подобные действия у пользователя.
Подробней см. тут https://developer.android.com/distribute/best-practices/develop/runtime-permissions?hl=ru
(2) Да, разрешение на запись запрашивается сразу при запуске — с этим, видимо, проблем нет.
Проблема именно с получением URI внутри 1C — если я верно понял, все что я могу сделать — это объявить намерение, а через намерения URI по пути к файлу не получить.
в намерение как раз нужно запихнуть uri.
На джаве это выглядит так
intent.putExtra(Intent.EXTRA_STREAM, uri)
Если в эту extra запихнуть путь к файлу (file://) вместо uri (content://) ошибки не будет, но и файл не прицепится, параметр просто будет проигнорирован.
uri получается или по старинке, через класс Uri, но в версиях Nougat и старше это вызывает ошибку. Там следует пользоваться классом FileProvider, предварительно объявив о своих намерениях в манифесте.
И еще такой момент, намерению желательно сделать setType("application/octet-stream"). Без него у меня родной почтовый клиент от производителя железяки не хотел прикреплять файл.
Блин, даже ЗапуститьПриложение() не срабатывает :) Неужели никто не решал?
(4), а если пересобрать приложения с более старым SDK — доступ по старой схеме (через file://) в намерениях будет работать? Или это ограничение накладывается независимо от использованного SDK.
(5) Решал, но не на 1С )) Вот тут у меня без проблем собирается csv файл, сохраняется в общий Downloads и отправляется через любую службу, поддерживающую отправку файлов.
Через file:// не будет работать вообще никак, ни на каком SDK. В это намерение всегда нужно было передавать uri, т.е. content://
Если только 1С на уровне платформы сама это парсила, то могло проканать.
(6), ясно. Я верно понимаю, что URI той же папки Downloads, например, будет отличаться от устройства к устройству и заранее его спрогнозировать без обращения к классам Java невозможно?
На случай, если кто-то будет искать решение проблемы: следует использовать объект СредстваПочты и проверить актуальность версии платформы (собрал на 8.3.12.67).