alex_lip
alex_lipМаусым 4, 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


                                Пікірлер

                                Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                                Кіріңіз немесе Тіркеліңіз
                                Г

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

                                • Нәтиже:66ұпай,
                                • Бағалау ұпайлары-1
                                t

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

                                • Нәтиже:33ұпай,
                                • Бағалау ұпайлары-10
                                t

                                Qt - Тест 001. Сигналы и слоты

                                • Нәтиже:52ұпай,
                                • Бағалау ұпайлары-4
                                Соңғы пікірлер
                                G
                                GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
                                Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
                                d
                                dblas5Шілде 5, 2024, 11:02 Т.Ж.
                                QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                k
                                kmssrАқп. 8, 2024, 6:43 Т.Қ.
                                Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                АК
                                Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
                                Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                Енді форумда талқылаңыз
                                Evgenii Legotckoi
                                Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
                                добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                F
                                FynjyШілде 22, 2024, 4:15 Т.Ж.
                                при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
                                BlinCT
                                BlinCTМаусым 25, 2024, 1 Т.Ж.
                                Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
                                BlinCT
                                BlinCTМамыр 5, 2024, 5:46 Т.Ж.
                                Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
                                Evgenii Legotckoi
                                Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
                                Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

                                Бізді әлеуметтік желілерде бақылаңыз