在c ++ builder中实例化Android SipManager

问题描述 投票:0回答:1

我正在尝试使用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. 这也编译,但在运行应用程序时,这个有一个异常类型的“中止”。 #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:[email protected]: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:[email protected]: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();

我想知道如何实例化sipManager for c ++ builder。在Java中,已经看到它使用方法“newInstance(context)”,但是当我尝试在C ++构建器中实例化它时,它不会出现属于这个类的任何类似方法。

  1. 我可以在C ++ builder中实例化吗?
  2. 什么是正确的方法呢?
  3. 如果不可能,是否有另一个库在Embarcadero中使用c ++ builder制作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接口的MISSING!

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


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

android c++ sip c++builder
1个回答
0
投票

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

1)您正在调用无参数的Java构造函数,表示为init(),但此类不是通过常规构造函数构造的。有人认为构造函数是私有的,但无论如何,文档说你通过newInstance()创建一个实例。

2)调用导入类Create()类方法通常与调用init()非常相似,但是通过不同的途径完成。鉴于init不可用,它失败了,只是在这里有不同的症状。

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

4)模板类TJSipManager是通过调用构造函数(可能通过JavaClassCreate())创建实例访问类方法接口(通过JavaClass->init()属性)或实例方法的帮助器。您不应构造实例这个模板类 - 它没有任何有效的目的。继续将(通过Wrap())上下文对象投射到绝望的SipManager中 - 它们是完全不同的类型。

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

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

Java2OP已经将方法留在那里因为它们存在,但是将它们注释掉以避免循环单元引用错误。

将在新的Delphi单元中重新定义SipManager JNI Bridge类型,将新单元添加到C ++项目中,包括其生成的标题并从那里继续。

要创建单元,可以在项目管理器中右键单击项目,然后选择Add New,Unit - Delphi。如果您只使用C ++ Builder(没有Delphi支持),只需在文本编辑器中创建单元即可。它被称为Androidapi.JNI.SIP.pas并且只包含一种类型的导入:SipManager - 为了避免歧义,我称之为基本导入界面JSipManager2

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.

然后在一些C ++代码中使用它,如下所示:

...
// 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...

这似乎编译并执行正常,但我没有SIP服务,所以不能比这更进一步。

作为分离注释,全球SharedActivityContext()函数已被弃用 - TAndroidHelper类现在包含所有类似静态方法/属性,如TAndroidHelper::Context

© www.soinside.com 2019 - 2024. All rights reserved.