Skip to content

Commit 9767541

Browse files
author
StArray
committed
refactor(native): 替换所有 JniHelperNative 调用为 JniNative
- 统一替换 AndroidUtils.cs 中所有 JniHelperNative 方法为 JniNative 对应方法 - 重构 JNI.cs,JavaClass 和 JavaObject 类大量替换委托调用为 JniNative 方法封装 - JNI.cs 简化静态方法调用,增加 CallStaticObjectMethodA 等重载实现 - 优化 ImGuiEGLRender.cs 中输入钩子安装顺序调整 - 修正 ImGuiDXRenderer.cs 异常日志打印,输出完整异常对象 - 大量jni_helper.c 新增jnihelper_call_*_method_a系列方法支持变参调用 - 更新 jni_helper.h 添加多个 JNI 辅助函数的声明,增强 JNI 辅助接口完整性 - 统一使用 JniNative 替代原 JniHelperNative,简化JNI调用层代码维护 - 修复 JNI 类加载流程,调用 currentApplication 替代 currentActivityThread 方法 - 删除未使用的 Env() 方法并移除相关委托类型,清理旧代码冗余
1 parent 540e77a commit 9767541

12 files changed

Lines changed: 1239 additions & 508 deletions

File tree

‎Android/library/src/main/cpp/core/jni_helper.c‎

Lines changed: 344 additions & 7 deletions
Large diffs are not rendered by default.

‎Android/library/src/main/cpp/core/jni_helper.h‎

