我正在尝试使用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
对于我的应用程序,我做了以下事情:
#if defined (_PLAT_ANDROID)
_di_JObject obj;
_di_JSipManager sipm;
obj = TJSipManager::JavaClass->init();
sipm = TJSipManager::Wrap(((_di_ILocalObject)obj)->GetObjectID());
#endif
#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:[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 ++构建器中实例化它时,它不会出现属于这个类的任何类似方法。
在另一个论坛上,雷米回答说:
“在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。
让我们看看你的产品,看看它们为什么不起作用:
1)您正在调用无参数的Java构造函数,表示为init()
,但此类不是通过常规构造函数构造的。有人认为构造函数是私有的,但无论如何,文档说你通过newInstance()
创建一个实例。
2)调用导入类Create()
类方法通常与调用init()
非常相似,但是通过不同的途径完成。鉴于init
不可用,它失败了,只是在这里有不同的症状。
3)您已经声明了Delphi JSipManager
实例方法接口类型的变量,但随后为其分配了JavaClass
属性,该属性给出了Delphi JSipManagerClass
类方法的接口类型。那两个不一样。错误是可以预料的。
4)模板类TJSipManager
是通过调用构造函数(可能通过JavaClass
或Create()
)创建实例访问类方法接口(通过JavaClass->init()
属性)或实例方法的帮助器。您不应构造实例这个模板类 - 它没有任何有效的目的。继续将(通过Wrap()
)上下文对象投射到绝望的SipManager
中 - 它们是完全不同的类型。
好的,现在让我们看看为什么应该工作不起作用。
newInstance()
方法(以及其他)在原始Delphi单元Androidapi.JNI.Net.pas中的JSipManagerClass
类方法接口中注释的原因是它们都有一个参数或返回类型,如JContext
或JIntent
,它是从已经使用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
。