简体   繁体   English

在C ++ Builder中实例化Android SipManager

[英]Instantiate Android SipManager in c++ builder

I'm trying to instantiate the SipManager (developer.android.com) in Embarcadero with c++ builder but I'm not able to find the right way. 我正在尝试使用C ++生成器在Embarcadero中实例化SipManager(developer.android.com),但我找不到正确的方法。 For this, I'm using Delphi Interface instances. 为此,我正在使用Delphi接口实例。

In Java it is like this: 在Java中是这样的:

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

For the correct compilation of the code that will appear next, it is necessary to include the following: 为了正确编译接下来显示的代码,必须包括以下内容:

#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

In addition, the "Use Sip" and "Internet" permissions must also be added to the manifest. 此外,还必须将“使用Sip”和“ Internet”权限添加到清单中。

I tried to do it in many ways, based on the fact that I already knew how to install the WifiManager: 基于我已经知道如何安装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

For my application I have done the following: 对于我的应用程序,我已执行以下操作:

  1. This compiles but when running the application it says that the method init() is not found. 这样可以编译,但是在运行应用程序时会提示未找到方法init()。

     #if defined (_PLAT_ANDROID) _di_JObject obj; _di_JSipManager sipm; obj = TJSipManager::JavaClass->init(); sipm = TJSipManager::Wrap(((_di_ILocalObject)obj)->GetObjectID()); #endif 
  2. This compiles too, but when running the application, this one has an exception kind of "Abort". 该程序也可以编译,但是在运行应用程序时,该程序具有“ Abort”异常类型。

     #if defined (_PLAT_ANDROID) _di_JSipManager sipm; sipm = TJSipManager::Create(); #endif 
  3. This compiles too, but when running the application, this one has an exception kind of "Access Violation". 它也可以编译,但是在运行应用程序时,该类具有“访问冲突”的异常类型。

     #if defined (_PLAT_ANDROID) _di_JSipManager sipm; sipm = TJSipManager::JavaClass; #endif 
  4. This compiles too, but it has an exception kind of "Abort" when I try to open the profile. 这也可以编译,但是当我尝试打开配置文件时,它具有“ Abort”的异常类型。

     #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 

If I do only the part of the SipProfile, there is no problem and the profile is built. 如果仅执行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

And in Java it is like this: 在Java中是这样的:

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

I would like to know how to instantiate the SipManager for c++ builder. 我想知道如何实例化C ++ Builder的SipManager。 In Java, it has been seen that it uses the method "newInstance(context)" for it, but when I try to instantiate it in C++ builder it doesn't appear any similar method that belongs to this class. 在Java中,已经看到它使用了“ newInstance(context)”方法,但是当我尝试在C ++构建器中实例化它时,似乎没有任何类似的方法属于此类。

  1. Can I instantiate in C++ builder? 我可以在C ++ Builder中实例化吗?

  2. What's the right way to do it? 什么是正确的方法?

  3. If not possible, is there another library to make a Sip application in Embarcadero with c++ builder? 如果不可能,是否有另一个库可以使用C ++ Builder在Embarcadero中制作Sip应用程序?


In another forum, Remy replied: 在另一个论坛中,雷米回答:

"It SHOULD be something as simple as this in C++Builder: “在C ++ Builder中应该像这样简单:

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

But in actuality, this doesn't work (at least in Seattle, don't know about later versions) because the static newInstance() method is MISSING from the JSipManagerClass interface in Androidapi.JNI.Net.hpp! 但是实际上,这是行不通的(至少在西雅图,不知道更高版本),因为静态newInstance()方法是从Androidapi.JNI.Net.hpp中的JSipManagerClass接口丢失的!

You could try using Java2OP to re-import the SipManager class, but I don't know if that will end up suffering from the same problem or not." 您可以尝试使用Java2OP重新导入SipManager类,但是我不知道那是否最终会遇到相同的问题。”


But I have the last release of Tokio and I still have the same problem. 但是我有Tokio的最新版本,但仍然有同样的问题。 I will try to re-import the SipManager. 我将尝试重新导入SipManager。

Let's go through your offerings and see why they don't work: 让我们浏览一下您的产品,看看它们为什么不起作用:

