Давайте рассмотрим ваши предложения и посмотрим, почему они не работают:
1) вы вызываете Java-конструктор без параметров, который отображается как init()
, но этот класс не предназначен для создания с помощью обычного конструктора. Предполагается, что конструктор является закрытым, но независимо от того, в документации сказано, что вы создаете экземпляр с помощью newInstance()
.
2) вызов метода класса Create()
для импорта обычно аналогичен вызову init()
, но выполняется другим способом. Учитывая, что init
недоступен, он терпит неудачу, просто с другим симптомом здесь.
3) Вы объявили переменную типа интерфейса методов экземпляра Delphi JSipManager
, но затем присвоили ей свойство JavaClass
, которое дает тип интерфейса методов класса Delphi JSipManagerClass
. Эти 2 не одинаковы. Ожидается ошибка.
4) Шаблонный класс TJSipManager
является помощником для получения доступа к интерфейсу методов класса (через свойство JavaClass
) или к методам экземпляра через экземпляр, созданный путем вызова конструктора (может быть, через Create()
или JavaClass->init()
. Вы не должны создавать экземпляр этого шаблонного класса - он не имеет смысла.
Приступая к преобразованию (через Wrap()
) объекта контекста в SipManager
привкуса отчаяния - это совершенно разные типы.
Хорошо, теперь давайте посмотрим, почему то, что должно работать, не работает.
Причина, по которой метод newInstance()
(и другие) закомментирован из интерфейса методов класса JSipManagerClass
в исходном модуле Delphi, Androidapi.JNI.Net.pas, заключается в том, что все они имеют параметр или возвращаемый тип. например, JContext
или JIntent
, который определен и представлен из модуля, который уже использует Androidapi.JNI.Net.pas, а именно из модуля Androidapi.JNI.GraphicsContentViewText.pas.
Java2OP оставил методы там, потому что они существуют, но закомментировал их, чтобы избежать ошибки ссылки на циклические единицы.
Что будет работать, так это переопределить типы SipManager
JNI Bridge в новом модуле Delphi, добавить этот новый модуль в проект C ++, включить его сгенерированный заголовок и продолжить оттуда.
Чтобы создать модуль, вы можете щелкнуть правой кнопкой мыши по проекту в Менеджере проектов и выбрать Добавить новый, Модуль - 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
.