【问题标题】:How to programmatically reject (hang up) incoming call on Android in Delphi?如何在 Delphi 中以编程方式拒绝(挂断)Android 上的来电?
【发布时间】:2015-10-21 18:16:35
【问题描述】:

Java 解决方案不是问题:

public boolean killCall(Context context) {
    try {
        // Get the boring old TelephonyManager
        TelephonyManager telephonyManager =
                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

        // Get the getITelephony() method
        Class classTelephony = Class.forName(telephonyManager.getClass().getName());
        Method methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony");

        // Ignore that the method is supposed to be private
        methodGetITelephony.setAccessible(true);

        // Invoke getITelephony() to get the ITelephony interface
        Object telephonyInterface = methodGetITelephony.invoke(telephonyManager);

        // Get the endCall method from ITelephony
        Class telephonyInterfaceClass =  
                Class.forName(telephonyInterface.getClass().getName());
        Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall");

        // Invoke endCall()
        methodEndCall.invoke(telephonyInterface);

    } catch (Exception ex) { // Many things can go wrong with reflection calls
        Log.d(TAG,"PhoneStateReceiver **" + ex.toString());
        return false;
    }
    return true;
}

但是如何在 Delphi 中做出同样的解决方案呢?

很遗憾,我没有找到任何解决此问题的指南。

【问题讨论】:

  • 不好意思问你为什么不用java代码?
  • @PedroLobito 因为他用 Delphi 而不是 Java 进行开发?
  • 我需要在一个用 Delphi 编写(并且必须是)的应用程序中使用它。
  • 没听说过在android上运行delphi编写的应用程序,Android大部分是基于Java、DalvikVM或ART运行时的。
  • @t0mm13b 现在你有了。 Delphi 是跨平台的,可以编译到 Win、iOS、OSX 和 Android。

标签: android delphi phone-call delphi-10-seattle


【解决方案1】:

不幸的是,由于 Delphi 的 Android Bridge 框架中的一个已知错误,您目前无法直接在 Delphi 代码中查询:

QC #120233 Android Jlang_Class interface is missing 19 methods

QP #RSP-12686 Android Jlang_Class interface is missing 19 methods

getDeclaredMethod() 是缺少的方法之一,没有它您将无法访问ITelephony 接口。因此,根据 Embarcadero 的文档,您只需用 Java 代码编写应用程序的该部分,将其包装在 .jar 文件中,然后作为外部 API 导入您的 Delphi 代码:

Using a Custom Set of Java Libraries In Your RAD Studio Android Apps

更新:在西雅图,大部分缺失的方法现已添加到Jlang_Class。但是,getDeclaredMethod() 不是其中之一,但幸运的是 getDeclaredMethods() 已添加,因此您应该可以为此编写一个小包装器,例如:

function getdeclaredMethod(Cls: Jlang_Class; const Name: JString): JMethod;
var
  Arr: TJavaObjectArray<JMethod>;
  Meth: JMethod;
  I: Integer;
begin
  Result := nil;
  Arr := Cls.getDeclaredMethods;
  for I := 0 to Arr.Length-1 do
  begin
    Meth := Arr.Items[I];
    if Meth.getName.compareTo(Name) = 0 then
    begin
      Result := Method;
      Exit;
    end;
  end;
  raise Exception.CreateFmt('method not found: %s', [Name]);
end;

然后你可以这样做:

function killCall(context: JContext): Boolean;
var
  obj: JObject;
  telephonyManager: JTelephonyManager;
  classTelephony: Jlang_Class;
  methodGetITelephony: JMethod;
  telephonyInterface: JObject;
  telephonyInterfaceClass: Jlang_Class;
  methodEndCall: JMethod;
begin
  try
    // Get the boring old TelephonyManager
    obj := context.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE);
    telephonyManager := TJTelephonyManager.Wrap((obj as ILocalObject).GetObjectID);

    // Get the getITelephony() method
    classTelephony := TJlang_Class.JavaClass.forName(telephonyManager.getClass.getName);
    methodGetITelephony := getDeclaredMethod(classTelephony, StringToJString('getITelephony'));

    // Ignore that the method is supposed to be private
    methodGetITelephony.setAccessible(True);

    // Invoke getITelephony() to get the ITelephony interface
    telephonyInterface := methodGetITelephony.invoke(telephonyManager);

    // Get the endCall method from ITelephony
    telephonyInterfaceClass := TJlang_Class.JavaClass.forName(telephonyInterface.getClass.getName);
    methodEndCall := getDeclaredMethod(telephonyInterfaceClass, StringToJString('endCall'));

    // Invoke endCall()
    methodEndCall.invoke(telephonyInterface);

    Result := True;
  except
    on E: Exception do // Many things can go wrong with reflection calls
    begin
      //
      Result := False;
    end;
  end;
end;

【讨论】:

  • 该错误是针对 XE-8 的。我有 DELPHI 10 SEATTLE。
  • 您对我有什么帮助吗?如果 bug 出现在 DELPHI 10 SEATTLE 我会试试?
  • @pudnivec74:如果您仔细观察,Jlang_Class 仍然缺少 Android 的 Class 类型中定义的几个方法,包括 getDeclaredMethod()。但是,它现在确实有 getDeclaredMethods(),它应该是 getDeclaredMethod() 的可用替代品,方法是遍历返回的数组,在每个 JMethod 上调用 getName(),直到找到所需的方法名称。
  • 对于JMethod.setAccessible,您必须使用JAccessibleObject(JMethod).setAccessible(True)。在你的情况下JAccessibleObject(methodGetITelephony).setAccessible(True)
  • 看起来invoke() 在 Delphi 中尚不可用,因此在 Embarcadero 进一步充实 JNI 桥之前,这个问题仍然无法解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多