changeset 2501:41984ffb5ca2

Android: Initial implement of HTML control with WebView. Getting an error about view calls not on the UI thread, even though the call stack is on the main thread... confusing.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 06 May 2021 00:05:32 +0000
parents ac0b7e579229
children b6319aed3298
files android/DWindows.kt android/dw.cpp
diffstat 2 files changed, 141 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/android/DWindows.kt	Wed May 05 21:59:23 2021 +0000
+++ b/android/DWindows.kt	Thu May 06 00:05:32 2021 +0000
@@ -14,17 +14,18 @@
 import android.text.InputFilter
 import android.text.InputFilter.LengthFilter
 import android.text.method.PasswordTransformationMethod
+import android.util.Base64
 import android.util.Log
 import android.view.Gravity
 import android.view.View
 import android.view.ViewGroup
+import android.webkit.WebView
 import android.widget.*
 import android.widget.SeekBar.OnSeekBarChangeListener
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.app.AppCompatActivity
 import androidx.collection.SimpleArrayMap
 import androidx.recyclerview.widget.RecyclerView
-import androidx.viewpager.widget.ViewPager
 import androidx.viewpager2.widget.ViewPager2
 import com.google.android.material.tabs.TabLayout
 import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
@@ -678,6 +679,53 @@
         percent.max = range
     }
 
