Mercurial > dwindows
changeset 2477:3fbf8783122d
Android: First functional version. Notebook-less first page of dwtest works.
FindClass failed on any created threads.. using a modified version of this:
https://stackoverflow.com/questions/13263340/findclass-from-any-thread-in-android-jni
Implemented dw_box_unpack(). Had to do this to fix an exception when
repacking a widget in dwtest's archive_add().
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Thu, 22 Apr 2021 17:49:20 +0000 |
parents | 20c9e83cba2a |
children | b0230e378667 |
files | android/DWindows.kt android/dw.cpp |
diffstat | 2 files changed, 64 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/android/DWindows.kt Thu Apr 22 00:04:01 2021 +0000 +++ b/android/DWindows.kt Thu Apr 22 17:49:20 2021 +0000 @@ -9,12 +9,9 @@ class DWindows : AppCompatActivity() { - public var windowLayout: LinearLayout = LinearLayout(this) - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(windowLayout) val m = packageManager var s = packageName @@ -31,6 +28,8 @@ */ fun windowNew(title: String, style: Int): LinearLayout { + var windowLayout: LinearLayout = LinearLayout(this) + setContentView(windowLayout) // For now we just return our DWindows' main activity layout... // in the future, later calls should create new activities return windowLayout @@ -68,6 +67,12 @@ box.addView(item) } + fun boxUnpack(item: View) + { + var box: LinearLayout = item.parent as LinearLayout + box.removeView(item) + } + fun buttonNew(text: String, cid: Int): Button { val button = Button(this)
--- a/android/dw.cpp Thu Apr 22 00:04:01 2021 +0000 +++ b/android/dw.cpp Thu Apr 22 17:49:20 2021 +0000 @@ -40,6 +40,36 @@ static HEV _dw_main_event; static JavaVM *_dw_jvm; static jobject _dw_obj; +static jobject _dw_class_loader; +static jmethodID _dw_class_method; + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) +{ + JNIEnv *env; + jclass randomClass, classClass, classLoaderClass; + jmethodID getClassLoaderMethod; + + /* Initialize the handle to the Java Virtual Machine */ + _dw_jvm = pjvm; + _dw_jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + + randomClass = env->FindClass(DW_CLASS_NAME); + classClass = env->GetObjectClass(randomClass); + classLoaderClass = env->FindClass("java/lang/ClassLoader"); + getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", + "()Ljava/lang/ClassLoader;"); + _dw_class_loader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod)); + _dw_class_method = env->GetMethodID(classLoaderClass, "findClass", + "(Ljava/lang/String;)Ljava/lang/Class;"); + + return JNI_VERSION_1_6; +} + +jclass _dw_find_class(JNIEnv *env, const char* name) +{ + return static_cast<jclass>(env->CallObjectMethod(_dw_class_loader, _dw_class_method, env->NewStringUTF(name))); +} + /* Call the dwmain entry point, Android has no args, so just pass the app path */ void _dw_main_launch(char *arg) @@ -55,15 +85,15 @@ * path: The path to the Android app. */ JNIEXPORT jstring JNICALL -Java_org_dbsoft_dwindows_dwtest_DWindows_dwindowsInit( - JNIEnv* env, jobject obj, jstring path) { +Java_org_dbsoft_dwindows_dwtest_DWindows_dwindowsInit(JNIEnv* env, jobject obj, jstring path) +{ char *arg = strdup(env->GetStringUTFChars((jstring) path, NULL)); - /* Initialize the handle to the Java Virtual Machine */ - env->GetJavaVM(&_dw_jvm); - _dw_obj = obj; + /* Save our class object pointer for later */ + _dw_obj = env->NewGlobalRef(obj); /* Save the JNIEnv for the main thread */ + pthread_key_create(&_dw_env_key, NULL); pthread_setspecific(_dw_env_key, env); /* Create the dwmain event */ @@ -367,7 +397,7 @@ if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) { // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID boxNew = env->GetMethodID(clazz, "boxNew", "(II)Landroid/widget/LinearLayout;"); // Call the method on the object @@ -431,14 +461,14 @@ } /* Internal box packing function called by the other 3 functions */ -void _dw_box_pack(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad, char *funcname) +void _dw_box_pack(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad, const char *funcname) { JNIEnv *env; if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) { // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID boxPack = env->GetMethodID(clazz, "boxPack", "(Landroid/widget/LinearLayout;Landroid/view/View;IIIIII)V"); // Call the method on the object @@ -455,6 +485,18 @@ */ int API dw_box_unpack(HWND handle) { + 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 boxUnpack = env->GetMethodID(clazz, "boxUnpack", "(Landroid/view/View;)V"); + // Call the method on the object + env->CallVoidMethod(_dw_obj, boxUnpack, handle); + return DW_ERROR_NONE; + } return DW_ERROR_GENERAL; } @@ -540,7 +582,7 @@ // Construct a String jstring jstr = env->NewStringUTF(text); // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID buttonNew = env->GetMethodID(clazz, "buttonNew", "(Ljava/lang/String;I)Landroid/widget/Button;"); @@ -560,7 +602,7 @@ // Construct a String jstring jstr = env->NewStringUTF(text); // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID entryfieldNew = env->GetMethodID(clazz, "entryfieldNew", "(Ljava/lang/String;II)Landroid/widget/EditText;"); @@ -714,7 +756,7 @@ // Construct a String jstring jstr = env->NewStringUTF(text); // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID radioButtonNew = env->GetMethodID(clazz, "radioButtonNew", "(Ljava/lang/String;I)Landroid/widget/RadioButton;"); @@ -846,7 +888,7 @@ // Construct a String jstring jstr = env->NewStringUTF(text); // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID checkboxNew = env->GetMethodID(clazz, "checkboxNew", "(Ljava/lang/String;I)Landroid/widget/CheckBox;"); @@ -1202,7 +1244,7 @@ // Construct a String jstring jstr = env->NewStringUTF(text); // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID textNew = env->GetMethodID(clazz, "textNew", "(Ljava/lang/String;II)Landroid/widget/TextView;"); @@ -2500,7 +2542,7 @@ // Construct a String jstring jstr = env->NewStringUTF(title); // First get the class that contains the method you need to call - jclass clazz = env->FindClass(DW_CLASS_NAME); + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID windowNew = env->GetMethodID(clazz, "windowNew", "(Ljava/lang/String;I)Landroid/widget/LinearLayout;");