Qt for Android enables you to run Qt 5 applications Android devices. All Qt modules (essential and add-on) are supported except Qt WebEngine, Qt Serial Port, and the platform-specific ones (Qt Mac Extras, Qt Windows Extras, and Qt X11 Extras).在Windows或者Linux平台上可以用QtWebEngine模块实现网页预览和打印成PDF文档,用起来很方便,生成的文档质量也比较好,但在Android平台上QtWebEngine模块不能用,想要显示网页可以用QtWebView模块,不支持打印成PDF。尝试用QTextDocument和QPrinter将html转为PDF,发现QTextDocument不支持CSS样式,生成的PDF文档排版是错的。 查看QtWebView在Android平台上的实现,可以发现其用的就是Android的WebView控件实现的网页显示。尝试在Android平台上实现html生成PDF,找到了这篇文章https://www.jianshu.com/p/d82bd61b11a4,验证后可行。需要依赖第三方库DexMaker,可以用谷歌实现的 implementation 'com.google.dexmaker:dexmaker:1.2',库文件名为dexmaker-1.2.jar。 修改QT源码,在Android平台上实现html转PDF的功能 主要修改: 增加了 void printToPdf(final String fileName)打印接口 增加了 native void c_onpdfPrintingFinished(long id, boolean succeed)作为打印完成的回调 增加了内部类Html2Pdf实现打印成PDF
增加槽函数 void printToPdf(const QString &fileName) Q_DECL_OVERRIDE;
实现槽函数 void QAndroidWebViewPrivate::printToPdf(const QString &fileName)
{const QJNIObjectPrivate &fileNameString = QJNIObjectPrivate::fromString(fileName);
m_viewController.callMethod<void>("printToPdf","(Ljava/lang/String;)V",fileNameString.object());
} 实现java代码中打印完成的回调 static void c_onpdfPrintingFinished(JNIEnv *env,
jobject thiz,
jlong id,
jboolean succeed)
{
Q_UNUSED(env)
Q_UNUSED(thiz)const WebViews &wv = (*g_webViews);
QAndroidWebViewPrivate *wc = wv[id];if (!wc)return;
Q_EMIT wc->pdfPrintingFinished(succeed);
} 修改JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/),注册c_onpdfPrintingFinished回调函数。 JNINativeMethod methods[]数组里增加一项
{"c_onpdfPrintingFinished","(JZ)V",reinterpret_cast<void *>(c_onpdfPrintingFinished)}
增加信号void pdfPrintingFinished(bool succeed);
增加公开槽函数 void printToPdf(const QString &fileName) Q_DECL_OVERRIDE; 增加信号 void pdfPrintingFinished(bool succeed); 增加私有槽函数 void onPdfPrintingFinished(bool succeed);
构造函数里关联槽函数和信号 #if ANDROIDconnect(m_webView, &QWebView::pdfPrintingFinished, this, &QQuickWebView::onPdfPrintingFinished);#endif 实现槽函数printToPdf #if ANDROIDvoid QQuickWebView::printToPdf(const QString &fileName)
{
m_webView->printToPdf(fileName);
}#endif 实现槽函数onPdfPrintingFinished #if ANDROIDvoid QQuickWebView::onPdfPrintingFinished(bool succeed)
{
Q_EMIT pdfPrintingFinished(succeed);
}#endif
增加纯虚函数 virtual void printToPdf(const QString &fileName) = 0;
QNullWebView类增加 void printToPdf(const QString &fileName) override{Q_UNUSED(fileName); }
增加公开槽函数 void printToPdf(const QString &fileName) Q_DECL_OVERRIDE; 增加信号 void pdfPrintingFinished(bool succeed); 增加私有槽函数 void onPdfPrintingFinished(bool succeed);
构造函数里关联槽函数和信号 #if ANDROIDconnect(d, &QAbstractWebView::pdfPrintingFinished, this, &QWebView::onPdfPrintingFinished);#endif 实现槽函数printToPdf #if ANDROIDvoid QWebView::printToPdf(const QString &fileName)
{
d->printToPdf(fileName);
}#endif 实现槽函数onPdfPrintingFinished #if ANDROIDvoid QWebView::onPdfPrintingFinished(bool succeed)
{
Q_EMIT pdfPrintingFinished(succeed);
}#endif
在$QtSrc/qtwebview/src/jar目录下新建lib目录,将dexmaker-1.2.jar文件拷贝到该目录下 修改$QtSrc/qtwebview/src/jar/jar.pro TARGET = QtAndroidWebView
load(qt_build_paths) CONFIG += java DESTDIR = $$MODULE_BASE_OUTDIR/jar
JAVACLASSPATH += $$PWD/src \ $$PWD/lib/dexmaker-1.2.jar
JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/view/QtAndroidWebViewController.java
# install thridpartyjar.files = \ $$PWD/lib/dexmaker-1.2.jar thridpartyjar.path = $$[QT_INSTALL_PREFIX]/jar
target.path = $$[QT_INSTALL_PREFIX]/jar INSTALLS += target thridpartyjar 修改$QtSrc/qtwebview/src/webview/webview.pro ……
QMAKE_DOCS = \ $$PWD/doc/qtwebview.qdocconf
ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtAndroidWebView.jar \ jar/dexmaker-1.2.jar ANDROID_PERMISSIONS = \ android.permission.ACCESS_FINE_LOCATION ANDROID_LIB_DEPENDENCIES = \ plugins/webview/libqtwebview_android.so
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
load(qt_module) 修改$QtSrc/qtwebview/src/imports/plugins.qmltypes
增加信号 Signal {
name: "pdfPrintingFinished"revision: 1Parameter { name: "succeed"; type: "bool" }
} 增加方法 Method {
name: "printToPdf"revision: 1Parameter { name: "fileName"; type: "string" }
}
./configure -extprefix $QTInstall/android_arm64_v8a -xplatform android-clang -release -nomake tests -nomake examples -opensource -confirm-license -recheck-all -android-ndk $NDKPATH -android-sdk $AndroidSDKPATH -android-ndk-host linux-x86_64 -android-arch arm64-v8a -android-arch支持armeabi, armeabi-v7a, arm64-v8a, x86, x86_64,一次只能编译一个架构,注意不同架构要修改安装目录 make -j8 make install
QT:5.13.2 NDK:r20b(20.1.5948944) Android-buildToolsVersion:29.0.2
使用示例 import QtQuick 2.12import QtQuick.Window 2.12import QtWebView 1.1import QtQuick.Controls 2.12Window {
id: window
visible: truewidth: 1080height: 1920title: qsTr("Hello World")
WebView{
id:webView
anchors.bottom: printBtn.top
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
anchors.bottomMargin: 0url:"http://www.qq.com"onPdfPrintingFinished: {
printBtn.text = "打印" + (succeed?"成功":"失败")
printBtn.enabled = true}
}
Button {
id:printBtn
text: "打印"anchors.bottom: parent.bottom
anchors.bottomMargin: 0onClicked: {
printBtn.enabled = falsewebView.printToPdf("/sdcard/aaa.pdf")
}
}
}
全部修改见https://github.com/ALittleDruid/qtwebview/commit/722a4757dd0acf86846194607a433cd724e9b028
|