【问题标题】:How I can access the elements returned for by KeyCharacterMap.getEvents function from Delphi?如何从 Delphi 访问 KeyCharacterMap.getEvents 函数返回的元素?
【发布时间】:2023-04-03 08:41:01
【问题描述】:

我正在尝试使用 Delphi 的 JKeyCharacterMap.getEvents 函数从 Char 中获取 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 变量为零

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;

但我不知道是什么导致了这种行为。

【问题讨论】:

  • 在失败函数的第一行放置一个断点,并单步执行代码以确定哪一行引发了错误。可能是您正在访问的数组不存在,至少在您检查它时是这样。
  • 感谢您的提示,我刚刚更新了答案。

标签: android delphi delphi-10-seattle


【解决方案1】:

在我的测试中,GetJNIEnv 运行良好。虽然看起来返回 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 正在返回预期的对象,但失败的是后续的 WrapJNIReturn,因为 FClassIDnil。需要FClassID 来创建具有正确类的包装器对象。

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;

【讨论】:

    猜你喜欢
    • 2011-08-07
    • 2011-04-08
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    相关资源
    最近更新 更多