如何在Delphi中以编程方式拒绝(挂断)Android上的来电?

2 delphi android phone-call delphi-10-seattle

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;
}
Run Code Online (Sandbox Code Playgroud)

但是如何在Delphi中制作相同的解决方案?

不幸的是我找不到任何解决这个问题的指南.

Rem*_*eau 7

不幸的是,由于Delphi的Android Bridge框架中存在已知错误,因此目前无法直接使用Delphi代码:

QC#120233 Android Jlang_Class接口缺少19种方法

QP#RSP-12686 Android Jlang_Class接口缺少19种方法

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

在RAD Studio Android应用程序中使用自定义Java库集

更新:在西雅图,现在已添加了大多数缺失的方法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;
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

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;
Run Code Online (Sandbox Code Playgroud)

  • 对于`JMethod.setAccessible`,您必须使用`JAccessibleObject(JMethod).setAccessible(True)`.在你的情况下`JAccessibleObject(methodGetITelephony).setAccessible(True)` (2认同)
  • 看起来像`invoke()`在Delphi中还没有,所以这个问题仍然无法解决,直到Embarcadero更多地充实JNI Bridge. (2认同)