alex_lip
alex_lipJune 4, 2018, 6:58 p.m.

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

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

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

15
Evgenii Legotckoi
  • June 4, 2018, 7:08 p.m.

Забавно, у 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
    • June 4, 2018, 10:34 p.m.

    Это вроде из-за 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
      • June 5, 2018, 1:21 p.m.
      Жестко ругается
       
      на вариант от 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
        • June 5, 2018, 1:25 p.m.
        вот мой манифест


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

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

                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
                  • June 5, 2018, 4:04 p.m.
                  • (edited)

                  непонятно причем тут 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
                    • June 5, 2018, 4:05 p.m.
                    • (edited)

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


                    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
                      • June 5, 2018, 5:39 p.m.

                      этот вариант работал на всех устройствах (от 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
                        • June 5, 2018, 8:32 p.m.
                        По идее у Вас это не должно было работать. Дело в том, что 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
                          • June 5, 2018, 10:45 p.m.
                          • (edited)

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

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


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


                                Comments

                                Only authorized users can post comments.
                                Please, Log in or Sign up
                                Ua

                                Qt - Test 001. Signals and slots

                                • Result:84points,
                                • Rating points4
                                Ua

                                Qt - Test 001. Signals and slots

                                • Result:42points,
                                • Rating points-8
                                ОК

                                Qt - Test 001. Signals and slots

                                • Result:47points,
                                • Rating points-6
                                Last comments
                                ИМ
                                Игорь МаксимовNov. 22, 2024, 9:51 p.m.
                                Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                Evgenii Legotckoi
                                Evgenii LegotckoiOct. 31, 2024, 11:37 p.m.
                                Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                A
                                ALO1ZEOct. 19, 2024, 5:19 p.m.
                                Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                ИМ
                                Игорь МаксимовOct. 5, 2024, 4:51 p.m.
                                Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                d
                                dblas5July 5, 2024, 8:02 p.m.
                                QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                Now discuss on the forum
                                f
                                firstlunoxodFeb. 15, 2025, 1:46 p.m.
                                Рисование на QGraphicsScene при зажатой кнопке мыши Подскажите, пожалуйста! Как данный класс можно дополнить, чтобы созданные объекты можно было перемещать мышкой по сцене?
                                Дмитрий
                                ДмитрийFeb. 3, 2025, 4:24 p.m.
                                Создание deb-пакета. Как создать ярлык на рабочем столе после установки собственного deb-пакета? Всем привет. Сделал свой deb-пакет с программой. Всё устанавливается и работает. Ставлю по пути /usr/bin/my_application. Как для пользователя при установке пакета сразу создать ярлык на раб…
                                NW
                                Nayo WaiJan. 30, 2025, 7:22 p.m.
                                не запускается компьютер!!! Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
                                n
                                nklyJan. 3, 2025, 12:52 p.m.
                                Нужно запретить перемещение только некоторых итемов, остальные перемещать можно. Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
                                M
                                MarselAug. 17, 2023, 12:26 a.m.
                                OAuth2.0 через VK, получение email Спасибо большое за помощь и простите за то что отнял время своей невнимательностью.

                                Follow us in social networks