Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

any upto date instructions/cheat sheet to view a pdf on Android from a qt app, ala openurl() but for API 26+



  • Hello Folks

    Just trying to open a pdf in android after I have saved it to QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)/pdf/

    followed https://www.qt.io/blog/2017/12/01/sharing-files-android-ios-qt-app and grabbed bits out the source for the ACTION_VIEW method.

    Setup fileprovider in the AndroidManifest

    but somethings not working...
    taping/clicking the row in my tableview, downloads the pdf successfully and kicks off the pdf viewer, but its blank.

    WIP code snip from mainwindow.cpp

    TemporaryFile file(QDir::toNativeSeparators("./pdf/suiteQL-XXXXXX.pdf"));
    file.setAutoRemove(false);
    if (file.open()) {
            file.write(QByteArray::fromBase64(b64));
            file.close();
    
            // fails on android :(
            QDesktopServices::openUrl(QUrl("file:///" + file.fileName()));
           
            QUrl tmpUrl  = file.fileName();
            QString tmpStra =  tmpUrl.fileName();
    
            //uggg hard coded for now
            QAndroidJniObject jniPath=QAndroidJniObject::fromString("content://blahSuiteQL.fileprovider/mypdf/" + tmpStra);
            
            QAndroidJniObject jniUri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", jniPath.object<jstring>());
            QAndroidJniObject jniParam = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_VIEW");
            QAndroidJniObject jniIntent("android/content/Intent","(Ljava/lang/String;)V",jniParam.object<jstring>());
            QAndroidJniObject jniType = QAndroidJniObject::fromString("application/pdf");
            QAndroidJniObject jniPermissions = 
            
            //fudged this in, not sure if it's correct.... also tried it without
            QAndroidJniObject::fromString("FLAG_GRANT_READ_URI_PERMISSION");
            QAndroidJniObject jniFlags = jniIntent.callObjectMethod("setFlags", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", jniPermissions.object<jstring>());
            //
    
            QAndroidJniObject jniResult = jniIntent.callObjectMethod("setDataAndType", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", jniUri.object<jobject>(), jniType.object<jstring>());
            QAndroidJniObject activity = QtAndroid::androidActivity();
            QAndroidJniObject packageManager = activity.callObjectMethod("getPackageManager",
                                                                         "()Landroid/content/pm/PackageManager;");
            QAndroidJniObject componentName = jniIntent.callObjectMethod("resolveActivity",
                                                                      "(Landroid/content/pm/PackageManager;)Landroid/content/ComponentName;",
                                                                      packageManager.object());
            QtAndroid::startActivity(jniIntent, 0);
            }
    

    snip from AndroidManifest.xml

            <provider android:name="android.support.v4.content.FileProvider"
            android:authorities="blahSuiteQL.fileprovider"
            android:grantUriPermissions="true" android:exported="false">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/filepaths"/>
            </provider>
        </application>
    

    res/xml/filepaths.xml

    <paths>
        <files-path path="pdf/" name="mypdf" />
    </paths>
    

    meh stuck, with head ache :(

    Any help or leads would be appreciated.

    Just trying to open a test pdf pulled down and decoded from a netsuite restlet. (POST reply)

    If I put it in QStandardPaths::standardLocations(QStandardPaths::DownloadLocation I can open it in file manager.

    Kind Regards

    Craig



  • @testmonkey said in any upto date instructions/cheat sheet to view a pdf on Android from a qt app, ala openurl() but for API 26+:

        //fudged this in, not sure if it's correct.... also tried it without
        QAndroidJniObject jniPermissions = QAndroidJniObject::fromString("FLAG_GRANT_READ_URI_PERMISSION");
        QAndroidJniObject jniFlags = jniIntent.callObjectMethod("setFlags", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", jniPermissions.object<jstring>());
        //
    

    just pasted the comment in the wrong place on original post.



  • Hi Folks.... was calling the setFlags wrong.

    this is the code I ended up with and working (tho no error checking atm)

            QAndroidJniObject path=QAndroidJniObject::fromString("content://blahSuiteQL.fileprovider/mypdf/" + tmpStra);
            QAndroidJniObject jniUri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", path.object<jstring>());
            QAndroidJniObject jniParam = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_VIEW");
            QAndroidJniObject intent("android/content/Intent","()V");
                              intent.callObjectMethod("setAction","(Ljava/lang/String;)Landroid/content/Intent;",jniParam.object<jstring>());
            QAndroidJniObject jniType = QAndroidJniObject::fromString("application/pdf");
            jint jniPermissions =  QAndroidJniObject::getStaticField<jint>("android/content/Intent","FLAG_GRANT_READ_URI_PERMISSION");
                              intent.callObjectMethod("setFlags", "(I)Landroid/content/Intent;",jniPermissions);
                              intent.callObjectMethod("setDataAndType", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", jniUri.object<jobject>(), jniType.object<jstring>());
            QAndroidJniObject activity = QtAndroid::androidActivity();
            QAndroidJniObject packageManager = activity.callObjectMethod("getPackageManager","()Landroid/content/pm/PackageManager;");
                               intent.callObjectMethod("resolveActivity","(Landroid/content/pm/PackageManager;)Landroid/content/ComponentName;",packageManager.object());
            QtAndroid::startActivity(intent, 0);
    

    Kind Regards
    Craig


Log in to reply