1) you are calling the parameterless Java constructor, surfaced as init() but this class is not meant to be constructed through a regular constructor. 1)您正在调用无参数Java构造函数,表面上显示为init()但此类并非旨在通过常规构造函数构造。 One presumes that constructor is private, but regardless, the documentation says you create an instance through newInstance() . 有人假设构造函数是私有的,但是无论如何,文档说您都是通过newInstance()创建一个实例的。

2) invoking the import class Create() class method is normally much the same as calling init() , but done through a different avenue. 2)调用导入类的Create()类方法通常与调用init()几乎相同,但通过不同的途径进行。 Given init is not available it fails, just with a different symptom here. 给定init不可用,它会失败,只是此处出现其他症状。

3) You have declared a variable of the Delphi JSipManager instance methods interface type, but then assigned it the JavaClass property, which gives the Delphi JSipManagerClass class methods interface type. 3)您已经声明了Delphi JSipManager实例方法接口类型的变量,然后为其分配了JavaClass属性,该属性提供了Delphi JSipManagerClass类方法的接口类型。 Those 2 are not the same. 那两个不一样。 An error is to be expected. 可能会出现错误。

4) The template class TJSipManager is a helper to gain access to the class methods interface (through the JavaClass property) or to instance methods via an instance created by invoking a constructor (maybe via Create() or JavaClass->init() . You shouldn't construct an instance of this template class - it serves no valid purpose. Proceeding to cast (via Wrap() ) the context object into a SipManager smacks of desperation - they are wholly disparate types. 4)模板类TJSipManager是一个帮助程序(通过JavaClass属性)访问类方法接口或通过调用构造函数创建的实例(可能通过Create()JavaClass->init() )访问实例方法。不应构造此模板类的实例-它没有任何用处;继续将上下文对象(通过Wrap() )转换为SipManager绝望的消息-它们是完全不同的类型。

OK, now let's see why what should work doesn't work. 好的,现在让我们看看为什么不起作用。

The reason the newInstance() method (and others) are commented out of the JSipManagerClass class methods interface in the original Delphi unit, Androidapi.JNI.Net.pas, is that they all have a parameter or a return type such as JContext or JIntent that is defined and exposed from a unit that already uses Androidapi.JNI.Net.pas, namely the unit Androidapi.JNI.GraphicsContentViewText.pas. 之所以在原始Delphi单元Androidapi.JNI.Net.pas中的JSipManagerClass类方法接口中注释newInstance()方法(及其他方法),是因为它们都具有参数或返回类型,例如JContextJIntent它是从已经使用Androidapi.JNI.Net.pas的单元(即单元Androidapi.JNI.GraphicsContentViewText.pas)定义和公开的。

Java2OP has left the methods there because they exist, but commented them out to avoid a circular unit reference error. Java2OP之所以将这些方法保留在那里,是因为它们存在,但将它们注释掉以避免循环单元引用错误。

What will work is to redefine the SipManager JNI Bridge types in a new Delphi unit, add that new unit to your C++ project, include its generated header and proceed from there. 起作用的是在新的Delphi单元中重新定义SipManager JNI Bridge类型,将该新单元添加到您的C ++项目中,包括其生成的标头,然后从那里开始。

To make the unit you can right-click on the project in the Project Manager and choose Add New, Unit - Delphi. 要制作单元,可以右键单击项目管理器中的项目,然后选择“添加新的单元-Delphi”。 If you are using C++ Builder only (with no Delphi support) just create the unit in a text editor. 如果仅使用C ++ Builder(不支持Delphi),只需在文本编辑器中创建单元。 It's called Androidapi.JNI.SIP.pas and contains the import of just one type: SipManager - to avoid fighting with ambiguity I've called the base import interface JSipManager2 : 它称为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.

Then use it in some C++ code like this: 然后在像这样的一些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...

This seems to compile and execute OK, but I have no SIP service so cannot get further than that. 这似乎可以编译并执行OK,但是我没有SIP服务,因此无法进一步解决。

As a parting comment, the global SharedActivityContext() function is deprecated - the TAndroidHelper class now contains all that sort of thing as static methods/properties such as TAndroidHelper::Context . 作为分手注释,不推荐使用全局SharedActivityContext()函数TAndroidHelper类现在包含所有此类东西,例如TAndroidHelper::Context类的静态方法/属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM