© 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"> - то же самое

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

  • alex_lip
  • #
  • отредактировано 5 июня 2018 г. 10:05
  • 5 июня 2018 г. 10:05

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


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


Ответы

Только авторизованные пользователи могут отвечать на форуме.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
25 июня 2018 г. 11:55
lebendig

C++ - Тест 006. Перечисления

  • Результат 100 баллов
  • Очки рейтинга 10
25 июня 2018 г. 11:24
lebendig

C++ - Тест 005. Структуры и Классы

  • Результат 100 баллов
  • Очки рейтинга 10
25 июня 2018 г. 8:48
lebendig

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

  • Результат 100 баллов
  • Очки рейтинга 10
Последние комментарии
25 июня 2018 г. 9:34
EVILEG

Как написать игру на Qt - Урок 4. Враг - смысл в выживании

Там неправильный подсчёт был по направлению и полный бардак был с поведением, эти 45 градусов исправляли ситуацию. Точную причину уже совсем не помню. А вообще все эти расчёты довольно...
25 июня 2018 г. 9:13
MarkSD

Как написать игру на Qt - Урок 4. Враг - смысл в выживании

Здравствуйте, Подскажите, пжлст, как работает этот код : QLineF lineToTarget(QPointF(0, 0), mapFromItem(target, 0, 0));  // Проводим линию от паука к мухе qreal angl...
25 июня 2018 г. 7:51
EVILEG

PyQt5 - Урок 003. QSystemTrayIcon - Как свернуть приложение в трей

Если не ошибаюсь, можно просто удалить вот эту строку central_widget.setLayout(grid_layout) Там указатель на парента передаётся в само размещение, что автоматически заменяет в размещен...
Сейчас обсуждают на форуме
25 июня 2018 г. 17:38
IscanderChe

Иконка исполняемого файла

Спасибо!
25 июня 2018 г. 13:12
Arrow

QComboBox и База данных

И если можно еще один вопрос. Таблицы во вложении. Если писать: mainModel = new QSqlRelationalTableModel(this);mainModel-&g...;
25 июня 2018 г. 7:49
EVILEG

На чём сделан этот сайт?

Добрый день! На сервере сайта установлена Ubuntu 16.04. В качестве сервера используется VDS. Хостинг-провайдер Timeweb . Сайт написан на Django/Python, для...
19 июня 2018 г. 7:56
EVILEG

как редактировать порядок обхода этементов по нажатию TAB в Qt5 qml

Что-то наподобие такого TextField { Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()}

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