Problem when viewing web pages in QML using android.webkit.WebView
-
Hi. I'm trying to create WebView-analogue QML component for Android. The problem is, when I call LoadUrl method for android.webkit.WebView I get a crash somewhere in com.android.webview.chromium.WebViewChromium. URL in loadUrl method can be any, even "about:blank". More details below:
Some code:
@AndroidWebView::AndroidWebView(QQuickItem *parent)
: QQuickItem(parent)
{
setFlag(QQuickItem::ItemHasContents);
}@@void AndroidWebView::componentComplete()
{
qDebug() << "AndroidWebView::componentComplete";QQuickItem::componentComplete(); // Get activity object of our application QAndroidJniObject qObjActivity = QtAndroid::androidActivity(); // Create WebView and set default background color qObjWebView = QAndroidJniObject("android/webkit/WebView", "(Landroid/content/Context;)V", qObjActivity.object<jobject>()); jint backgroundColor = 0xFF000000; qObjWebView.callObjectMethod("setBackgroundColor", "(I)V", backgroundColor); // Construct LayoutParams object jint width = 100; jint height = 100; jint x = 0; jint y = 0; QAndroidJniObject qObjLayoutParams("android/widget/AbsoluteLayout/LayoutParams", "(IIII)V", width, height, x, y); // Add WebView as content view for our activity qObjActivity.callObjectMethod("addContentView", "(Landroid/view/View;Landroid/view/ViewGroup/LayoutParams;)V", qObjWebView.object<jobject>(), qObjLayoutParams.object<jobject>());
}@
@void AndroidWebView::loadURL(QString url)
{
qDebug() << "AndroidWebView::loadURL" << url;
QAndroidJniObject qObjUrlString = QAndroidJniObject::fromString(url);
// The crash happens when I call this method
qObjWebView.callObjectMethod("loadUrl", "(Ljava/lang/String;)V", qObjUrlString.object<jstring>());
}@Here is what I have got in QML:
@AndroidWebView {
id: androidWebView
anchors.fill: parent
Component.onCompleted: androidWebView.loadURL("about:blank");
}@EDIT:
And here is a log:
@D/Qt (21155): ../MyApp/android/AndroidWebView.cpp:10 (AndroidWebView::AndroidWebView(QQuickItem*)): AndroidWebView::componentComplete
D/Qt (21155): ../MyApp/android/AndroidWebView.cpp:82 (void AndroidWebView::loadURL(QString)): AndroidWebView::loadURL "about:blank"
V/WebViewChromiumFactoryProvider(21155): Binding Chromium to main looper Looper (main, tid 1) {42dec630}
I/LibraryLoader(21155): Expected native library version number "",actual native library version number ""
I/chromium(21155): [INFO:library_loader_hooks.cc(116)] Chromium logging enabled: level = 0, default verbosity = 0
I/BrowserStartupController(21155): Initializing chromium process, renderers=0
E/AudioManagerAndroid(21155): BLUETOOTH permission is missing!
E/dalvikvm(21155): JNI ERROR (app bug): attempt to use stale local reference 0x1
E/dalvikvm(21155): VM aborting
F/libc (21155): Fatal signal 6 (SIGABRT) at 0x000052a3 (code=-6), thread 21171 (qtproject.MyApp)
D/AndroidRuntime(21155): Shutting down VM
W/dalvikvm(21155): threadid=1: thread exiting with uncaught exception (group=0x41600d88)
E/AndroidRuntime(21155): FATAL EXCEPTION: main
E/AndroidRuntime(21155): Process: org.qtproject.MyApp, PID: 21155
E/AndroidRuntime(21155): java.lang.NullPointerException
E/AndroidRuntime(21155): at com.android.webview.chromium.WebViewChromium$15.run(WebViewChromium.java:616)
E/AndroidRuntime(21155): at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue.drainQueue(WebViewChromium.java:113)
E/AndroidRuntime(21155): at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue$1.run(WebViewChromium.java:100)
E/AndroidRuntime(21155): at android.os.Handler.handleCallback(Handler.java:733)
E/AndroidRuntime(21155): at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime(21155): at android.os.Looper.loop(Looper.java:212)
E/AndroidRuntime(21155): at android.app.ActivityThread.main(ActivityThread.java:5135)
E/AndroidRuntime(21155): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(21155): at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime(21155): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:877)
E/AndroidRuntime(21155): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
E/AndroidRuntime(21155): at dalvik.system.NativeStart.main(Native Method)@One more interesting fact, when I don't call loadURL that crash not happens, but I can't see a view. There must be black square 100x100 pixels, if my code is correct, but I can't see anything like this. Am I doing it wrong?
Thanks!
-
I have checked in several forums and I have found this:
The "stale local reference" error means that you're saving a local reference to some Java object between JNI calls;
You need to convert that reference to a global reference using the NewGlobalRef method before doing anything that would cause the reference to persist outside the scope of the one JNI call.
@jclass jc = env->FindClass(callbacks.name);
// Since Android ICS, class references are not global so we need to peg a
// global reference to the jclass returned by FindClass(), otherwise we get
// following error in the log:
// "JNI ERROR (app bug): attempt to use stale local reference 0xHHHHHHHH".
callbacks._class = static_cast<jclass>(env->NewGlobalRef(jc));@In you case try to convert that reference to a global reference.....
@jclass jc = env->FindClass(callbacks.name);
callbacks._class = static_cast<jclass>(env->NewGlobalRef(jc));@in any case I think that the error is the following block:
@void AndroidWebView::loadURL(QString url)
{
qDebug() << "AndroidWebView::loadURL" << url;
QAndroidJniObject qObjUrlString = QAndroidJniObject::fromString(url);
// The crash happens when I call this method
qObjWebView.callObjectMethod("loadUrl", "(Ljava/lang/String;)V", qObjUrlString.object<jstring>());
}@because loadUrl is a method of QDesktopServices class and I don't see this class in your code.
your code will be the following:
@void AndroidWebView::loadURL(QString url)
{
qDebug() << "AndroidWebView::loadURL" << url;QAndroidJniObject javaClass("QDesktopServices");
QAndroidJniEnvironment env;
jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
objectClass.callObjectMethod("loadUrl", "(Ljava/lang/String;)V", qObjUrlString.object<jstring>());
}@
-
Hi,
There's now the "QtWebView module":https://qt.gitorious.org/qt/qtwebview/source/a2dd3fb028d731b3971e442db81b693c98849900 that can be used on android
-
[quote author="nologinma" date="1408629120"]
You need to convert that reference to a global reference using the NewGlobalRef method before doing anything that would cause the reference to persist outside the scope of the one JNI call.
[/quote]
Hi! Thanks for help. I tried to call NewGlobalRef for all jobjects and jclasses I using in my code, but I still get the same error.[quote author="nologinma" date="1408629120"]
because loadUrl is a method of QDesktopServices class and I don't see this class in your code.
[/quote]
But I think I don't need to call any methods of QDesktopServices class. loadUrl, in this case, is the method of android.webkit.WebView class and described "here":http://developer.android.com/reference/android/webkit/WebView.html#loadUrl(java.lang.String).[quote author="SGaist" date="1408630724"]Hi,
There's now the "QtWebView module":https://qt.gitorious.org/qt/qtwebview/source/a2dd3fb028d731b3971e442db81b693c98849900 that can be used on android[/quote]
Hi. Thanks, this looks very closely to my needs. But I don't sure how I should build this? Can I build it with Qt5.3? -
Using qmake, AFAIK yes
-
[quote author="SGaist" date="1408723811"]Using qmake, AFAIK yes[/quote]
Got these results:
Alexeys-MacBook-Pro:qtwebview alexeykolikov$ ~/Qt5.3.1/5.3/android_armv7/bin/qmake
Alexeys-MacBook-Pro:qtwebview alexeykolikov$ make
cd src/ && ( test -e Makefile || /Users/alexeykolikov/Qt5.3.1/5.3/android_armv7/bin/qmake /Users/alexeykolikov/Documents/github/qtwebview/src/src.pro -o Makefile ) && make -f Makefile
cd webview/ && ( test -e Makefile || /Users/alexeykolikov/Qt5.3.1/5.3/android_armv7/bin/qmake /Users/alexeykolikov/Documents/github/qtwebview/src/webview/webview.pro -o Makefile ) && make -f Makefile
Project WARNING: You should probably load(qt_build_config) first in webview.pro for QtWebView, as the latter also load()s qt_module.
Project MESSAGE: Not doing so may lead to qt_module.prf overriding compiler/linker options in your .pro file.
Project MESSAGE: Ignore this warning with CONFIG+=no_qt_module_warning if you know what you are doing.
Project ERROR: Module does not define version.
make[1]: *** [sub-webview-make_first] Error 3
make: *** [sub-src-make_first] Error 2I guess it's not supposed to be built in this way. Looks like I should build it as a new Qt module like described "here":http://qt-project.org/wiki/Creating-a-new-module-or-tool-for-Qt#55af8d3b581bc7a96ac2a08eb19da92c. Please correct me if I'm wrong.
-
In my app I have used the following called in c++
@QAndroidJniObject m_url = QAndroidJniObject::fromString("storage/sdcard0/gps/gps.kml");
QAndroidJniObject m_application_type = QAndroidJniObject::fromString("application/vnd.google-earth.kml+xml");
QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/Chronometer/Next72Utility", "openUrl", "(Ljava/lang/String;Ljava/lang/String;)V",m_url.object<jstring>(),m_application_type.object<jstring>());@and the java class is the following:
@//
// Next72Utility.java
//
package org.qtproject.example.Chronometer;import android.content.Context;
import android.app.Activity;
import java.lang.Runnable;import android.content.Intent;
import java.io.File;
import android.net.Uri;public class Next72Utility extends org.qtproject.qt5.android.bindings.QtActivity
{public static Next72Utility m_istance;
public Next72Utility()
{
m_istance = this;
}public static void openUrl(final String m_url, final String m_application_type)
{
m_istance.runOnUiThread(new Runnable() {
public void run() {Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); File file = new File(m_url); intent.setDataAndType(Uri.fromFile(file), m_application_type); m_istance.startActivity(intent); } });
}
}
@I hope that solves your case.
-
Indeed, it seems that there are some details missing. Patch underway
-
I have write the steps to introduce the java code into qt project into follwing post: ? "[SOLVED] Qt on Android : How to Vibrate the device ?":https://qt-project.org/forums/viewreply/190435/
I hope that it is usefull here.....