如何从 Delphi 访问 KeyCharacterMap.getEvents 函数返回的元素?
How I can access the elements returned for by KeyCharacterMap.getEvents function from Delphi?
我正在尝试使用 Delphi 中的 JKeyCharacterMap.getEvents
函数从字符中获取 KeyCode。
所以我正在使用这段代码。
uses
FMX.Platform.Android,
Androidapi.Helpers,
Androidapi.JNIBridge;
var
s : string;
PlatformKey : Word;
FKeyCharacterMap: JKeyCharacterMap;
events : TJavaObjectArray<JKeyEvent>;
event : JKeyEvent;
chars: TJavaArray<Char>;
l : integer;
begin
FKeyCharacterMap := TJKeyCharacterMap.JavaClass.load(TJKeyCharacterMap.JavaClass.BUILT_IN_KEYBOARD);
chars := TJavaArray<Char>.Create(1);
chars[0] := 'A';
events := FKeyCharacterMap.getEvents(chars);
l := events.Length; //this returns 4
if l>0 then
begin
event := events[0]; // Segmentation fault (11)
PlatformKey := event.getKeyCode;
end;
end;
但不幸的是,当我尝试访问 JKeyCharacterMap.getEvents
函数返回的数组的某些元素时,我遇到了 Segmentation fault (11)
异常。
所以问题是,如何从 Delphi?
访问 KeyCharacterMap.getEvents 函数返回的元素
更新
我使用一个断点进行调试,在这个断点处出现了异常,应用程序在此函数上失败 Androidapi.JNIBridge.TJNIResolver.GetObjectArrayElement
因为 JNIEnvRes
变量为 nil
class function TJNIResolver.GetObjectArrayElement(AArray: JNIObjectArray; Index: JNISize): JNIObject;
begin
GetJNIEnv;
//JNIEnvRes is nil
Result := JNIEnvRes^.GetObjectArrayElement(JNIEnvRes, AArray, Index);
end;
GetJNIEnv
函数无法为 JNIEnvRes
变量赋值。
class function TJNIResolver.GetJNIEnv: PJNIEnv;
begin
if JNIEnvRes = nil then
PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @JNIEnvRes, nil);
Result := JNIEnvRes;
end;
但我不知道是什么导致了这种行为。
在我的测试中,GetJNIEnv
运行良好。虽然看起来 returns 为 nil,但它是 Delphi 的调试器显示 JNIEnvRes
的错误值,如您所见 Result
不是 nil:
class function TJNIResolver.GetJNIEnv: PJNIEnv;
begin
if JNIEnvRes = nil then
PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @JNIEnvRes, nil);
Result := JNIEnvRes;
// debugger shows JNIEnvRes as nil and Result as not nil
end;
事实上,GetObjectArrayElement
正在返回预期的对象,但由于 FClassID
是 nil
,因此失败的是后续的 WrapJNIReturn
。需要 FClassID
来创建具有适当 class.
的包装器对象
WrapJNIReturn(AObject, FClassID, FBaseType.Handle, Result);
你有两种方法可以解决这个问题:
1。获取原始项目并将其包装在具有正确类型的对象中
events := FKeyCharacterMap.getEvents(chars);
l := events.Length; //this returns 4
if l>0 then
begin
//event := events[0]; // Fails!
event := TJKeyEvent.Wrap(events.GetRawItem(0)); // works
PlatformKey := event.getKeyCode;
end;
2。使用正确的 ClassID
将数组包装在一个数组中
events := TJavaObjectArray<JKeyEvent>.Wrap(FKeyCharacterMap.getEvents(chars));
l := events.Length; //this returns 4
if l>0 then
begin
event := events[0]; // now working well
PlatformKey := event.getKeyCode;
end;
我正在尝试使用 Delphi 中的 JKeyCharacterMap.getEvents
函数从字符中获取 KeyCode。
所以我正在使用这段代码。
uses
FMX.Platform.Android,
Androidapi.Helpers,
Androidapi.JNIBridge;
var
s : string;
PlatformKey : Word;
FKeyCharacterMap: JKeyCharacterMap;
events : TJavaObjectArray<JKeyEvent>;
event : JKeyEvent;
chars: TJavaArray<Char>;
l : integer;
begin
FKeyCharacterMap := TJKeyCharacterMap.JavaClass.load(TJKeyCharacterMap.JavaClass.BUILT_IN_KEYBOARD);
chars := TJavaArray<Char>.Create(1);
chars[0] := 'A';
events := FKeyCharacterMap.getEvents(chars);
l := events.Length; //this returns 4
if l>0 then
begin
event := events[0]; // Segmentation fault (11)
PlatformKey := event.getKeyCode;
end;
end;
但不幸的是,当我尝试访问 JKeyCharacterMap.getEvents
函数返回的数组的某些元素时,我遇到了 Segmentation fault (11)
异常。
所以问题是,如何从 Delphi?
访问 KeyCharacterMap.getEvents 函数返回的元素更新
我使用一个断点进行调试,在这个断点处出现了异常,应用程序在此函数上失败 Androidapi.JNIBridge.TJNIResolver.GetObjectArrayElement
因为 JNIEnvRes
变量为 nil
class function TJNIResolver.GetObjectArrayElement(AArray: JNIObjectArray; Index: JNISize): JNIObject;
begin
GetJNIEnv;
//JNIEnvRes is nil
Result := JNIEnvRes^.GetObjectArrayElement(JNIEnvRes, AArray, Index);
end;
GetJNIEnv
函数无法为 JNIEnvRes
变量赋值。
class function TJNIResolver.GetJNIEnv: PJNIEnv;
begin
if JNIEnvRes = nil then
PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @JNIEnvRes, nil);
Result := JNIEnvRes;
end;
但我不知道是什么导致了这种行为。
在我的测试中,GetJNIEnv
运行良好。虽然看起来 returns 为 nil,但它是 Delphi 的调试器显示 JNIEnvRes
的错误值,如您所见 Result
不是 nil:
class function TJNIResolver.GetJNIEnv: PJNIEnv;
begin
if JNIEnvRes = nil then
PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @JNIEnvRes, nil);
Result := JNIEnvRes;
// debugger shows JNIEnvRes as nil and Result as not nil
end;
事实上,GetObjectArrayElement
正在返回预期的对象,但由于 FClassID
是 nil
,因此失败的是后续的 WrapJNIReturn
。需要 FClassID
来创建具有适当 class.
WrapJNIReturn(AObject, FClassID, FBaseType.Handle, Result);
你有两种方法可以解决这个问题:
1。获取原始项目并将其包装在具有正确类型的对象中
events := FKeyCharacterMap.getEvents(chars);
l := events.Length; //this returns 4
if l>0 then
begin
//event := events[0]; // Fails!
event := TJKeyEvent.Wrap(events.GetRawItem(0)); // works
PlatformKey := event.getKeyCode;
end;
2。使用正确的 ClassID
将数组包装在一个数组中events := TJavaObjectArray<JKeyEvent>.Wrap(FKeyCharacterMap.getEvents(chars));
l := events.Length; //this returns 4
if l>0 then
begin
event := events[0]; // now working well
PlatformKey := event.getKeyCode;
end;