Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Save and Open PDF on Android!
Forum Updated to NodeBB v4.3 + New Features

Save and Open PDF on Android!

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
16 Posts 3 Posters 1.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    RenanHm
    wrote on last edited by
    #1

    Hello.. I am saving a PDF file on the Android device as follows:

    QString fileName = QFileDialog::getSaveFileName(this, tr("Exportar relatório..."), QString(), tr("PDF (*.pdf);;HTML (*.htm *.html);;Excel (*.csv);;Todos Arquivos (*)"));
        if(fileName.isEmpty())
            return;
    
    printer->setOutputFormat(QPrinter::PdfFormat);
    printer->setOutputFileName(fileName);
    TE_Rel->document()->print(printer);
    

    This way I use on Windows and now I'm using it on Android.
    Apparently the PDF is successfully saved in the APP folder. But I can't view the APP form PDF, which I believe is related to Android permissions.

    Given this, I'm trying to open the PDF right after saving. I use the following code to try to open it:

            QString filePath = fileName; //The file exists at that location, I used the same path to create the pdf
            QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
    

    However, the PDF is not opened through a standard PDF viewer that is installed on the device.

    Any other alternative to save and read PDF on Android?

    I use QT 5.14.2.
    Thanks.

    1 Reply Last reply
    0
    • JoeCFDJ Offline
      JoeCFDJ Offline
      JoeCFD
      wrote on last edited by JoeCFD
      #2

      add read and write permissions in your AndroidManifess.xml? You can save your files in QStandardPaths::DocumentsLocation

      1 Reply Last reply
      0
      • R Offline
        R Offline
        RenanHm
        wrote on last edited by
        #3

        I will add the following permissions:

            <uses-permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"/>
            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
            <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
            <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
            <uses-permission android:name="android.permission.WRITE_PROFILE"/>
        

        But apparently it has no effect.

        Whenever I save the PDF, the QFileDialog opens, allowing saving only within the APP folder.

        Any idea?

        1 Reply Last reply
        0
        • JoeCFDJ Offline
          JoeCFDJ Offline
          JoeCFD
          wrote on last edited by JoeCFD
          #4

          @JoeCFD said in Save and Open PDF on Android!:

          QStandardPaths::DocumentsLocation

          you assign this path QStandardPaths::DocumentsLocation to QFileDialog

          1 Reply Last reply
          0
          • R Offline
            R Offline
            RenanHm
            wrote on last edited by
            #5

            Hello.. Okay. Change to:

                QString caminho = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
                QString fileName = QFileDialog::getSaveFileName(this, tr("Exportar relatório..."), caminho, tr("PDF (*.pdf);;HTML (*.htm *.html);;Excel (*.csv);;Todos Arquivos (*)"));
                if(fileName.isEmpty())
                    return;
            

            Now open the "Documents" folder. Saves correctly. But I can't open it with my APP through QDesktopServices

            1 Reply Last reply
            0
            • JoeCFDJ Offline
              JoeCFDJ Offline
              JoeCFD
              wrote on last edited by JoeCFD
              #6

              not familiar with QDesktopServices. What is the error message?
              the following link is a bit old. But it may help a bit.
              https://stackoverflow.com/questions/18786919/qt-android-qdesktopservicesopenurl-qurlfromlocalfile-pdf-with
              https://bugreports.qt.io/browse/QTBUG-67877

              1 Reply Last reply
              0
              • R Offline
                R Offline
                RenanHm
                wrote on last edited by
                #7

                W System.err: android.os.FileUriExposedException: file:///storage/emulated/0/Documents/Caduser.pdf exposed beyond app through Intent.getData()
                W System.err: at android.os.StrictMode.onFileUriExposed(StrictMode.java:2209)
                W System.err: at android.net.Uri.checkFileUriExposed(Uri.java:2402)
                W System.err: at android.content.Intent.prepareToLeaveProcess(Intent.java:12108)
                W System.err: at android.content.Intent.prepareToLeaveProcess(Intent.java:12057)
                W System.err: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1742)
                W System.err: at android.app.Activity.startActivityForResult(Activity.java:5473)
                W System.err: at android.app.Activity.startActivityForResult(Activity.java:5431)
                W System.err: at android.app.Activity.startActivity(Activity.java:5817)
                W System.err: at android.app.Activity.startActivity(Activity.java:5770)
                W System.err: at org.qtproject.qt5.android.QtNative.openURL(QtNative.java:164)
                W System.err: at org.qtproject.qt5.android.QtNative.startQtApplication(Native Method)
                W System.err: at org.qtproject.qt5.android.QtNative$7.run(QtNative.java:390)
                W System.err: at org.qtproject.qt5.android.QtThread$1.run(QtThread.java:61)
                W System.err: at java.lang.Thread.run(Thread.java:1012)

                piervalliP 1 Reply Last reply
                0
                • R RenanHm

                  W System.err: android.os.FileUriExposedException: file:///storage/emulated/0/Documents/Caduser.pdf exposed beyond app through Intent.getData()
                  W System.err: at android.os.StrictMode.onFileUriExposed(StrictMode.java:2209)
                  W System.err: at android.net.Uri.checkFileUriExposed(Uri.java:2402)
                  W System.err: at android.content.Intent.prepareToLeaveProcess(Intent.java:12108)
                  W System.err: at android.content.Intent.prepareToLeaveProcess(Intent.java:12057)
                  W System.err: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1742)
                  W System.err: at android.app.Activity.startActivityForResult(Activity.java:5473)
                  W System.err: at android.app.Activity.startActivityForResult(Activity.java:5431)
                  W System.err: at android.app.Activity.startActivity(Activity.java:5817)
                  W System.err: at android.app.Activity.startActivity(Activity.java:5770)
                  W System.err: at org.qtproject.qt5.android.QtNative.openURL(QtNative.java:164)
                  W System.err: at org.qtproject.qt5.android.QtNative.startQtApplication(Native Method)
                  W System.err: at org.qtproject.qt5.android.QtNative$7.run(QtNative.java:390)
                  W System.err: at org.qtproject.qt5.android.QtThread$1.run(QtThread.java:61)
                  W System.err: at java.lang.Thread.run(Thread.java:1012)

                  piervalliP Offline
                  piervalliP Offline
                  piervalli
                  wrote on last edited by
                  #8

                  @RenanHm said in Save and Open PDF on Android!:

                  W System.err: at java.lang.Thread.run(Thread.java:1012)

                  Have you checked permission on startup?

                  #ifdef REQUEST_PERMISSIONS_ON_ANDROID
                  #include <QtAndroid>
                  
                  bool requestStoragePermission() {
                      using namespace QtAndroid;
                      SOPermission sop;
                      QStringList permissions = {"android.permission.ACCESS_FINE_LOCATION"};
                      const QHash<QString, PermissionResult> results = requestPermissionsSync(permissions);
                      auto ok = true;
                      auto i = 0;
                      while (ok && i< permissions.size()) {
                          if (!results.contains(permissions[i]) || results[permissions[i]] == PermissionResult::Denied) {
                              qCritical() << "Couldn't get permission: " << permissions[i];
                              ok = false;
                              --i;
                          }
                          ++i;
                      }
                      return ok;
                  }
                  #endif
                  
                  1 Reply Last reply
                  0
                  • R Offline
                    R Offline
                    RenanHm
                    wrote on last edited by
                    #9

                    Hello.. I performed the test with the function mentioned. Change to permission:

                        QStringList permissions = {"android.permission.READ_EXTERNAL_STORAGE"};
                    

                    It is returned to me that it has permission. But without any practical effect.

                    Searching more.. I found that in the most recent versions of Android it is now necessary to use "Provider".

                    https://bugreports.qt.io/browse/QTBUG-67877
                    https://bugreports.qt.io/browse/QTBUG-85238

                    Following the guidelines for using the Provider, I add in the Manifest:

                    <provider
                                android:name="androidx.core.content.FileProvider"
                                android:authorities="com.example.myapp.fileprovider"
                                android:grantUriPermissions="true"
                                android:exported="false">
                                <meta-data
                                    android:name="android.support.FILE_PROVIDER_PATHS"
                                    android:resource="@xml/filepaths" />
                            </provider>
                    

                    I also include the "filepaths" file in the "xml" folder.
                    But the error always occurs when opening the APP:

                    E AndroidRuntime: FATAL EXCEPTION: main
                    E AndroidRuntime: Process: com.digitalsof.totallocapp, PID: 4718
                    E AndroidRuntime: java.lang.RuntimeException: Unable to get provider androidx.core.content.FileProvider: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" on path: DexPathList[[zip file "/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk"],nativeLibraryDirectories=[/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/lib/arm64, /data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
                    E AndroidRuntime: 	at android.app.ActivityThread.installProvider(ActivityThread.java:8231)
                    E AndroidRuntime: 	at android.app.ActivityThread.installContentProviders(ActivityThread.java:7728)
                    E AndroidRuntime: 	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7482)
                    E AndroidRuntime: 	at android.app.ActivityThread.access$1600(ActivityThread.java:310)
                    E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2281)
                    E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
                    E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:226)
                    E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:313)
                    E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:8669)
                    E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
                    E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
                    E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
                    E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" on path: DexPathList[[zip file "/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk"],nativeLibraryDirectories=[/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/lib/arm64, /data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
                    E AndroidRuntime: 	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
                    E AndroidRuntime: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
                    E AndroidRuntime: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
                    E AndroidRuntime: 	at android.app.AppComponentFactory.instantiateProvider(AppComponentFactory.java:147)
                    E AndroidRuntime: 	at android.app.ActivityThread.installProvider(ActivityThread.java:8215)
                    E AndroidRuntime: 	... 11 more
                    

                    Any idea?

                    piervalliP 1 Reply Last reply
                    0
                    • R RenanHm

                      Hello.. I performed the test with the function mentioned. Change to permission:

                          QStringList permissions = {"android.permission.READ_EXTERNAL_STORAGE"};
                      

                      It is returned to me that it has permission. But without any practical effect.

                      Searching more.. I found that in the most recent versions of Android it is now necessary to use "Provider".

                      https://bugreports.qt.io/browse/QTBUG-67877
                      https://bugreports.qt.io/browse/QTBUG-85238

                      Following the guidelines for using the Provider, I add in the Manifest:

                      <provider
                                  android:name="androidx.core.content.FileProvider"
                                  android:authorities="com.example.myapp.fileprovider"
                                  android:grantUriPermissions="true"
                                  android:exported="false">
                                  <meta-data
                                      android:name="android.support.FILE_PROVIDER_PATHS"
                                      android:resource="@xml/filepaths" />
                              </provider>
                      

                      I also include the "filepaths" file in the "xml" folder.
                      But the error always occurs when opening the APP:

                      E AndroidRuntime: FATAL EXCEPTION: main
                      E AndroidRuntime: Process: com.digitalsof.totallocapp, PID: 4718
                      E AndroidRuntime: java.lang.RuntimeException: Unable to get provider androidx.core.content.FileProvider: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" on path: DexPathList[[zip file "/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk"],nativeLibraryDirectories=[/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/lib/arm64, /data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
                      E AndroidRuntime: 	at android.app.ActivityThread.installProvider(ActivityThread.java:8231)
                      E AndroidRuntime: 	at android.app.ActivityThread.installContentProviders(ActivityThread.java:7728)
                      E AndroidRuntime: 	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7482)
                      E AndroidRuntime: 	at android.app.ActivityThread.access$1600(ActivityThread.java:310)
                      E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2281)
                      E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
                      E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:226)
                      E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:313)
                      E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:8669)
                      E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
                      E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
                      E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
                      E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" on path: DexPathList[[zip file "/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk"],nativeLibraryDirectories=[/data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/lib/arm64, /data/app/~~qh7wYdLZU6AvVfgP104ckQ==/com.digitalsof.totallocapp-pzAvkKqAw1X05TWYviFvnA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
                      E AndroidRuntime: 	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
                      E AndroidRuntime: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
                      E AndroidRuntime: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
                      E AndroidRuntime: 	at android.app.AppComponentFactory.instantiateProvider(AppComponentFactory.java:147)
                      E AndroidRuntime: 	at android.app.ActivityThread.installProvider(ActivityThread.java:8215)
                      E AndroidRuntime: 	... 11 more
                      

                      Any idea?

                      piervalliP Offline
                      piervalliP Offline
                      piervalli
                      wrote on last edited by piervalli
                      #10

                      @RenanHm
                      In the my app I haved inserted in the all permission that we need .
                      const QStringList m_permissionsNameListAndroid = {"android.permission.ACCESS_FINE_LOCATION","android.permission.ACCESS_COARSE_LOCATION","android.permission.READ_EXTERNAL_STORAGE","android.permission.WRITE_EXTERNAL_STORAGE","android.permission.CHANGE_WIFI_STATE","android.permission.READ_PHONE_STATE","android.permission.ACCESS_WIFI_STATE","android.permission.BLUETOOTH","android.permission.BLUETOOTH_ADMIN","android.permission.VIBRATE","android.permission.RECEIVE_BOOT_COMPLETED"};

                      For Android > 10 I have ceate this function to create an file on directory. So You can test, if you can write on directory. I neved opened a url but I think the way is create a function java.

                      For example
                      //https://trendoceans.com/how-to-open-pdf-programmatically-using-intent-in-android/

                      For open the url
                      public static String directoryDownLoad() {
                      Context context = m_instance.getApplicationContext();
                      File path = android.os.Environment.getExternalStoragePublicDirectory(
                      android.os.Environment.DIRECTORY_DOWNLOADS);
                      Log.v(m_instance.TAG,"directoryDownLoad"+path.getAbsolutePath());
                      return path.getAbsolutePath();
                      }

                      Id

                      1 Reply Last reply
                      0
                      • R Offline
                        R Offline
                        RenanHm
                        wrote on last edited by
                        #11

                        I'm managing to save the PDF, as I went above.
                        The problem is in opening the PDF.

                        From what I researched, the "Provider" should be created and call the native java class through "QAndroidJniObject".

                        But I can't move forward when I edit the Manifest file as above.

                        piervalliP 1 Reply Last reply
                        0
                        • R RenanHm

                          I'm managing to save the PDF, as I went above.
                          The problem is in opening the PDF.

                          From what I researched, the "Provider" should be created and call the native java class through "QAndroidJniObject".

                          But I can't move forward when I edit the Manifest file as above.

                          piervalliP Offline
                          piervalliP Offline
                          piervalli
                          wrote on last edited by
                          #12

                          @RenanHm
                          In this case usually I create a basic project with Android Studio to open a pdf. Then you can push the function in activity that you have extended in Qt for Android

                          R 1 Reply Last reply
                          0
                          • piervalliP piervalli

                            @RenanHm
                            In this case usually I create a basic project with Android Studio to open a pdf. Then you can push the function in activity that you have extended in Qt for Android

                            R Offline
                            R Offline
                            RenanHm
                            wrote on last edited by
                            #13

                            @piervalli said in Save and Open PDF on Android!:

                            In this case usually I create a basic project with Android Studio to open a pdf. Then you can push the function in activity that you have extended in Qt for Android

                            I understood. I am going to try..

                            1 Reply Last reply
                            0
                            • R Offline
                              R Offline
                              RenanHm
                              wrote on last edited by
                              #14

                              I'm having the same problem with printing documents on Android... QT doesn't recognize the drivers installed... it just gives the option to save to PDF... Do you know anything about this?

                              piervalliP 1 Reply Last reply
                              0
                              • R RenanHm

                                I'm having the same problem with printing documents on Android... QT doesn't recognize the drivers installed... it just gives the option to save to PDF... Do you know anything about this?

                                piervalliP Offline
                                piervalliP Offline
                                piervalli
                                wrote on last edited by
                                #15

                                @RenanHm
                                I am remember that the printer is not supported on Android, I think that you need same way.

                                R 1 Reply Last reply
                                0
                                • piervalliP piervalli

                                  @RenanHm
                                  I am remember that the printer is not supported on Android, I think that you need same way.

                                  R Offline
                                  R Offline
                                  RenanHm
                                  wrote on last edited by
                                  #16

                                  @piervalli Got it.. I'll research about it. Thanks.

                                  1 Reply Last reply
                                  0

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved