Skip to content

Commit 6da71a2

Browse files
committed
SDK: v1.0.31
1 parent e00c2ac commit 6da71a2

File tree

10 files changed

+141
-23
lines changed

10 files changed

+141
-23
lines changed

siprix_voip_sdk/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
## 1.0.31
2+
- Updated upgradeToVideo implementation. Added new mode 'manual'
3+
- Added new event 'onCallVideoUpgradeRequested'
4+
Triggered when specified 'acc.upgradeToVideo=manual' and remote side requests to add video
5+
- Added new method 'acceptVideoUpgrade'
6+
App has invoke it from 'onCallVideoUpgradeRequested' event handler
7+
- iOS: Added new method 'endCallKitCall'
8+
Example app uses it to end CallKit calls when SIP INVITE hasn't received
9+
- Android: Added ability to disable displaying activity on lock screen by adding to manifest
10+
`<meta-data android:name="com.siprix.DontShowWhenLocked" android:value="true" />`
11+
//2025.11.16
12+
113
## 1.0.30
214
- Added new setting 'acc.upgradeToVideo' and event 'onCallVideoUpgraded'
315
//2025.11.07
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
distributionBase=GRADLE_USER_HOME
2-
distributionPath=wrapper/dists
3-
zipStoreBase=GRADLE_USER_HOME
4-
zipStorePath=wrapper/dists
5-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
4+
networkTimeout=10000
5+
validateDistributionUrl=true
6+
zipStoreBase=GRADLE_USER_HOME
7+
zipStorePath=wrapper/dists

siprix_voip_sdk/example/android/settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pluginManagement {
2323

2424
plugins {
2525
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
26-
id "com.android.application" version '8.1.4' apply false
26+
id "com.android.application" version '8.2.1' apply false
2727
}
2828

2929
include ":app"

siprix_voip_sdk/example/lib/account_add.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ class AccountPageState extends State<AccountPage> {
309309
onChanged: (String? value) { setState(() { _account.userAgent = value; }); },
310310
initialValue: _account.userAgent,
311311
),
312+
_buildUpgradeToVideModeDropDown()
312313
];
313314
}
314315

@@ -354,6 +355,26 @@ class AccountPageState extends State<AccountPage> {
354355
);
355356
}
356357

