在C ++ Builder中实例化Android SipManager

时间:2018-09-12 08:48:31

标签: android c++ sip c++builder

我正在尝试使用c ++ builder实例化Embarcadero中的SipManager(developer.android.com),但我找不到正确的方法。 为此,我正在使用Delphi接口实例。

在Java中是这样的:

public static SipManager manager;
manager = SipManager.newInstance(context);
//Context is the application context for creating the manager object.

要正确编译接下来将出现的代码,必须包括以下内容:

#include <System.Classes.hpp>
#if defined (_PLAT_ANDROID)
    #include <Androidapi.Helpers.HPP>
    #include <Androidapi.JNI.Net.HPP>
    #include <Androidapi.JNI.os.HPP>
    #include <Androidapi.JNI.Support.HPP>
    #include <Androidapi.JNI.Media.HPP>
#endif

此外,还必须将“使用Sip”和“ Internet”权限添加到清单中。

基于我已经知道如何安装WifiManager的事实,我尝试了多种方式来实现它:

#if defined (_PLAT_ANDROID)
    _di_JObject obj;
    _diJWifiManager wm;
    obj = SharedActivityContext()->getSystemService(TJContext::JavaClass->WIFI_SERVICE);
    wm = TJWifiManager::Wrap(((_di_ILocalObject)obj)->GetObjectID());
    wm->setWifiEnabled(true);
#endif

对于我的应用程序,我已执行以下操作:

  1. 这会编译,但是在运行应用程序时会显示未找到init()方法。

    #if defined (_PLAT_ANDROID)
        _di_JObject obj;
        _di_JSipManager sipm;
        obj = TJSipManager::JavaClass->init();
        sipm = TJSipManager::Wrap(((_di_ILocalObject)obj)->GetObjectID());
    #endif
    
  2. 它也可以编译,但是在运行应用程序时,它具有“ Abort”异常类型。

    #if defined (_PLAT_ANDROID)
        _di_JSipManager sipm;
        sipm = TJSipManager::Create();
    #endif
    
  3. 它也可以编译,但是在运行应用程序时,它具有“访问冲突”的异常类型。

    #if defined (_PLAT_ANDROID)
        _di_JSipManager sipm;
        sipm = TJSipManager::JavaClass;
    #endif
    
  4. 这也可以编译,但是当我尝试打开配置文件时,它有一个异常的“异常终止”。

    #if defined (_PLAT_ANDROID)
        _di_JSipManager sipm;
        _di_JContext context;
        _di_JSipProfileBuilder sippb;
        _di_JSipProfile sipp;
        context = SharedActivityContext()->getApplicationContext();
        TJSipManager *sipn = new TJSipManager();
        sipm = sipn->Wrap(((_di_ILocalObject)context) >GetObjectID());
        _di_JString uri;
        uri = StringToJString("sip:165@40.134.279.145:5060");
        sippb = TJSipProfile_Builder::JavaClass->init(uri);
        sipp = sippb->build();
        sipm->open(sipp);
    #endif
    

如果我仅执行SipProfile的一部分,就没有问题,并且配置文件已构建。

#if defined (_PLAT_ANDROID)
    _di_JSipProfileBuilder sippb;
    _di_JSipProfile sipp;
    _di_JString uri;
    uri = StringToJString("sip:165@40.134.279.145:5060");
    sippb = TJSipProfile_Builder::JavaClass->init(uri);
    sipp = sippb->build();
#endif

在Java中是这样的:

public static SipProfile me;
SipProfile.Builder builder = new SipProfile.Builder("uri");
me = builder.build();

我想知道如何实例化C ++ Builder的SipManager。 在Java中,可以看到它使用了“ newInstance(context)”方法, 但是当我尝试在C ++构建器中实例化它时,它没有出现任何属于此类的类似方法。

  1. 我可以在C ++构建器中实例化吗?

  2. 正确的方法是什么?

  3. 如果不可能,是否还有另一个库可以使用c ++ builder在Embarcadero中制作Sip应用程序?


在另一个论坛中,雷米回答:

“在C ++ Builder中应该像这样简单:

#if defined (_PLAT_ANDROID)
    _di_JSipManager manager = TJSipManager::JavaClass->newInstance(SharedActivityContext());
    // use manager as needed...
#endif

但是实际上,这是行不通的(至少在西雅图,不知道更高版本),因为静态newInstance()方法是从Androidapi.JNI.Net.hpp的JSipManagerClass接口丢失的!

您可以尝试使用Java2OP重新导入SipManager类,但是我不知道这是否最终会遇到相同的问题。”


但是我有Tokio的最新版本,但仍然有同样的问题。 我将尝试重新导入SipManager。

1 个答案:

答案 0 :(得分:0)

让我们看一下您的产品,看看为什么它们不起作用:

1)您正在调用无参数Java构造函数,表面上显示为init(),但此类并非旨在通过常规构造函数构造。一个人假设构造函数是私有的,但是不管怎么说,文档说您是通过newInstance()创建一个实例的。

2)调用导入类Create()的类方法通常与调用init()几乎相同,但是通过不同的途径进行。鉴于init不可用,它会失败,只是此处的症状有所不同。

3)您已经声明了Delphi JSipManager实例方法接口类型的变量,但随后为其分配了JavaClass属性,该属性赋予了Delphi JSipManagerClass类方法接口类型。那两个不一样。会出现错误。

