alex_lip
alex_lip4 июня 2018 г. 8: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)

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

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

15
Evgenii Legotckoi
  • 4 июня 2018 г. 9:08

Забавно, у 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.
    a
    • 4 июня 2018 г. 12: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"


      alex_lip
      • 5 июня 2018 г. 3:21
      Жестко ругается
       
      на вариант от 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]]

        alex_lip
        • 5 июня 2018 г. 3:25
        вот мой манифест


        <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>
        



          alex_lip
          • 5 июня 2018 г. 4:04
          • (ред.)
          А как заменить начало uri с file:// на content:// ?
          Я же не вручную пишу file:/// - это пишет QUrl::fromLocalFile
            Evgenii Legotckoi
            • 5 июня 2018 г. 4:12
            QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation).toString().replace("file://", "content://")
              alex_lip
              • 5 июня 2018 г. 4:45
              нет - не обманешь ))
              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
                Evgenii Legotckoi
                • 5 июня 2018 г. 5:20

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

                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">
                  alex_lip
                  • 5 июня 2018 г. 6: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"> - то же самое

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

                    Evgenii Legotckoi
                    • 5 июня 2018 г. 6: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
                      a
                      • 5 июня 2018 г. 7: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"
                      приложение при запуске завершалось с ошибкой
                        alex_lip
                        • 5 июня 2018 г. 10:32
                        По идее у Вас это не должно было работать. Дело в том, что 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
                        Как-то все запутанно....



                          a
                          • 5 июня 2018 г. 12:45
                          • (ред.)

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

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


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


                                Комментарии

                                Только авторизованные пользователи могут публиковать комментарии.
                                Пожалуйста, авторизуйтесь или зарегистрируйтесь
                                e
                                • ehot
                                • 31 марта 2024 г. 21:29

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

                                • Результат:78баллов,
                                • Очки рейтинга2
                                B

                                C++ - Тест 002. Константы

                                • Результат:16баллов,
                                • Очки рейтинга-10
                                B

                                C++ - Тест 001. Первая программа и типы данных

                                • Результат:46баллов,
                                • Очки рейтинга-6
                                Последние комментарии
                                k
                                kmssr9 февраля 2024 г. 2:43
                                Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                АК
                                Анатолий Кононенко5 февраля 2024 г. 9:50
                                Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                EVA
                                EVA25 декабря 2023 г. 18:30
                                Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                                J
                                JonnyJo25 декабря 2023 г. 16:38
                                Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                                G
                                Gvozdik19 декабря 2023 г. 5:01
                                Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                                Сейчас обсуждают на форуме
                                a
                                a_vlasov14 апреля 2024 г. 13:41
                                Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                                Павел Дорофеев
                                Павел Дорофеев14 апреля 2024 г. 9:35
                                QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
                                f
                                fastrex4 апреля 2024 г. 11:47
                                Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
                                P
                                Pisych27 февраля 2023 г. 12:04
                                Как получить в массив значения из связанной модели? Спасибо, разобрался:))
                                AC
                                Alexandru Codreanu19 января 2024 г. 19:57
                                QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…

                                Следите за нами в социальных сетях