我正在尝试使用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
对于我的应用程序,我已执行以下操作:
这会编译,但是在运行应用程序时会显示未找到init()方法。
#if defined (_PLAT_ANDROID)
_di_JObject obj;
_di_JSipManager sipm;
obj = TJSipManager::JavaClass->init();
sipm = TJSipManager::Wrap(((_di_ILocalObject)obj)->GetObjectID());
#endif
它也可以编译,但是在运行应用程序时,它具有“ Abort”异常类型。
#if defined (_PLAT_ANDROID)
_di_JSipManager sipm;
sipm = TJSipManager::Create();
#endif
它也可以编译,但是在运行应用程序时,它具有“访问冲突”的异常类型。
#if defined (_PLAT_ANDROID)
_di_JSipManager sipm;
sipm = TJSipManager::JavaClass;
#endif
这也可以编译,但是当我尝试打开配置文件时,它有一个异常的“异常终止”。
#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 ++构建器中实例化它时,它没有出现任何属于此类的类似方法。
我可以在C ++构建器中实例化吗?
正确的方法是什么?
如果不可能,是否还有另一个库可以使用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。
答案 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单元)定义并公开的返回类型(如JSipManagerClass
或JContext
)。
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
。