+    fun htmlNew(cid: Int): WebView?
+    {
+        val looper = Looper.myLooper()
+
+        // WebView requires an active Looper
+        if(looper == null) {
+            Looper.prepare()
+        }
+
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+        val html = WebView(this)
+
+        html.tag = dataArrayMap
+        html.id = cid
+        return html
+    }
+
+    fun htmlLoadURL(html: WebView, url: String)
+    {
+        html.loadUrl(url)
+    }
+
+    fun htmlRaw(html: WebView, data: String)
+    {
+        val encodedHtml: String = Base64.encodeToString(data.toByteArray(), Base64.NO_PADDING)
+        html.loadData(encodedHtml, "text/html", "base64")
+    }
+
+    fun htmlJavascriptRun(html: WebView, javascript: String, data: Long)
+    {
+        html.evaluateJavascript(javascript) { value ->
+            // Execute onReceiveValue's code
+            eventHandlerHTMLResult(html, 18, value, data)
+        }
+    }
+
+    fun htmlAction(html: WebView, action: Int)
+    {
+        when (action) {
+            0 -> html.goBack()
+            1 -> html.goForward()
+            2 -> html.loadUrl("http://dwindows.netlabs.org")
+            4 -> html.reload()
+            5 -> html.stopLoading()
+        }
+    }
+
     fun timerConnect(interval: Long, sigfunc: Long, data: Long): Timer
     {
         // creating timer task, timer
@@ -801,6 +849,7 @@
     external fun eventHandlerSimple(obj1: View, message: Int)
     external fun eventHandlerNotebook(obj1: View, message: Int, pageID: Long)
     external fun eventHandlerTimer(sigfunc: Long, data: Long): Int
+    external fun eventHandlerHTMLResult(obj1: View, message: Int, result: String, data: Long)
 
     companion object
     {
--- a/android/dw.cpp	Wed May 05 21:59:23 2021 +0000
+++ b/android/dw.cpp	Thu May 06 00:05:32 2021 +0000
@@ -371,7 +371,7 @@
     _dw_event_handler(obj1, params, message);
 }
 
-/* A more simple method for quicker calls */
+/* Handler for notebook page changes */
 JNIEXPORT void JNICALL
 Java_org_dbsoft_dwindows_DWindows_eventHandlerNotebook(JNIEnv* env, jobject obj, jobject obj1, jint message, jlong pageID) {
     void *params[8] = { NULL };
@@ -380,6 +380,16 @@
     _dw_event_handler(obj1, params, message);
 }
 
+/* Handler for HTML events */
+JNIEXPORT void JNICALL
+Java_org_dbsoft_dwindows_DWindows_eventHandlerHTMLResult(JNIEnv* env, jobject obj, jobject obj1,
+                                               jint message, jstring htmlResult, jlong data) {
+    const char *result = env->GetStringUTFChars(htmlResult, NULL);
+    void *params[8] = { NULL, DW_POINTER(result), NULL, 0, 0, 0, 0, DW_INT_TO_POINTER(data) };
+
+    _dw_event_handler(obj1, params, message);
+}
+
 JNIEXPORT void JNICALL
 Java_org_dbsoft_dwindows_DWindows_eventHandlerInt(JNIEnv* env, jobject obj, jobject obj1, jint message,
                                                jint inta, jint intb, jint intc, jint intd) {
@@ -887,7 +897,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(box && item && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -909,7 +919,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -935,7 +945,7 @@
     JNIEnv *env;
     HWND retval = 0;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) {
+    if(box && (env = (JNIEnv *)pthread_getspecific(_dw_env_key))) {
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
         // Get the method that you want to call
@@ -1082,7 +1092,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -1250,7 +1260,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -1321,7 +1331,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -1368,7 +1378,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -1419,7 +1429,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         //jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -1443,7 +1453,7 @@
 {
     JNIEnv *env;
 
-    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
     {
         // First get the class that contains the method you need to call
         //jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
@@ -2790,19 +2800,46 @@
  */
 void API dw_html_action(HWND handle, int action)
 {
+    JNIEnv *env;
+
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID htmlAction = env->GetMethodID(clazz, "htmlAction",
+                                                "(Landroid/webkit/WebView;I)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, htmlAction, handle, action);
+    }
 }
 
 /*
  * Render raw HTML code in the embedded HTML widget..
  * Parameters:
  *       handle: Handle to the window.
- *       string: String buffer containt HTML code to
+ *       string: String buffer containing HTML code to
  *               be rendered.
  * Returns:
  *       DW_ERROR_NONE (0) on success.
  */
 int API dw_html_raw(HWND handle, const char *string)
 {
+    JNIEnv *env;
+
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct a String
+        jstring jstr = env->NewStringUTF(string);
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID htmlRaw = env->GetMethodID(clazz, "htmlRaw",
+                                                 "(Landroid/webkit/WebView;Ljava/lang/String;)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, htmlRaw, handle, jstr);
+        return DW_ERROR_NONE;
+    }
     return DW_ERROR_GENERAL;
 }
 
@@ -2817,6 +2854,21 @@
  */
 int API dw_html_url(HWND handle, const char *url)
 {
+    JNIEnv *env;
+
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct a String
+        jstring jstr = env->NewStringUTF(url);
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID htmlLoadURL = env->GetMethodID(clazz, "htmlLoadURL",
+                                                 "(Landroid/webkit/WebView;Ljava/lang/String;)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, htmlLoadURL, handle, jstr);
+        return DW_ERROR_NONE;
+    }
     return DW_ERROR_GENERAL;
 }
 
@@ -2832,6 +2884,21 @@
  */
 int API dw_html_javascript_run(HWND handle, const char *script, void *scriptdata)
 {
+    JNIEnv *env;
+
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct a String
+        jstring jstr = env->NewStringUTF(script);
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID htmlJavascriptRun = env->GetMethodID(clazz, "htmlJavascriptRun",
+                                                       "(Landroid/webkit/WebView;Ljava/lang/String;J)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, htmlJavascriptRun, handle, jstr, (jlong)scriptdata);
+        return DW_ERROR_NONE;
+    }
     return DW_ERROR_UNKNOWN;
 }
 
@@ -2844,6 +2911,19 @@
  */
 HWND API dw_html_new(unsigned long cid)
 {
+    JNIEnv *env;
+
+    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID htmlNew = env->GetMethodID(clazz, "htmlNew",
+                                             "(I)Landroid/webkit/WebView;");
+        // Call the method on the object
+        jobject result = env->NewWeakGlobalRef(env->CallObjectMethod(_dw_obj, htmlNew, (int)cid));
+        return result;
+    }
     return 0;
 }