-
Notifications
You must be signed in to change notification settings - Fork 79
/
jni_util.go
124 lines (112 loc) · 4.56 KB
/
jni_util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package android
import "errors"
type SoftKeyboardState int32
const (
SoftKeyboardHidden SoftKeyboardState = iota
SoftKeyboardVisible
)
// SetSoftKeyboardState allows to toggle Android virtual keyboard using JNI calls into JavaVM.
func (a *NativeActivity) SetSoftKeyboardState(state SoftKeyboardState) error {
return a.JNICall(func(env *JNIEnv, activity Jobject, activityClass, contextClass *Jclass) error {
// Context.INPUT_METHOD_SERVICE
inputMethodService := JNIEnvGetStaticObjectField(env, contextClass,
JNIEnvGetStaticFieldID(env, contextClass,
s("INPUT_METHOD_SERVICE"), JClassString.Spec().Sig()),
)
if inputMethodService == nil {
return errors.New("failed to get INPUT_METHOD_SERVICE")
}
// getSystemService(Context.INPUT_METHOD_SERVICE)
getSystemService := JNIEnvGetMethodID(env, activityClass,
s("getSystemService"), JNIMethodSig(JClassObject.Spec(), JClassString.Spec()))
inputMethodManager := JNIEnvCallObjectMethod(env, activity, getSystemService, []Jvalue{
JobjectV(inputMethodService),
})
if inputMethodManager == nil {
return errors.New("failed to run getSystemService()")
}
defer JNIEnvDeleteLocalRef(env, inputMethodManager)
// getWindow().getDecorView()
getWindowMethod := JNIEnvGetMethodID(env, activityClass,
s("getWindow"), JNIMethodSig(JClassWindow.Spec()))
getDecorViewMethod := JNIEnvGetMethodID(env, JNIEnvFindClass(env, JClassWindow.Name()),
s("getDecorView"), JNIMethodSig(JClassView.Spec()))
window := JNIEnvCallObjectMethod(env, activity, getWindowMethod, nil)
if window == nil {
return errors.New("failed to run getWindow()")
}
defer JNIEnvDeleteLocalRef(env, window)
decorView := JNIEnvCallObjectMethod(env, window, getDecorViewMethod, nil)
if decorView == nil {
return errors.New("failed to run getDecorView()")
}
defer JNIEnvDeleteLocalRef(env, decorView)
switch state {
case SoftKeyboardHidden:
const flags = 0
// decorView.getWindowToken()
getWindowTokenMethod := JNIEnvGetMethodID(env,
JNIEnvFindClass(env, JClassView.Name()),
s("getWindowToken"), JNIMethodSig(JClassIBinder.Spec()))
binder := JNIEnvCallObjectMethod(env, decorView, getWindowTokenMethod, nil)
if binder == nil {
return errors.New("failed to run getWindowToken()")
}
defer JNIEnvDeleteLocalRef(env, binder)
// inputMethodManager.hideSoftInputFromWindow(...)
hideSoftInputFromWindowMethod := JNIEnvGetMethodID(env,
JNIEnvFindClass(env, JClassInputMethodManager.Name()),
s("hideSoftInputFromWindow"), JNIMethodSig(JBoolean.Spec(), JClassIBinder.Spec(), JInt.Spec()))
result := JNIEnvCallBooleanMethod(env, inputMethodManager,
hideSoftInputFromWindowMethod, []Jvalue{
JobjectV(binder), JintV(flags),
})
if result == JNIFalse {
return errors.New("failed to run hideSoftInputFromWindow()")
}
case SoftKeyboardVisible:
const flags = 0
// inputMethodManager.showSoftInput(...)
showSoftInputMethod := JNIEnvGetMethodID(env,
JNIEnvFindClass(env, JClassInputMethodManager.Name()),
s("showSoftInput"), JNIMethodSig(JBoolean.Spec(), JClassView.Spec(), JInt.Spec()))
result := JNIEnvCallBooleanMethod(env, inputMethodManager,
showSoftInputMethod, []Jvalue{
JobjectV(decorView), JintV(flags),
})
if result == JNIFalse {
return errors.New("failed to run showSoftInput()")
}
}
return nil
})
}
// KeyEventGetUnicodeChar gets the Unicode character generated by the specified key and meta key state combination.
func (a *NativeActivity) KeyEventGetUnicodeChar(action, keyCode, metaState int32) (rune, error) {
var result rune
err := a.JNICall(func(env *JNIEnv, activity Jobject, activityClass, contextClass *Jclass) error {
keyEventClass := JNIEnvFindClass(env, JClassKeyEvent.Name())
keyEventInit := JNIEnvGetMethodID(env, keyEventClass,
s("<init>"), JNIMethodSig(JVoid.Spec(), JInt.Spec(), JInt.Spec()))
keyEvent := JNIEnvNewObject(env, keyEventClass, keyEventInit, []Jvalue{
JintV(action), JintV(keyCode),
})
defer JNIEnvDeleteLocalRef(env, keyEvent)
if keyEvent == nil {
return errors.New("failed to construct new KeyEvent")
}
if metaState == 0 {
getUnicodeCharMethod := JNIEnvGetMethodID(env, keyEventClass,
s("getUnicodeChar"), JNIMethodSig(JInt.Spec()))
result = rune(JNIEnvCallIntMethod(env, keyEvent, getUnicodeCharMethod, nil))
} else {
getUnicodeCharMethod := JNIEnvGetMethodID(env, keyEventClass,
s("getUnicodeChar"), JNIMethodSig(JInt.Spec(), JInt.Spec()))
result = rune(JNIEnvCallIntMethod(env, keyEvent, getUnicodeCharMethod, []Jvalue{
JintV(metaState),
}))
}
return nil
})
return result, err
}