comparison android/dw.cpp @ 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 94f0d61d6953
comparison
equal deleted inserted replaced
2476:20c9e83cba2a 2477:3fbf8783122d
38 38
39 static pthread_key_t _dw_env_key; 39 static pthread_key_t _dw_env_key;
40 static HEV _dw_main_event; 40 static HEV _dw_main_event;
41 static JavaVM *_dw_jvm; 41 static JavaVM *_dw_jvm;
42 static jobject _dw_obj; 42 static jobject _dw_obj;
43 static jobject _dw_class_loader;
44 static jmethodID _dw_class_method;
45
46 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved)
47 {
48 JNIEnv *env;
49 jclass randomClass, classClass, classLoaderClass;
50 jmethodID getClassLoaderMethod;
51
52 /* Initialize the handle to the Java Virtual Machine */
53 _dw_jvm = pjvm;
54 _dw_jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
55
56 randomClass = env->FindClass(DW_CLASS_NAME);
57 classClass = env->GetObjectClass(randomClass);
58 classLoaderClass = env->FindClass("java/lang/ClassLoader");
59 getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader",
60 "()Ljava/lang/ClassLoader;");
61 _dw_class_loader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod));
62 _dw_class_method = env->GetMethodID(classLoaderClass, "findClass",
63 "(Ljava/lang/String;)Ljava/lang/Class;");
64
65 return JNI_VERSION_1_6;
66 }
67
68 jclass _dw_find_class(JNIEnv *env, const char* name)
69 {
70 return static_cast<jclass>(env->CallObjectMethod(_dw_class_loader, _dw_class_method, env->NewStringUTF(name)));
71 }
72
43 73
44 /* Call the dwmain entry point, Android has no args, so just pass the app path */ 74 /* Call the dwmain entry point, Android has no args, so just pass the app path */
45 void _dw_main_launch(char *arg) 75 void _dw_main_launch(char *arg)
46 { 76 {
47 char *argv[2] = { arg, NULL }; 77 char *argv[2] = { arg, NULL };
53 * to be called and return. 83 * to be called and return.
54 * Parameters: 84 * Parameters:
55 * path: The path to the Android app. 85 * path: The path to the Android app.
56 */ 86 */
57 JNIEXPORT jstring JNICALL 87 JNIEXPORT jstring JNICALL
58 Java_org_dbsoft_dwindows_dwtest_DWindows_dwindowsInit( 88 Java_org_dbsoft_dwindows_dwtest_DWindows_dwindowsInit(JNIEnv* env, jobject obj, jstring path)
59 JNIEnv* env, jobject obj, jstring path) { 89 {
60 char *arg = strdup(env->GetStringUTFChars((jstring) path, NULL)); 90 char *arg = strdup(env->GetStringUTFChars((jstring) path, NULL));
61 91
62 /* Initialize the handle to the Java Virtual Machine */ 92 /* Save our class object pointer for later */
63 env->GetJavaVM(&_dw_jvm); 93 _dw_obj = env->NewGlobalRef(obj);
64 _dw_obj = obj;
65 94
66 /* Save the JNIEnv for the main thread */ 95 /* Save the JNIEnv for the main thread */
96 pthread_key_create(&_dw_env_key, NULL);
67 pthread_setspecific(_dw_env_key, env); 97 pthread_setspecific(_dw_env_key, env);
68 98
69 /* Create the dwmain event */ 99 /* Create the dwmain event */
70 _dw_main_event = dw_event_new(); 100 _dw_main_event = dw_event_new();
71 101
365 JNIEnv *env; 395 JNIEnv *env;
366 396
367 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 397 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
368 { 398 {
369 // First get the class that contains the method you need to call 399 // First get the class that contains the method you need to call
370 jclass clazz = env->FindClass(DW_CLASS_NAME); 400 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
371 // Get the method that you want to call 401 // Get the method that you want to call
372 jmethodID boxNew = env->GetMethodID(clazz, "boxNew", "(II)Landroid/widget/LinearLayout;"); 402 jmethodID boxNew = env->GetMethodID(clazz, "boxNew", "(II)Landroid/widget/LinearLayout;");
373 // Call the method on the object 403 // Call the method on the object
374 jobject result = env->CallObjectMethod(_dw_obj, boxNew, type, pad); 404 jobject result = env->CallObjectMethod(_dw_obj, boxNew, type, pad);
375 return result; 405 return result;
429 { 459 {
430 return 0; 460 return 0;
431 } 461 }
432 462
433 /* Internal box packing function called by the other 3 functions */ 463 /* Internal box packing function called by the other 3 functions */
434 void _dw_box_pack(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad, char *funcname) 464 void _dw_box_pack(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad, const char *funcname)
435 { 465 {
436 JNIEnv *env; 466 JNIEnv *env;
437 467
438 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 468 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
439 { 469 {
440 // First get the class that contains the method you need to call 470 // First get the class that contains the method you need to call
441 jclass clazz = env->FindClass(DW_CLASS_NAME); 471 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
442 // Get the method that you want to call 472 // Get the method that you want to call
443 jmethodID boxPack = env->GetMethodID(clazz, "boxPack", "(Landroid/widget/LinearLayout;Landroid/view/View;IIIIII)V"); 473 jmethodID boxPack = env->GetMethodID(clazz, "boxPack", "(Landroid/widget/LinearLayout;Landroid/view/View;IIIIII)V");
444 // Call the method on the object 474 // Call the method on the object
445 env->CallVoidMethod(_dw_obj, boxPack, box, item, index, width, height, hsize, vsize, pad); 475 env->CallVoidMethod(_dw_obj, boxPack, box, item, index, width, height, hsize, vsize, pad);
446 } 476 }
453 * Returns: 483 * Returns:
454 * DW_ERROR_NONE on success and DW_ERROR_GENERAL on failure. 484 * DW_ERROR_NONE on success and DW_ERROR_GENERAL on failure.
455 */ 485 */
456 int API dw_box_unpack(HWND handle) 486 int API dw_box_unpack(HWND handle)
457 { 487 {
488 JNIEnv *env;
489
490 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
491 {
492 // First get the class that contains the method you need to call
493 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
494 // Get the method that you want to call
495 jmethodID boxUnpack = env->GetMethodID(clazz, "boxUnpack", "(Landroid/view/View;)V");
496 // Call the method on the object
497 env->CallVoidMethod(_dw_obj, boxUnpack, handle);
498 return DW_ERROR_NONE;
499 }
458 return DW_ERROR_GENERAL; 500 return DW_ERROR_GENERAL;
459 } 501 }
460 502
461 /* 503 /*
462 * Remove windows (widgets) from a box at an arbitrary location. 504 * Remove windows (widgets) from a box at an arbitrary location.
538 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 580 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
539 { 581 {
540 // Construct a String 582 // Construct a String
541 jstring jstr = env->NewStringUTF(text); 583 jstring jstr = env->NewStringUTF(text);
542 // First get the class that contains the method you need to call 584 // First get the class that contains the method you need to call
543 jclass clazz = env->FindClass(DW_CLASS_NAME); 585 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
544 // Get the method that you want to call 586 // Get the method that you want to call
545 jmethodID buttonNew = env->GetMethodID(clazz, "buttonNew", 587 jmethodID buttonNew = env->GetMethodID(clazz, "buttonNew",
546 "(Ljava/lang/String;I)Landroid/widget/Button;"); 588 "(Ljava/lang/String;I)Landroid/widget/Button;");
547 // Call the method on the object 589 // Call the method on the object
548 jobject result = env->CallObjectMethod(_dw_obj, buttonNew, jstr, (int)cid); 590 jobject result = env->CallObjectMethod(_dw_obj, buttonNew, jstr, (int)cid);
558 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 600 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
559 { 601 {
560 // Construct a String 602 // Construct a String
561 jstring jstr = env->NewStringUTF(text); 603 jstring jstr = env->NewStringUTF(text);
562 // First get the class that contains the method you need to call 604 // First get the class that contains the method you need to call
563 jclass clazz = env->FindClass(DW_CLASS_NAME); 605 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
564 // Get the method that you want to call 606 // Get the method that you want to call
565 jmethodID entryfieldNew = env->GetMethodID(clazz, "entryfieldNew", 607 jmethodID entryfieldNew = env->GetMethodID(clazz, "entryfieldNew",
566 "(Ljava/lang/String;II)Landroid/widget/EditText;"); 608 "(Ljava/lang/String;II)Landroid/widget/EditText;");
567 // Call the method on the object 609 // Call the method on the object
568 jobject result = env->CallObjectMethod(_dw_obj, entryfieldNew, jstr, (int)cid, password); 610 jobject result = env->CallObjectMethod(_dw_obj, entryfieldNew, jstr, (int)cid, password);
712 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 754 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
713 { 755 {
714 // Construct a String 756 // Construct a String
715 jstring jstr = env->NewStringUTF(text); 757 jstring jstr = env->NewStringUTF(text);
716 // First get the class that contains the method you need to call 758 // First get the class that contains the method you need to call
717 jclass clazz = env->FindClass(DW_CLASS_NAME); 759 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
718 // Get the method that you want to call 760 // Get the method that you want to call
719 jmethodID radioButtonNew = env->GetMethodID(clazz, "radioButtonNew", 761 jmethodID radioButtonNew = env->GetMethodID(clazz, "radioButtonNew",
720 "(Ljava/lang/String;I)Landroid/widget/RadioButton;"); 762 "(Ljava/lang/String;I)Landroid/widget/RadioButton;");
721 // Call the method on the object 763 // Call the method on the object
722 jobject result = env->CallObjectMethod(_dw_obj, radioButtonNew, jstr, (int)cid); 764 jobject result = env->CallObjectMethod(_dw_obj, radioButtonNew, jstr, (int)cid);
844 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 886 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
845 { 887 {
846 // Construct a String 888 // Construct a String
847 jstring jstr = env->NewStringUTF(text); 889 jstring jstr = env->NewStringUTF(text);
848 // First get the class that contains the method you need to call 890 // First get the class that contains the method you need to call
849 jclass clazz = env->FindClass(DW_CLASS_NAME); 891 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
850 // Get the method that you want to call 892 // Get the method that you want to call
851 jmethodID checkboxNew = env->GetMethodID(clazz, "checkboxNew", 893 jmethodID checkboxNew = env->GetMethodID(clazz, "checkboxNew",
852 "(Ljava/lang/String;I)Landroid/widget/CheckBox;"); 894 "(Ljava/lang/String;I)Landroid/widget/CheckBox;");
853 // Call the method on the object 895 // Call the method on the object
854 jobject result = env->CallObjectMethod(_dw_obj, checkboxNew, jstr, (int)cid); 896 jobject result = env->CallObjectMethod(_dw_obj, checkboxNew, jstr, (int)cid);
1200 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 1242 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
1201 { 1243 {
1202 // Construct a String 1244 // Construct a String
1203 jstring jstr = env->NewStringUTF(text); 1245 jstring jstr = env->NewStringUTF(text);
1204 // First get the class that contains the method you need to call 1246 // First get the class that contains the method you need to call
1205 jclass clazz = env->FindClass(DW_CLASS_NAME); 1247 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
1206 // Get the method that you want to call 1248 // Get the method that you want to call
1207 jmethodID textNew = env->GetMethodID(clazz, "textNew", 1249 jmethodID textNew = env->GetMethodID(clazz, "textNew",
1208 "(Ljava/lang/String;II)Landroid/widget/TextView;"); 1250 "(Ljava/lang/String;II)Landroid/widget/TextView;");
1209 // Call the method on the object 1251 // Call the method on the object
1210 jobject result = env->CallObjectMethod(_dw_obj, textNew, jstr, (int)cid, status); 1252 jobject result = env->CallObjectMethod(_dw_obj, textNew, jstr, (int)cid, status);
2498 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 2540 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
2499 { 2541 {
2500 // Construct a String 2542 // Construct a String
2501 jstring jstr = env->NewStringUTF(title); 2543 jstring jstr = env->NewStringUTF(title);
2502 // First get the class that contains the method you need to call 2544 // First get the class that contains the method you need to call
2503 jclass clazz = env->FindClass(DW_CLASS_NAME); 2545 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
2504 // Get the method that you want to call 2546 // Get the method that you want to call
2505 jmethodID windowNew = env->GetMethodID(clazz, "windowNew", 2547 jmethodID windowNew = env->GetMethodID(clazz, "windowNew",
2506 "(Ljava/lang/String;I)Landroid/widget/LinearLayout;"); 2548 "(Ljava/lang/String;I)Landroid/widget/LinearLayout;");
2507 // Call the method on the object 2549 // Call the method on the object
2508 jobject result = env->CallObjectMethod(_dw_obj, windowNew, jstr, (int)flStyle); 2550 jobject result = env->CallObjectMethod(_dw_obj, windowNew, jstr, (int)flStyle);