Qt & Android, Launching 3rdParty PDF-Viewer


  • Moderators

    Hi everyone,

    I'm creating a pdf out of data. That works fine, and if the user clicks on the generated pdf, the installed pdfviewer app is started and everything is displayed correctly.

    Now I'm trying to launch that pdf viewer from my QtApplication.

    I tried 2 approaches QDesktopServices and Writing my own Activity extension.

    //DesktopService
    
    QString filePath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QString("/Report.pdf"); //The file exists at that location, I used the same path to create the pdf
    QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
    
    //Java approach
    //cpp call
    QAndroidJniObject javaFilenameStr = QAndroidJniObject::fromString(filePath);
    QAndroidJniObject::callStaticMethod<void>("myApp/pdfView/PdfViewerChoice","showPdf","(Ljava/lang/String;)V", javaFilenameStr.object<jstring>());
    
    //Java class
    package myApp.pdfView;
    
    import java.io.File;
    import android.app.Activity;
    import android.content.Intent;
    import android.util.Log;
    import android.net.Uri;
    
    public class PdfViewerChoice extends org.qtproject.qt5.android.bindings.QtActivity {
        private static PdfViewerChoice m_pdfViewer;
    
        public PdfViewerChoice()
        {
            Log.d("PdfViewerChoice::PdfViewerChoice", "Constructor");
            m_pdfViewer = this;
        }
    
        public static void showPdf(String filepath)
        {
            Log.d("PdfViewerChoice::PdfViewerChoice", "showPdf");
            Log.d("PdfViewerChoice::PdfViewerChoice", filepath);
            //String f = "file://" + filepath;
            //Uri uri = Uri.parse(f);
    
            File file = null;
                 file = new File(filepath);
    
            if(file.exists())
                Log.d("File Exists", "true");
            else
                Log.d("File Exists", "false");
    
            Intent target = new Intent(Intent.ACTION_VIEW);
            target.setDataAndType(Uri.fromFile(file), "application/pdf");
            target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    
            Intent intent = Intent.createChooser(target, "Open File");
            try {
                m_pdfViewer.getApplicationContext().startActivity(intent);
            } catch (android.content.ActivityNotFoundException ex){
                Log.e("PdfViewerChoice", "catched android.content.ActivityNotFoundException while starting activity");
                ex.printStackTrace();
            }
        }
    }
    
    

    I even get a file exists true log from the java class. But no chooser or pdf viewer is launched.

    For reasons I can't go deeper into I'm limited to Qt 5.11.3, this is only supposed to work on android and on PC and Mac. PC/Mac works fine with the DesktopService call, but Android refuses to work.

    What am I missing, perhaps a special android permission ?


  • Qt Champions 2018

    Welcome to hell.
    @ekkescorner wrote an excellent blog post to explain this: https://blog.qt.io/blog/2017/12/01/sharing-files-android-ios-qt-app/


  • Moderators

    @VRonin thanks for the link, I'll read through it.

    I have a slightly different class in an other project to attach a pdf to the E-Mail program that is working fine. So I'm assuming it's something minor right now x)

                Intent intent = new Intent(Intent.ACTION_SEND);
                intent.setType("message/rfc822");
    
                intent.putExtra(Intent.EXTRA_SUBJECT, "AttachmentTest");
                intent.putExtra(Intent.EXTRA_EMAIL, new String[]{sendTo});
                intent.putExtra(Intent.EXTRA_STREAM, uri);
                Intent mailer = Intent.createChooser(intent, null);
                if(mailer == null)
                {
                    Log.e("Mailer::sendMail", "Couldn't get Mail Intent");
                    return;
                }
    
                m_instance.getApplicationContext().startActivity(mailer);
    

  • Moderators

    Turns out, with an android target of 23 or older my approach is more than fine. But google decided to make it more complicated going forwards. As 23 is no longer viable version for updates.

    So, I read through the block post (multiple times), extracted everything I needed and managed to cram everything into one java file.

    also I get this warning:

    WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
    It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html

    since it's now April 2019 I'm going to ignore that until it bites me in the back ;-)

    All in all I'm once again reminded why I'm not a fan of Java....

    Thanks @VRonin and @ekkescorner , for helping me solve this, very much appreciated.