Mercurial > dwindows
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); |