4)模板类TJSipManager是一个帮助程序,用于访问类方法接口(通过JavaClass属性)或通过调用构造函数创建的实例(可能通过{ {1}}或Create(),您不应构造此模板类的实例-它没有任何作用。 继续(通过JavaClass->init()将上下文对象转换为Wrap()绝望的痕迹-它们是完全不同的类型。

好的,现在让我们看看为什么应该做的不起作用。

在原始Delphi单元Androidapi.JNI.Net.pas的SipManager类方法接口中将newInstance()方法(及其他方法)注释掉的原因是它们都具有一个参数或从已经使用Androidapi.JNI.Net.pas的单元(即Androidapi.JNI.GraphicsContentViewText.pas单元)定义并公开的返回类型(如JSipManagerClassJContext)。

Java2OP保留了这些方法的存在,因为它们已经存在,但将其注释掉以避免循环单位引用错误。

有效的方法是在新的Delphi单元中重新定义JIntent JNI Bridge类型,将该新单元添加到C ++项目中,包括其生成的标头,然后从那里开始。

要制作单元,可以在项目管理器中右键单击项目,然后选择“添加新的单元-Delphi”。如果仅使用C ++ Builder(不支持Delphi),只需在文本编辑器中创建单元。它称为Androidapi.JNI.SIP.pas,仅包含一种类型的导入:SipManager-为避免歧义,我将其称为基本导入接口SipManager

JSipManager2

然后在像这样的某些C ++代码中使用它:

unit Androidapi.JNI.SIP;

interface

uses
  Androidapi.JNIBridge,
  Androidapi.JNI.Net,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Os;

type
// ===== Forward declarations =====

  JSipManager2 = interface;//android.net.sip.SipManager

  JSipManager2Class = interface(JObjectClass)
    ['{62C12348-C7E4-4B5E-AE75-715EAAFD4465}']
    {class} function _GetEXTRA_CALL_ID: JString; cdecl;
    {class} function _GetEXTRA_OFFER_SD: JString; cdecl;
    {class} function _GetINCOMING_CALL_RESULT_CODE: Integer; cdecl;
    {class} function getCallId(incomingCallIntent: JIntent): JString; cdecl;
    {class} function getOfferSessionDescription(incomingCallIntent: JIntent): JString; cdecl;
    {class} function isApiSupported(context: JContext): Boolean; cdecl;
    {class} function isIncomingCallIntent(intent: JIntent): Boolean; cdecl;
    {class} function isSipWifiOnly(context: JContext): Boolean; cdecl;
    {class} function isVoipSupported(context: JContext): Boolean; cdecl;
    {class} function newInstance(context: JContext): JSipManager2; cdecl;
    {class} property EXTRA_CALL_ID: JString read _GetEXTRA_CALL_ID;
    {class} property EXTRA_OFFER_SD: JString read _GetEXTRA_OFFER_SD;
    {class} property INCOMING_CALL_RESULT_CODE: Integer read _GetINCOMING_CALL_RESULT_CODE;
  end;

  [JavaSignature('android/net/sip/SipManager')]
  JSipManager2 = interface(JObject)
    ['{EDE899E1-4774-41FB-BC53-03BB69565231}']
    procedure close(localProfileUri: JString); cdecl;
    function createSipSession(localProfile: JSipProfile; listener: JSipSession_Listener): JSipSession; cdecl;
    //function getSessionFor(incomingCallIntent: JIntent): JSipSession; cdecl;
    function isOpened(localProfileUri: JString): Boolean; cdecl;
    function isRegistered(localProfileUri: JString): Boolean; cdecl;
    function makeAudioCall(localProfile: JSipProfile; peerProfile: JSipProfile; listener: JSipAudioCall_Listener; timeout: Integer): JSipAudioCall; cdecl; overload;
    function makeAudioCall(localProfileUri: JString; peerProfileUri: JString; listener: JSipAudioCall_Listener; timeout: Integer): JSipAudioCall; cdecl; overload;
    procedure open(localProfile: JSipProfile); cdecl; overload;
    //procedure open(localProfile: JSipProfile; incomingCallPendingIntent: JPendingIntent; listener: JSipRegistrationListener); cdecl; overload;
    procedure register(localProfile: JSipProfile; expiryTime: Integer; listener: JSipRegistrationListener); cdecl;
    procedure setRegistrationListener(localProfileUri: JString; listener: JSipRegistrationListener); cdecl;
    //function takeAudioCall(incomingCallIntent: JIntent; listener: JSipAudioCall_Listener): JSipAudioCall; cdecl;
    procedure unregister(localProfile: JSipProfile; listener: JSipRegistrationListener); cdecl;
  end;
  TJSipManager2 = class(TJavaGenericImport<JSipManager2Class, JSipManager2>) end;

implementation

procedure RegisterTypes;
begin
  TRegTypes.RegisterType('Androidapi.JNI.SIP.JSipManager2', TypeInfo(Androidapi.JNI.SIP.JSipManager2));
end;

initialization
  RegisterTypes;
end.

这似乎可以编译并执行,但是我没有SIP服务,因此无法进一步解决。

不建议使用全局... // Cleanse build of lots of errors about __cdecl... #define __cdecl #include "Androidapi.JNI.SIP.hpp" #include <Androidapi.Helpers.hpp> ... _di_JSipManager2 manager = TJSipManager2::JavaClass->newInstance(TAndroidHelper::Context); // use manager as needed... 函数-SharedActivityContext()类现在包含所有类似静态方法/属性的东西,例如TAndroidHelper