358+
Widget _buildUpgradeToVideModeDropDown() {
359+
return ButtonTheme(alignedDropdown: true, child:
360+
DropdownButtonFormField<UpgradeToVideoMode>(
361+
decoration: InputDecoration(
362+
border: const UnderlineInputBorder(),
363+
labelText: 'Upgrade to video mode:',
364+
labelStyle: TextStyle(color: isAddMode() ? null : Theme.of(context).disabledColor),
365+
),
366+
value: _account.upgradeToVideo,
367+
onChanged: (UpgradeToVideoMode? value) { setState(() { _account.upgradeToVideo = value!; }); },
368+
items: UpgradeToVideoMode.values.map((t) => _upgradeTovideoModeItem(t)).toList()
369+
));
370+
}
371+
372+
DropdownMenuItem<UpgradeToVideoMode> _upgradeTovideoModeItem(UpgradeToVideoMode mode) {
373+
return DropdownMenuItem<UpgradeToVideoMode>(value: mode, child:
374+
Text(mode.name, style:Theme.of(context).textTheme.bodyMedium,)
375+
);
376+
}
377+
357378
void _submit() {
358379
final form = _formKey.currentState;
359380
if (form == null || !form.validate() ||

siprix_voip_sdk/example/lib/calls_model_app.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// ignore_for_file: non_constant_identifier_names
22

3+
import 'dart:async';
34
import 'dart:io';
45

56
import 'package:siprix_voip_sdk/calls_model.dart';
@@ -18,6 +19,8 @@ class CallMatcher {
1819
String push_Hint;
1920
///Id assigned by library when SIP INVITE received
2021
int sip_CallId;
22+
///Timestamp when this item has been created
23+
DateTime timestamp = DateTime.now();
2124

2225
CallMatcher(this.callkit_CallUUID, this.push_Hint, [this.sip_CallId=0]);
2326
}
@@ -31,6 +34,7 @@ class AppCallsModel extends CallsModel {
3134

3235
final ILogsModel? _logs;
3336
final List<CallMatcher> _callMatchers=[];//iOS PushKit specific impl
37+
Timer? _pushNotifTimer;
3438

3539
/// Handle iOS Pushkit notification received by library (parse payload, update CallKit window, store data from push payload)
3640
@override
@@ -62,6 +66,9 @@ class AppCallsModel extends CallsModel {
6266

6367
//Update CallKit
6468
SiprixVoipSdk().updateCallKitCallDetails(callkit_CallUUID, sipCallId, localizedCallerName, genericHandle, withVideo);
69+
70+
//Start timer which cleanups CallKit calls when SIP not received
71+
_startPushNotifTimer();
6572
}
6673

6774
@override
@@ -102,6 +109,30 @@ class AppCallsModel extends CallsModel {
102109
}
103110
}
104111
}
112+
113+
void _startPushNotifTimer() {
114+
if(_pushNotifTimer != null) return;
115+
116+
const Duration kTimerDelay = Duration(seconds: 1);
117+
const Duration kEndCallDelay = Duration(seconds: 15);
118+
119+
_pushNotifTimer = Timer.periodic(kTimerDelay, (Timer timer) {
120+
DateTime now = DateTime.now();
121+
for(int i = _callMatchers.length-1; i>=0; --i) {
122+
//End CallKit call when SIP INVITE hasn't received during kEndCallDelay
123+
CallMatcher cm = _callMatchers[i];
124+
if((cm.sip_CallId==0) && now.difference(cm.timestamp) > kEndCallDelay) {
125+
SiprixVoipSdk().endCallKitCall(cm.callkit_CallUUID);
126+
_callMatchers.removeAt(i);
127+
}
128+
}
129+
130+
if(_callMatchers.isEmpty) {
131+
_pushNotifTimer?.cancel();
132+
_pushNotifTimer = null;
133+
}
134+
});
135+
}
105136
}
106137