Lines changed: 100 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -8,113 +8,130 @@
88
extern "C" {
99
#endif
1010

11-
/**
12-
* JNI Helper - 简化 JNI 调用的辅助函数
13-
*/
14-
15-
/**
16-
* 保存 JavaVM 指针(在 JNI_OnLoad 中调用)
17-
*/
11+
// ===== 初始化 =====
1812
void jnihelper_set_jvm(JavaVM *vm);
19-
20-
/**
21-
* 获取 JavaVM
22-
*/
2313
JavaVM* jnihelper_get_jvm();
24-
25-
/**
26-
* 获取 JNIEnv(自动附加当前线程)
27-
*/
2814
JNIEnv* jnihelper_get_env();
2915

30-
/**
31-
* 查找 Java 类(返回全局引用)
32-
*/
16+
// ===== 类 / 方法 / 字段查找 =====
3317
jclass jnihelper_find_class(const char *class_name);
34-
35-
/**
36-
* 获取方法 ID
37-
*/
3818
jmethodID jnihelper_get_method_id(jclass clazz, const char *method_name, const char *signature);
39-
40-
/**
41-
* 获取静态方法 ID
42-
*/
4319
jmethodID jnihelper_get_static_method_id(jclass clazz, const char *method_name, const char *signature);
44-
45-
/**
46-
* 获取字段 ID
47-
*/
4820
jfieldID jnihelper_get_field_id(jclass clazz, const char *field_name, const char *signature);
49-
50-
/**
51-
* 获取静态字段 ID
52-
*/
5321
jfieldID jnihelper_get_static_field_id(jclass clazz, const char *field_name, const char *signature);
5422

55-
/**
56-
* 创建 Java String
57-
*/
58-
jstring jnihelper_new_string(const char *str);
59-
60-
/**
61-
* Java String 转 C string(需要调用者释放内存)
62-
*/
63-
char* jnihelper_get_string(jstring jstr);
64-
65-
/**
66-
* 删除本地引用
67-
*/
23+
// ===== 引用管理 =====
24+
jobject jnihelper_new_global_ref(jobject obj);
25+
jobject jnihelper_new_local_ref(jobject obj);
6826
void jnihelper_delete_local_ref(jobject obj);
69-
70-
/**
71-
* 删除全局引用
72-
*/
7327
void jnihelper_delete_global_ref(jobject obj);
28+
jclass jnihelper_get_object_class(jobject obj);
7429

75-
/**
76-
* 检查并清除异常
77-
*/
30+
// ===== 异常 =====
7831
jboolean jnihelper_check_exception();
32+
void jnihelper_clear_exception();
7933

80-
/**
81-
* 获取当前 Activity 或 Application
82-
*/
83-
jobject jnihelper_get_current_activity();
84-
85-
/**
86-
* 获取 Unity Surface
87-
* 调用链: UnityPlayer.currentActivity -> mUnityPlayer -> getSurfaceView() -> getHolder() -> getSurface()
88-
*/
89-
jobject jnihelper_get_unity_surface();
90-
91-
/**
92-
* 获取 Unity ANativeWindow(从 Surface 对象转换)
93-
* 返回可用于 ImGui_ImplAndroid_Init 的 ANativeWindow*
94-
*/
95-
struct ANativeWindow* jnihelper_get_unity_native_window();
96-
97-
/**
98-
* 通用 JNI 调用辅助(供 C# P/Invoke 使用)
99-
*/
34+
// ===== 字符串 =====
35+
jstring jnihelper_new_string(const char *str);
36+
char* jnihelper_get_string(jstring jstr);
37+
const char* jnihelper_get_string_utf_chars(jstring jstr);
38+
void jnihelper_release_string_utf_chars(jstring jstr, const char *utf);
39+
jsize jnihelper_get_string_length(jstring jstr);
40+
jstring jnihelper_new_string_utf(const char *utf);
41+
42+
// ===== 实例方法调用 (A 变体,通过 jvalue* 传参) =====
43+
jobject jnihelper_call_object_method_a(jobject obj, jmethodID methodID, jvalue *args);
44+
jboolean jnihelper_call_boolean_method_a(jobject obj, jmethodID methodID, jvalue *args);
45+
jbyte jnihelper_call_byte_method_a(jobject obj, jmethodID methodID, jvalue *args);
46+
jchar jnihelper_call_char_method_a(jobject obj, jmethodID methodID, jvalue *args);
47+
jshort jnihelper_call_short_method_a(jobject obj, jmethodID methodID, jvalue *args);
48+
jint jnihelper_call_int_method_a(jobject obj, jmethodID methodID, jvalue *args);
49+
jlong jnihelper_call_long_method_a(jobject obj, jmethodID methodID, jvalue *args);
50+
jfloat jnihelper_call_float_method_a(jobject obj, jmethodID methodID, jvalue *args);
51+
jdouble jnihelper_call_double_method_a(jobject obj, jmethodID methodID, jvalue *args);
52+
void jnihelper_call_void_method_a(jobject obj, jmethodID methodID, jvalue *args);
53+
54+
// ===== 实例方法调用 (无参简版) =====
10055
jobject jnihelper_call_object_method(jobject obj, jmethodID methodID);
56+
57+
// ===== 静态方法调用 (A 变体) =====
58+
jobject jnihelper_call_static_object_method_a(jclass clazz, jmethodID methodID, jvalue *args);
59+
jboolean jnihelper_call_static_boolean_method_a(jclass clazz, jmethodID methodID, jvalue *args);
60+
jbyte jnihelper_call_static_byte_method_a(jclass clazz, jmethodID methodID, jvalue *args);
61+
jchar jnihelper_call_static_char_method_a(jclass clazz, jmethodID methodID, jvalue *args);
62+
jshort jnihelper_call_static_short_method_a(jclass clazz, jmethodID methodID, jvalue *args);
63+
jint jnihelper_call_static_int_method_a(jclass clazz, jmethodID methodID, jvalue *args);
64+
jlong jnihelper_call_static_long_method_a(jclass clazz, jmethodID methodID, jvalue *args);
65+
jfloat jnihelper_call_static_float_method_a(jclass clazz, jmethodID methodID, jvalue *args);
66+
jdouble jnihelper_call_static_double_method_a(jclass clazz, jmethodID methodID, jvalue *args);
67+
void jnihelper_call_static_void_method_a(jclass clazz, jmethodID methodID, jvalue *args);
68+
69+
// ===== 静态方法调用 (无参简版) =====
10170
jobject jnihelper_call_static_object_method(jclass clazz, jmethodID methodID);
102-
jobject jnihelper_get_static_object_field(jclass clazz, jfieldID fieldID);
71+
72+
// ===== 实例字段 Get/Set =====
10373
jobject jnihelper_get_object_field(jobject obj, jfieldID fieldID);
104-
jclass jnihelper_get_object_class(jobject obj);
74+
jboolean jnihelper_get_boolean_field(jobject obj, jfieldID fieldID);
75+
jbyte jnihelper_get_byte_field(jobject obj, jfieldID fieldID);
76+
jchar jnihelper_get_char_field(jobject obj, jfieldID fieldID);
77+
jshort jnihelper_get_short_field(jobject obj, jfieldID fieldID);
78+
jint jnihelper_get_int_field(jobject obj, jfieldID fieldID);
79+
jlong jnihelper_get_long_field(jobject obj, jfieldID fieldID);
80+
jfloat jnihelper_get_float_field(jobject obj, jfieldID fieldID);
81+
jdouble jnihelper_get_double_field(jobject obj, jfieldID fieldID);
82+
83+
void jnihelper_set_object_field(jobject obj, jfieldID fieldID, jobject value);
84+
void jnihelper_set_boolean_field(jobject obj, jfieldID fieldID, jboolean value);
85+
void jnihelper_set_byte_field(jobject obj, jfieldID fieldID, jbyte value);
86+
void jnihelper_set_char_field(jobject obj, jfieldID fieldID, jchar value);
87+
void jnihelper_set_short_field(jobject obj, jfieldID fieldID, jshort value);
88+
void jnihelper_set_int_field(jobject obj, jfieldID fieldID, jint value);
89+
void jnihelper_set_long_field(jobject obj, jfieldID fieldID, jlong value);
90+
void jnihelper_set_float_field(jobject obj, jfieldID fieldID, jfloat value);
91+
void jnihelper_set_double_field(jobject obj, jfieldID fieldID, jdouble value);
92+
93+
// ===== 静态字段 Get/Set =====
94+
jobject jnihelper_get_static_object_field(jclass clazz, jfieldID fieldID);
95+
jboolean jnihelper_get_static_boolean_field(jclass clazz, jfieldID fieldID);
96+
jbyte jnihelper_get_static_byte_field(jclass clazz, jfieldID fieldID);
97+
jchar jnihelper_get_static_char_field(jclass clazz, jfieldID fieldID);
98+
jshort jnihelper_get_static_short_field(jclass clazz, jfieldID fieldID);
99+
jint jnihelper_get_static_int_field(jclass clazz, jfieldID fieldID);
100+
jlong jnihelper_get_static_long_field(jclass clazz, jfieldID fieldID);
101+
jfloat jnihelper_get_static_float_field(jclass clazz, jfieldID fieldID);
102+
jdouble jnihelper_get_static_double_field(jclass clazz, jfieldID fieldID);
103+
104+
void jnihelper_set_static_object_field(jclass clazz, jfieldID fieldID, jobject value);
105+
void jnihelper_set_static_boolean_field(jclass clazz, jfieldID fieldID, jboolean value);
106+
void jnihelper_set_static_byte_field(jclass clazz, jfieldID fieldID, jbyte value);
107+
void jnihelper_set_static_char_field(jclass clazz, jfieldID fieldID, jchar value);
108+
void jnihelper_set_static_short_field(jclass clazz, jfieldID fieldID, jshort value);
109+
void jnihelper_set_static_int_field(jclass clazz, jfieldID fieldID, jint value);
110+
void jnihelper_set_static_long_field(jclass clazz, jfieldID fieldID, jlong value);
111+
void jnihelper_set_static_float_field(jclass clazz, jfieldID fieldID, jfloat value);
112+
void jnihelper_set_static_double_field(jclass clazz, jfieldID fieldID, jdouble value);
113+
114+
// ===== 数组 =====
115+
jsize jnihelper_get_array_length(jarray array);
116+
jobject jnihelper_get_object_array_element(jobjectArray array, jsize index);
117+
void jnihelper_set_object_array_element(jobjectArray array, jsize index, jobject value);
118+
119+
// ===== Unity 集成 =====
120+
jobject jnihelper_get_current_activity();
121+
jobject jnihelper_get_unity_surface();
122+
struct ANativeWindow* jnihelper_get_unity_native_window();
105123
jobject jnihelper_surface_to_native_window(jobject surface);
106124

107-
/**
108-
* 从 AInputEvent KeyEvent 提取 Unicode 字符(通过 JNI KeyEvent.getUnicodeChar)
109-
*/
125+
// ===== Input 事件 =====
110126
uint32_t jnihelper_keyevent_get_unicode(AInputEvent *event);
111-
112-
/**
113-
* 从 Java InputEvent 对象提取并缓存 Unicode(配合 nativeInjectEvent hook)
114-
*/
115127
void jnihelper_capture_input_event_unicode(JNIEnv* env, jobject inputEvent);
116128
uint32_t jnihelper_poll_captured_unicode();
117129

130+
// ===== Data 通道(C# <-> Java) =====
131+
void jnihelper_set_data(const char *key, jint *data, int len);
132+
int jnihelper_get_data_len(const char *key);
133+
jint* jnihelper_get_data_buf(const char *key);
134+
118135
#ifdef __cplusplus
119136
}
120137
#endif

