© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB
4 июня 2018 г. 12:58

Открыть файл из своего приложения - приложением по умолчанию под андроид 7

Открываю файл из своего приложения так -

            QDesktopServices::openUrl(QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/temp_esd/file."+file_ext));
проверял на младших версиях андроид - работает. Сейчас проверяю на Galaxy tab2 - android 7 - пишет -

D libQuickEsd.so: (null):0 ((null)): path : "/storage/emulated/0/Documents/temp_esd/file.docx"

D libQuickEsd.so: (null):0 ((null)): Downloading is completed

W System.err: android.os.FileUriExposedException: file:///storage/emulated/0/temp_esd/file.docx exposed beyond app through Intent.getData()

W System.err: at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)

W System.err: at android.net.Uri.checkFileUriExposed(Uri.java:2346)

Видимо какие-то разрешения нужны. В тотал командере открывает приложением по умолчанию. А с моего приложения - нет. Где-то какие то пермиссии проверять?

Забавно, у Java разработчиков тоже что-то подобное вываливается на Android 7.


Из советов рекомендуют заменить начало uri с file:// на content://

А также покрутить manifest для file provider`a

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <application
        ...
        <provider
            android:name=".GenericFileProvider"
            android:authorities="${applicationId}.my.package.name.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest>
Ну и создать этот xml для provider_paths
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>
Но что-то мне кажется, что может хватить и просто смены начала URI в случае с Qt.
  • #
  • 4 июня 2018 г. 16:34

Это вроде из-за targetSdk


Вот такой вариант с targetSdkVersion 26 (у меня работал, но я не вникал что к чему)

  <provider android:name="android.support.v4.content.FileProvider" android:authorities="<к примеру имя пакета>.fileprovider" android:exported="false" android:grantUriPermissions="true">

            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/>
        </provider>
создать file_paths.xml

и в build.gradle в dependencies указать:
compile "com.android.support:support-core-utils:27.1.0"
compile "com.android.support:appcompat-v7:27.1.0"


Жестко ругается
 
на вариант от ant87 пишет
 
E AndroidRuntime: FATAL EXCEPTION: main
E AndroidRuntime: Process: org.adm.esd, PID: 8470
E AndroidRuntime: java.lang.RuntimeException: Unable to get provider android.support.v4.content.FileProvider: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.content.FileProvider" on path: DexPathList[[zip file "/data/app/org.adm.esd-2/base.apk"],nativeLibraryDirectories=[/data/app/org.adm.esd-2/lib/arm, /data/app/org.adm.esd-2/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
правда у меня не получилось компильнуть с зависимостями
compile 'com.android.support:support-core-utils:27.1.0'
compile 'com.android.support:appcompat-v7:27.1.0'
ругается
A problem occurred evaluating root project 'android-build'.

> Could not find method compile() for arguments [com.android.support:support-core-utils:27.1.0] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

 

Вариант с

.GenericFileProvider
тоже не прокатывает приложение запускается и вываливается с ошибкой
 
E AndroidRuntime: FATAL EXCEPTION: main

E AndroidRuntime: Process: org.adm.esd, PID: 11116

E AndroidRuntime: java.lang.RuntimeException: Unable to get provider org.adm.esd.GenericFileProvider: java.lang.ClassNotFoundException: Didn't find class "org.adm.esd.GenericFileProvider" on path: DexPathList[[zip file "/data/app/org.adm.esd-2/base.apk"],nativeLibraryDirectories=[/data/app/org.adm.esd-2/lib/arm, /data/app/org.adm.esd-2/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]

вот мой манифест


<provider android:name=".GenericFileProvider" android:authorities="${applicationId}.org.adm.esd.provider" android:exported="false" android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/>
        </provider>



  • #
  • отредактировано5 июня 2018 г. 8:04
  • 5 июня 2018 г. 8:04
А как заменить начало uri с file:// на content:// ?
Я же не вручную пишу file:/// - это пишет QUrl::fromLocalFile
QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation).toString().replace("file://", "content://")
нет - не обманешь ))
W System.err: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.VIEW dat=content:///storage/emulated/0/temp_esd/file.pdf cmp=com.google.android.gm/.browse.TrampolineActivity launchParam=MultiScreenLaunchParams { mDisplayId=0 mFlags=0 } } from ProcessRecord{7633793 19246:org.adm.esd/u0a155} (pid=19246, uid=10155) requires com.google.android.gm.permission.READ_GMAIL

Вообще здесь конкретно написано, какие разрешения нужны

requires com.google.android.gm.permission.READ_GMAIL
Попробуйте подправить манифест
<user-permission android :name="com.google.android.gm.permission.WRITE_GMAIL">
<user-permission android :name="com.google.android.gm.permission.AUTO_SEND">
  • #
  • отредактировано5 июня 2018 г. 10:08
  • 5 июня 2018 г. 10:04

непонятно причем тут Gmail ? Я открываю pdf или docx приложением по умолчанию для pdf или docx.

(написал вот так - <uses-permission android:name="com.google.android.gm.permission.WRITE_GMAIL"> - пишет несоответствие tag mistmach    <user-permission android:name="com.google.android.gm.permission.WRITE_GMAIL"> - то же самое

Надо все-таки с файл провайдером разбираться..

Тоже понятия не имею, у вас в ошибке написано


W System.err: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.VIEW dat=content:///storage/emulated/0/temp_esd/file.pdf cmp=com.google.android.gm/.browse.TrampolineActivity launchParam=MultiScreenLaunchParams { mDisplayId=0 mFlags=0 } } from ProcessRecord{7633793 19246:org.adm.esd/u0a155} (pid=19246, uid=10155) requires com.google.android.gm.permission.READ_GMAIL
  • #
  • 5 июня 2018 г. 11:39

этот вариант работал на всех устройствах (от Android 4.1 до 8.0), на которых я пробовал(пробовал на эмуляторах), но я записывал и считывал данные из своей папки, которая создавалась при установке программы:


manifest:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.example.fileprovider" android:exported="false" android:grantUriPermissions="true">

            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/>
        </provider>
В папке папке res создай папку xml и добавь туда file_paths.xml. Добавь res в проект в android

file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path name="my_folder" path="folder"/>
</paths>

При запуске программы автоматически создастся каталог com.example/files/
Я пробовал вариант с чтением и записью файла только по этому пути (а не вообще любого файла)

Потом
QString c_pathFolder = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
c_pathFolder += "/Android/data/com.example/files/folder/"
QDir t_dir;
t_dir.mkpath(c_pathFolder);
c_pathFolder += "text.txt";
QFile t_file(c_pathFolder);
t_file.open.....
Без этого
compile "com.android.support:support-core-utils:27.1.0"
приложение при запуске завершалось с ошибкой
По идее у Вас это не должно было работать. Дело в том, что fileprovider не просто меняет file:/// на content:/// , но и добавляет авторизацию и доступ к отдельной папке через

// Using FileProvider you must get the URI from FileProvider using your AUTHORITY
// Uri uri = Uri.fromFile(imageFileToShare);
Uri uri;
try {
uri = FileProvider.getUriForFile(QtNative.activity(), AUTHORITY, imageFileToShare);
}

и сам fileprovider добавлен в версии 22.1.0 - а это андроид 5.1
Как-то все запутанно....



  • #
  • отредактировано5 июня 2018 г. 16:49
  • 5 июня 2018 г. 16:45

я проверял только создание/чтение/запись файлов только моим тестовым приложением, другие варианты я не пробовал. Т.е. файлы находящиеся в каталоге com.example/files/folder/ я мог своим тестовым приложением создавать/открывать/удалять вне зависимости от targetSdkVersion.

Судя по всему только вставка на яве может помочь - вот документация в которой подробно описаны все пять этапов https://developer.android.com/reference/android/support/v4/content/FileProvider#GetUri


Судя по всему только вставка на яве может помочь - вот документация в которой подробно описаны все пять этапов https://developer.android.com/reference/android/support/v4/content/FileProvider#GetUri


Ответы

Только авторизованные пользователи могут отвечать на форуме.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
14 августа 2018 г. 11:29
Марк Федяшов

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат 70баллов,
  • Очки рейтинга1
14 августа 2018 г. 11:05
Марк Федяшов

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат 50баллов,
  • Очки рейтинга-4
14 августа 2018 г. 11:00
Марк Федяшов

C++ - Тест 003. Условия и циклы

  • Результат 42баллов,
  • Очки рейтинга-8
Последние комментарии
10 августа 2018 г. 13:40
Alex

Работа с триггерными функциями в PostgreSQL

Приветствую! Если вы создаете новую таблицу, почему бы просто не сделать вьюху ? Просто от одного названия "триггер" как-то не хочется его использовать, а уж кода сколько писа...
10 августа 2018 г. 11:46
Евгений Легоцкой

Bash скрипт для создания и скачивания дампа базы данных и медиа файлов с удаленного сервера

Вон оно что. Не сталкивался с таким, надо будет глянуть исходники дефолтного менеджера объектов. Возможно там кеширование просто. Пробовали добавить запись через adminer, перезапусти...
10 августа 2018 г. 11:34
Alex

Bash скрипт для создания и скачивания дампа базы данных и медиа файлов с удаленного сервера

допустим у нас есть любая таблица, созданная джангой. через админку добавляем пару записей. все ок. далее, лично в моем случае , я открываю adminer, и в эту таблицу добавляю еще одну зап...
Сейчас обсуждают на форуме
14 августа 2018 г. 7:02
Ruslan-maniak

Переключение страниц и перевод фокуса на потомка новой страницы

Большое спасибо. Подтолкнули меня на мысль вынести обработку клавиш из PathView на всю страницу. И тогда - да, ваша подсказка работает. добавил в StackView onCurrentItemChanged: currentItem.fo...
14 августа 2018 г. 6:39
Евгений Легоцкой

Как сделать аудиовизуализацию для плеера на qt?

Добрый день. Просмотрите пример в Qt Creator, который на QML, там реализовано визуализация, возможно вам понравится использовать, QML, да и кастомные интерфейсы на нём всё-таки лучше...
11 августа 2018 г. 10:12
Евгений Легоцкой

Qt C++ vs QML

Добрый день. Если Андроид предполагается, то конечно нужно использовать QML. Я занимался разработкой арканоида на QML и ещё одной игры. Пытался реализовывать логику на QML, но это ...
11 августа 2018 г. 9:24
Евгений Легоцкой

Помогите со слоями

Проверочное сообщение
9 августа 2018 г. 13:27
Иринка Садыкова

как выделять текст мышкой в qml ?

я ведь использую те же средства. единственное отличие -  ввожу текст с клавиатуры в TextArea

Рекомендуемые страницы