在 C++ 生成器中实例化 Android SipManager
Instantiate Android SipManager in c++ builder
我正在尝试使用 C++ 生成器在 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
此外,"Use 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
这个也能编译,但是当运行应用的时候,这个有一个异常类型"Access Violation".
#if defined (_PLAT_ANDROID)
_di_JSipManager sipm;
sipm = TJSipManager::JavaClass;
#endif
这也可以编译,但是当我尝试打开配置文件时它有一个异常 "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
如果我只做SipProfile的部分,没有问题,profile就建好了。
#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();
我想知道如何实例化 SipManager for c++ builder。
在Java中已经看到它使用了方法"newInstance(context)",
但是当我尝试在 C++ 构建器中实例化它时,它没有出现任何属于此 class.
的类似方法
我可以在 C++ 构建器中实例化吗?
正确的做法是什么?
如果不可能,是否有另一个库可以使用 c++ builder 在 Embarcadero 中制作 Sip 应用程序?
在另一个论坛里,Remy 回复:
“在 C++Builder 中它应该像这样简单:
#if defined (_PLAT_ANDROID)
_di_JSipManager manager = TJSipManager::JavaClass->newInstance(SharedActivityContext());
// use manager as needed...
#endif
但实际上,这行不通(至少在西雅图,不知道以后的版本如何),因为 Androidapi.JNI.Net.hpp 中的 JSipManagerClass 接口中缺少静态 newInstance() 方法!
您可以尝试使用 Java2OP 重新导入 SipManager class,但我不知道最终是否会遇到同样的问题。"
但是我有最新版本的 Tokio,但我仍然遇到同样的问题。
我会尝试重新导入 SipManager。
让我们检查一下您的产品,看看为什么它们不起作用:
1) 您正在调用无参数 Java 构造函数,显示为 init()
但此 class 并不意味着通过常规构造函数构造。有人假设构造函数是私有的,但无论如何,文档说您通过 newInstance()
.
创建了一个实例
2) 调用 import class Create()
class 方法通常与调用 init()
非常相似,但通过不同的途径完成。鉴于 init
不可用,它失败了,只是这里的症状不同。
3) 你已经声明了一个 Delphi JSipManager
实例方法接口类型的变量,但是随后给它赋值了 JavaClass
属性,这给出了 Delphi JSipManagerClass
class 方法接口类型。那两个不一样。预计会出现错误。
4) 模板 class TJSipManager
是获取 class 方法接口(通过 JavaClass
属性)或通过调用构造函数创建的实例的实例方法(可能通过 Create()
或 JavaClass->init()
。您不应该构造此模板的实例 class - 它没有任何有效目的。
继续(通过 Wrap()
)上下文 object 变成 SipManager
绝望的味道 - 它们是完全不同的类型。
好的,现在让我们看看为什么应该起作用的却不起作用。
newInstance()
方法(和其他方法)在原始 Delphi 单元 Androidapi.JNI.Net.pas 中的 JSipManagerClass
class 方法接口中被注释掉的原因, 是它们都有一个参数或 return 类型,例如 JContext
或 JIntent
是从已经使用 Androidapi.JNI.Net.pas 的单元定义和公开的,即单元 Androidapi.JNI.GraphicsContentViewText.pas.
Java2OP 将这些方法保留在那里,因为它们存在,但将它们注释掉以避免循环单元引用错误。
有效的方法是在新的 Delphi 单元中重新定义 SipManager
JNI Bridge 类型,将该新单元添加到您的 C++ 项目中,包括其生成的 header 并继续那里。
要制作单位,您可以 right-click 在项目管理器中的项目上,然后选择添加新单位 - 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
class 现在包含所有类似静态 methods/properties 的东西,例如 TAndroidHelper::Context
.
我正在尝试使用 C++ 生成器在 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
此外,"Use 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
这个也能编译,但是当运行应用的时候,这个有一个异常类型"Access Violation".
#if defined (_PLAT_ANDROID) _di_JSipManager sipm; sipm = TJSipManager::JavaClass; #endif
这也可以编译,但是当我尝试打开配置文件时它有一个异常 "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
如果我只做SipProfile的部分,没有问题,profile就建好了。
#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();
我想知道如何实例化 SipManager for c++ builder。 在Java中已经看到它使用了方法"newInstance(context)", 但是当我尝试在 C++ 构建器中实例化它时,它没有出现任何属于此 class.
的类似方法我可以在 C++ 构建器中实例化吗?
正确的做法是什么?
如果不可能,是否有另一个库可以使用 c++ builder 在 Embarcadero 中制作 Sip 应用程序?
在另一个论坛里,Remy 回复:
“在 C++Builder 中它应该像这样简单:
#if defined (_PLAT_ANDROID)
_di_JSipManager manager = TJSipManager::JavaClass->newInstance(SharedActivityContext());
// use manager as needed...
#endif
但实际上,这行不通(至少在西雅图,不知道以后的版本如何),因为 Androidapi.JNI.Net.hpp 中的 JSipManagerClass 接口中缺少静态 newInstance() 方法!
您可以尝试使用 Java2OP 重新导入 SipManager class,但我不知道最终是否会遇到同样的问题。"
但是我有最新版本的 Tokio,但我仍然遇到同样的问题。 我会尝试重新导入 SipManager。
让我们检查一下您的产品,看看为什么它们不起作用:
1) 您正在调用无参数 Java 构造函数,显示为 init()
但此 class 并不意味着通过常规构造函数构造。有人假设构造函数是私有的,但无论如何,文档说您通过 newInstance()
.
2) 调用 import class Create()
class 方法通常与调用 init()
非常相似,但通过不同的途径完成。鉴于 init
不可用,它失败了,只是这里的症状不同。
3) 你已经声明了一个 Delphi JSipManager
实例方法接口类型的变量,但是随后给它赋值了 JavaClass
属性,这给出了 Delphi JSipManagerClass
class 方法接口类型。那两个不一样。预计会出现错误。
4) 模板 class TJSipManager
是获取 class 方法接口(通过 JavaClass
属性)或通过调用构造函数创建的实例的实例方法(可能通过 Create()
或 JavaClass->init()
。您不应该构造此模板的实例 class - 它没有任何有效目的。
继续(通过 Wrap()
)上下文 object 变成 SipManager
绝望的味道 - 它们是完全不同的类型。
好的,现在让我们看看为什么应该起作用的却不起作用。
newInstance()
方法(和其他方法)在原始 Delphi 单元 Androidapi.JNI.Net.pas 中的 JSipManagerClass
class 方法接口中被注释掉的原因, 是它们都有一个参数或 return 类型,例如 JContext
或 JIntent
是从已经使用 Androidapi.JNI.Net.pas 的单元定义和公开的,即单元 Androidapi.JNI.GraphicsContentViewText.pas.
Java2OP 将这些方法保留在那里,因为它们存在,但将它们注释掉以避免循环单元引用错误。
有效的方法是在新的 Delphi 单元中重新定义 SipManager
JNI Bridge 类型,将该新单元添加到您的 C++ 项目中,包括其生成的 header 并继续那里。
要制作单位,您可以 right-click 在项目管理器中的项目上,然后选择添加新单位 - 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
class 现在包含所有类似静态 methods/properties 的东西,例如 TAndroidHelper::Context
.