‎StArray.ModManager.Android/Managed.cs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public static int Entry(int argc, IntPtr argv)
5555
{
5656
return Il2CppInit();
5757
}
58+
5859
return IntPtr.Zero;
5960
});
6061

‎StArray.ModManager.Android/Native/AndroidUtils.cs‎

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static IntPtr GetCurrentActivity()
2929
{
3030
try
3131
{
32-
var activity = JniHelperNative.GetCurrentActivity();
32+
var activity = JniNative.GetCurrentActivity();
3333
if (activity != IntPtr.Zero) Info("AndroidUtils", $"Activity: 0x{activity:X}");
3434
return activity;
3535
}
@@ -41,14 +41,14 @@ public static void ShowToast(string message)
4141
try
4242
{
4343
using var toast = new JavaClass("android/widget/Toast");
44-
var context = JniHelperNative.GetCurrentActivity();
44+
var context = JniNative.GetCurrentActivity();
4545
if (context == IntPtr.Zero) return;
4646

4747
var makeText = toast.GetStaticMethodID("makeText",
4848
"(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;");
49-
var jMsg = JniHelperNative.NewString(message);
49+
var jMsg = JniNative.NewString(message);
5050
var toastObj = toast.CallStaticObjectMethod3(makeText, context, jMsg, 0);
51-
JniHelperNative.DeleteLocalRef(jMsg);
51+
JniNative.DeleteLocalRef(jMsg);
5252

5353
if (toastObj != IntPtr.Zero)
5454
{
@@ -75,10 +75,10 @@ public static IntPtr GetUnitySurface()
7575

7676
using var actObj = new JavaObject(activity);
7777
using var actCls = actObj.GetClass();
78-
var upField = JniHelperNative.GetFieldID(actCls.Handle, "mUnityPlayer",
78+
var upField = JniNative.GetFieldID(actCls.Handle, "mUnityPlayer",
7979
"Lcom/unity3d/player/UnityPlayerForActivityOrService;");
8080
if (upField == IntPtr.Zero)
81-
upField = JniHelperNative.GetFieldID(actCls.Handle, "mUnityPlayer",
81+
upField = JniNative.GetFieldID(actCls.Handle, "mUnityPlayer",
8282
"Lcom/unity3d/player/UnityPlayer;");
8383
if (upField == IntPtr.Zero) return IntPtr.Zero;
8484

@@ -87,21 +87,21 @@ public static IntPtr GetUnitySurface()
8787

8888
using var pObj = new JavaObject(player);
8989
using var pCls = pObj.GetClass();
90-
var getSV = JniHelperNative.GetMethodID(pCls.Handle, "getSurfaceView",
90+
var getSV = JniNative.GetMethodID(pCls.Handle, "getSurfaceView",
9191
"()Landroid/view/SurfaceView;");
9292
var sv = pObj.CallObjectMethod0(getSV);
9393
if (sv == IntPtr.Zero) return IntPtr.Zero;
9494

9595
using var svObj = new JavaObject(sv);
96-
var getH = JniHelperNative.GetMethodID(
97-
JniHelperNative.FindClass("android/view/SurfaceView"), "getHolder",
96+
var getH = JniNative.GetMethodID(
97+
JniNative.FindClass("android/view/SurfaceView"), "getHolder",
9898
"()Landroid/view/SurfaceHolder;");
9999
var holder = svObj.CallObjectMethod0(getH);
100100
if (holder == IntPtr.Zero) return IntPtr.Zero;
101101

102102
using var hObj = new JavaObject(holder);
103-
var getS = JniHelperNative.GetMethodID(
104-
JniHelperNative.FindClass("android/view/SurfaceHolder"), "getSurface",
103+
var getS = JniNative.GetMethodID(
104+
JniNative.FindClass("android/view/SurfaceHolder"), "getSurface",
105105
"()Landroid/view/Surface;");
106106
var surface = hObj.CallObjectMethod0(getS);
107107

@@ -117,8 +117,8 @@ public static IntPtr GetUnityNativeWindow()
117117
if (_cachedNativeWindow != IntPtr.Zero) return _cachedNativeWindow;
118118
var surface = GetUnitySurface();
119119
if (surface == IntPtr.Zero) return IntPtr.Zero;
120-
_cachedNativeWindow = JniHelperNative.SurfaceToNativeWindow(surface);
121-
JniHelperNative.DeleteLocalRef(surface);
120+
_cachedNativeWindow = JniNative.SurfaceToNativeWindow(surface);
121+
JniNative.DeleteLocalRef(surface);
122122
return _cachedNativeWindow;
123123
}
124124

@@ -127,7 +127,7 @@ public static IntPtr GetUnityNativeWindow()
127127
/// </summary>
128128
public static string? GetInternalFilesDir()
129129
{
130-
var context = JniHelperNative.GetCurrentActivity();
130+
var context = JniNative.GetCurrentActivity();
131131
if (context == IntPtr.Zero) return null;
132132
return GetDirFromContext(context, "getFilesDir", "()Ljava/io/File;");
133133
}
@@ -137,7 +137,7 @@ public static IntPtr GetUnityNativeWindow()
137137
/// </summary>
138138
public static string? GetExternalFilesDir()
139139
{
140-
var context = JniHelperNative.GetCurrentActivity();
140+
var context = JniNative.GetCurrentActivity();
141141
if (context == IntPtr.Zero) return null;
142142
return GetDirFromContext(context, "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;", null);
143143
}
@@ -148,14 +148,14 @@ public static IntPtr GetUnityNativeWindow()
148148
{
149149
using var ctxObj = new JavaObject(context);
150150
using var ctxCls = ctxObj.GetClass();
151-
var methodId = JniHelperNative.GetMethodID(ctxCls.Handle, methodName, sig);
151+
var methodId = JniNative.GetMethodID(ctxCls.Handle, methodName, sig);
152152

153153
IntPtr file;
154154
if (arg != null)
155155
{
156-
var jArg = JniHelperNative.NewString(arg);
156+
var jArg = JniNative.NewString(arg);
157157
file = ctxObj.CallObjectMethod1(methodId, jArg);
158-
JniHelperNative.DeleteLocalRef(jArg);
158+
JniNative.DeleteLocalRef(jArg);
159159
}
160160
else
161161
{
@@ -166,11 +166,11 @@ public static IntPtr GetUnityNativeWindow()
166166

167167
using var fileObj = new JavaObject(file);
168168
using var fileCls = fileObj.GetClass();
169-
var getPath = JniHelperNative.GetMethodID(fileCls.Handle, "getAbsolutePath", "()Ljava/lang/String;");
169+
var getPath = JniNative.GetMethodID(fileCls.Handle, "getAbsolutePath", "()Ljava/lang/String;");
170170
var pathStr = fileObj.CallObjectMethod0(getPath);
171171

172172
var result = JniHelperNative.GetString(pathStr);
173-
JniHelperNative.DeleteLocalRef(pathStr);
173+
JniNative.DeleteLocalRef(pathStr);
174174
return result;
175175
}
176176
catch (Exception ex) { Error("AndroidUtils", $"GetDirFromContext({methodName}): {ex}"); return null; }

0 commit comments

Comments
 (0)