107138
/*

siprix_voip_sdk/example/lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ class _MyAppState extends State<MyApp> {
207207
//vdoData.bitrateKbps = 800;
208208
//SiprixVoipSdk().setVideoParams(vdoData);
209209

210-
//Detect version
210+
//Check the version
211211
//String? version = await SiprixVoipSdk().version();
212212
//debugPrint("Siprix version: $version");
213213
}

siprix_voip_sdk/lib/accounts_model.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,9 @@ enum UpgradeToVideoMode {
269269
/// Accept video from remote side, don't send (mute) local
270270
RecvOnly(SiprixVoipSdk.kUpgradeToVideoRecvOnly, "RecvOnly"),
271271
/// Don't accept video from remote side (continue audio only call)
272-
Inactive(SiprixVoipSdk.kUpgradeToVideoInactive, "Inactive");
272+
Inactive(SiprixVoipSdk.kUpgradeToVideoInactive, "Inactive"),
273+
/// Trigger event 'OnCallVideoUpgradeRequested', ask user confirmation and invoke 'AcceptVideoUpgrade(true/false)'
274+
Manual(SiprixVoipSdk.kUpgradeToVideoManual, "Manual");
273275

274276
const UpgradeToVideoMode(this.id, this.name);
275277
/// Value
@@ -282,6 +284,7 @@ enum UpgradeToVideoMode {
282284
switch(val) {
283285
case SiprixVoipSdk.kUpgradeToVideoSendRecv: return UpgradeToVideoMode.SendRecv;
284286
case SiprixVoipSdk.kUpgradeToVideoInactive: return UpgradeToVideoMode.Inactive;
287+
case SiprixVoipSdk.kUpgradeToVideoManual : return UpgradeToVideoMode.Manual;
285288
default: return UpgradeToVideoMode.RecvOnly;
286289
}
287290
}

siprix_voip_sdk/lib/calls_model.dart

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ class CallModel extends ChangeNotifier {
178178
bool _isMicMuted=false;
179179
bool _isCamMuted=false;
180180
bool _isRecStarted=false;
181+
bool _isUpgradingToVideo=false;
181182
final ILogsModel? _logs;
182183

183184
/// State of this call
@@ -205,6 +206,7 @@ class CallModel extends ChangeNotifier {
205206
bool get isMicMuted => _isMicMuted;
206207
bool get isCamMuted => _isCamMuted;
207208
bool get isRecStarted => _isRecStarted;
209+
bool get isUpgradingToVideo => _isUpgradingToVideo;
208210
bool get isFilePlaying => _playerId!=0;
209211
bool get hasVideo => _hasVideo;
210212
int get playerId => _playerId;
@@ -419,7 +421,7 @@ class CallModel extends ChangeNotifier {
419421

420422
try{
421423
await SiprixVoipSdk().upgradeToVideo(myCallId);
422-
_hasVideo = true;
424+
_isUpgradingToVideo = true;
423425
notifyListeners();
424426
} on PlatformException catch (err) {
425427
_logs?.print('Can\'t upgrade callId:$myCallId Err: ${err.code} ${err.message}');
@@ -470,8 +472,11 @@ class CallModel extends ChangeNotifier {
470472

471473
/// Handle upgrade to video
472474
void onVideoUpgraded(bool withVideo, bool isUpgradeModeRecvOnly) {
475+
//Siprix mutes camera when upgrade video request received from remote side AND mode set as recvOnly
476+
if(withVideo && isUpgradeModeRecvOnly && !_isUpgradingToVideo) _isCamMuted = true;
477+
473478
_hasVideo = withVideo;
474-
if(isUpgradeModeRecvOnly) _isCamMuted = true;
479+
_isUpgradingToVideo = false;
475480
notifyListeners();
476481
}
477482

@@ -514,7 +519,9 @@ class CallModel extends ChangeNotifier {
514519
typedef ResolveContactNameCallback = String Function(String phoneNumber);
515520
/// Callback function which is raised by model when call switched
516521
typedef CallSwitchedCallCallback = void Function(int callId);
517-
/// Callback function which is raised by model when new incomning call
522+
/// Callback function which is raised by model when upgrade to video requeste received
523+
typedef CallVideoUpgradeRequestedCallback = void Function(int callId);
524+
/// Callback function which is raised by model when new incoming call received
518525
typedef NewIncomingCallCallback = void Function();
519526

520527
//--------------------------------------------------------------------------
@@ -542,7 +549,8 @@ class CallsModel extends ChangeNotifier {
542549
terminated : onTerminated,
543550
transferred : onTransferred,
544551
redirected : onRedirected,
545-
videoUpgraded: onVideoUpgraded,
552+
videoUpgraded : onVideoUpgraded,
553+
videoUpgradeRequested : onVideoUpgradeRequested,
546554
dtmfReceived : onDtmfReceived,
547555
switched : onSwitched,
548556
held : onHeld
@@ -553,8 +561,10 @@ class CallsModel extends ChangeNotifier {
553561
ResolveContactNameCallback? onResolveContactName;
554562
/// Callback function which is raised by model when call switched
555563
CallSwitchedCallCallback? onSwitchedCall;
556-
/// Callback function which is raised by model when new incomning call received
564+
/// Callback function which is raised by model when new incoming call received
557565
NewIncomingCallCallback? onNewIncomingCall;
566+
/// Callback function which is raised by model when video upgrade request received
567+
CallVideoUpgradeRequestedCallback? onVideoUpgradeRequestReceived;
558568

559569
/// Returns true when list of calls is empty
560570
bool get isEmpty => _callItems.isEmpty;
@@ -773,6 +783,12 @@ class CallsModel extends ChangeNotifier {
773783
_callItems[index].onVideoUpgraded(withVideo, isUpgradeModeRecvOnly);
774784
}
775785

786+
/// Handle upgrade to video request
787+
void onVideoUpgradeRequested(int callId) {
788+
_logs?.print('onVideoUpgradeRequested callId:$callId');
789+
onVideoUpgradeRequestReceived?.call(callId);
790+
}
791+
776792
/// Handle receive DTMF event raised by library and route it to matched call instance
777793
void onDtmfReceived(int callId, int tone) {
778794
_logs?.print('onDtmfReceived callId:$callId tone:$tone');
@@ -804,7 +820,7 @@ class CallsModel extends ChangeNotifier {
804820
/// Handle call switched event raised by library
805821
void onPlayerStateChanged(int playerId, PlayerState state) {
806822
_logs?.print('onPlayerStateChanged playerId:$playerId $state');
807-
for(final call in _callItems)
823+
for(final call in _callItems)
808824
if(call.onPlayerStateChanged(playerId, state)) break;
809825
}
810826

siprix_voip_sdk/lib/siprix_voip_sdk.dart

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,17 @@ class CallVideoUpgradedArg {
221221
}
222222
}
223223

224+
/// Helper class for handling 'onCallVideoUpgradeRequested' event raised by library
225+
class CallVideoUpgradeRequestedArg {
226+
int callId=0;
227+
bool fromMap(Map<dynamic, dynamic> argsMap) {
228+
int argsCounter=0;
229+
argsMap.forEach((key, value) {
230+
if((key == SiprixVoipSdkPlatform.kArgCallId)&&(value is int)) { callId = value; argsCounter+=1; }
231+
});
232+
return (argsCounter==1);
233+
}
234+
}
224235

225236
/// Helper class for handling 'onCallRedirected' event raised by library
226237
class CallRedirectedArg {
@@ -388,8 +399,8 @@ class NetStateListener {
388399
class CallStateListener {
389400
CallStateListener({this.proceeding, this.incoming, this.incomingPush, this.acceptNotif,
390401
this.connected, this.terminated, this.dtmfReceived,
391-
this.transferred, this.redirected, this.videoUpgraded, this.held, this.switched,
392-
this.playerStateChanged});
402+
this.transferred, this.redirected, this.videoUpgraded, this.videoUpgradeRequested,
403+
this.held, this.switched, this.playerStateChanged});
393404

394405
///Triggered by library when changed player state in specific call
395406
void Function(int playerId, PlayerState s)? playerStateChanged;
@@ -411,6 +422,8 @@ class CallStateListener {
411422
void Function(int origCallId, int relatedCallId, String referTo)? redirected;
412423
///Triggered by library when remote side requested to start send/receive video and request accepted.
413424
void Function(int callId, bool withVideo)? videoUpgraded;
425+
///Triggered by library when remote side requested to start send/receive video
426+
void Function(int callId)? videoUpgradeRequested;
414427
///Triggered by library when received DTMF tone from remote side.
415428
void Function(int callId, int tone)? dtmfReceived;
416429
///Triggered by library when local or remote side has put call on hold
@@ -545,6 +558,7 @@ class SiprixVoipSdk {
545558
static const int kUpgradeToVideoSendRecv = 0;
546559
static const int kUpgradeToVideoRecvOnly = 1;
547560
static const int kUpgradeToVideoInactive = 2;
561+
static const int kUpgradeToVideoManual = 3;
548562

549563
///Error codes constants
550564
static const int eOK = 0;
@@ -749,6 +763,11 @@ class SiprixVoipSdk {
749763
return _platform.upgradeToVideo(callId);
750764
}
751765

766+
/// Accept requested upgrade of the call's media and specify is allowed to use video
767+
Future<void> acceptVideoUpgrade(int callId, bool withVideo) async {
768+
return _platform.acceptVideoUpgrade(callId, withVideo);
769+
}
770+
752771
/// Stop playing (mute) ringtone.
753772
Future<void> stopRingtone() async {
754773
return _platform.stopRingtone();
@@ -900,6 +919,12 @@ class SiprixVoipSdk {
900919
return _platform.getCallKitCallUUID(sip_callId);
901920
}
902921

922+
///End CallKit call specified by its UUID (Allowed to use only when missed SIP signalling for that call)
923+
Future<void>? endCallKitCall(String callkit_CallUUID) {
924+
return _platform.endCallKitCall(callkit_CallUUID);
925+
}
926+
927+
903928
//-//////////////////////////////////////////////////////////////////////////////////////
904929
//-Android specific implementation
905930

@@ -944,6 +969,7 @@ class SiprixVoipSdk {
944969
case SiprixVoipSdkPlatform.kOnCallTransferred : _onCallTransferred(argsMap); break;
945970
case SiprixVoipSdkPlatform.kOnCallRedirected : _onCallRedirected(argsMap); break;
946971
case SiprixVoipSdkPlatform.kOnCallVideoUpgraded: _onCallVideoUpgraded(argsMap); break;
972+
case SiprixVoipSdkPlatform.kOnCallVideoUpgradeRequested: _onCallVideoUpgradeRequested(argsMap); break;
947973
case SiprixVoipSdkPlatform.kOnCallSwitched : _onCallSwitched(argsMap); break;
948974
case SiprixVoipSdkPlatform.kOnCallHeld : _onCallHeld(argsMap); break;
949975

@@ -1039,6 +1065,13 @@ class SiprixVoipSdk {
10391065
}
10401066
}
10411067

1068+
void _onCallVideoUpgradeRequested(Map<dynamic, dynamic> argsMap) {
1069+
CallVideoUpgradeRequestedArg arg = CallVideoUpgradeRequestedArg();
1070+
if(arg.fromMap(argsMap)) {
1071+
callListener?.videoUpgradeRequested?.call(arg.callId);
1072+
}
1073+
}
1074+
10421075
void _onCallRedirected(Map<dynamic, dynamic> argsMap) {
10431076
CallRedirectedArg arg = CallRedirectedArg();
10441077
if(arg.fromMap(argsMap)) {

siprix_voip_sdk/pubspec.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Siprix VoIP SDK plugin for embedding voice-over-IP (VoIP) audio/vid
33
homepage: https://siprix-voip.com
44
repository: https://github.com/siprix/FlutterPluginFederated/tree/main/siprix_voip_sdk
55
documentation: https://docs.siprix-voip.com
6-
version: 1.0.30
6+
version: 1.0.31
77

88
environment:
99
sdk: ^3.2.0
@@ -27,12 +27,12 @@ dependencies:
2727
flutter:
2828
sdk: flutter
2929
intl: ^0.20.1
30-
siprix_voip_sdk_android: ^1.0.23
31-
siprix_voip_sdk_ios: ^1.0.27
32-
siprix_voip_sdk_linux: ^1.0.17
33-
siprix_voip_sdk_macos: ^1.0.17
34-
siprix_voip_sdk_windows: ^1.0.18
35-
siprix_voip_sdk_platform_interface: ^1.0.9
30+
siprix_voip_sdk_android: ^1.0.24
31+
siprix_voip_sdk_ios: ^1.0.28
32+
siprix_voip_sdk_linux: ^1.0.18
33+
siprix_voip_sdk_macos: ^1.0.18
34+
siprix_voip_sdk_windows: ^1.0.19
35+
siprix_voip_sdk_platform_interface: ^1.0.10
3636

3737
dev_dependencies:
3838
flutter_test:

0 commit comments

Comments
 (0)