Skip to content

Commit 5b85a03

Browse files
committed
fix call ringing on Android when app is in detached state
1 parent c507e53 commit 5b85a03

File tree

7 files changed

+41
-11
lines changed

7 files changed

+41
-11
lines changed

dogfooding/lib/app/app_content.dart

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class _StreamDogFoodingAppContentState
3535

3636
final _compositeSubscription = CompositeSubscription();
3737
bool? _microphoneEnabledBeforeInterruption;
38+
bool _isInitialized = false;
3839

3940
@override
4041
void initState() {
@@ -46,11 +47,14 @@ class _StreamDogFoodingAppContentState
4647

4748
_userAuthController.addListener(() {
4849
if (_userAuthController.currentUser != null) {
49-
_compositeSubscription.clear();
50-
initPushNotificationManagerIfAvailable();
51-
_handleMobileAudioInterruptions();
50+
// Ensure we only initialize and observe events once
51+
if (!_isInitialized) {
52+
_compositeSubscription.clear();
53+
initPushNotificationManagerIfAvailable();
54+
}
5255
} else {
5356
_compositeSubscription.clear();
57+
_isInitialized = false;
5458
}
5559
});
5660

@@ -68,6 +72,10 @@ class _StreamDogFoodingAppContentState
6872
_observeDeepLinks();
6973
// Observe FCM messages.
7074
_observeFcmMessages();
75+
76+
_handleMobileAudioInterruptions();
77+
78+
_isInitialized = true;
7179
}
7280

7381
void _handleMobileAudioInterruptions() {

packages/stream_video/lib/src/core/client_state.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
22

33
import '../../stream_video.dart' show DisconnectReason, StreamVideoOptions;
44
import '../call/call.dart';
5+
import '../lifecycle/lifecycle_state.dart';
56
import '../models/user.dart';
67
import '../state_emitter.dart';
78
import 'connection_state.dart';
@@ -49,6 +50,9 @@ abstract class ClientState {
4950
/// Removes the call from the list of active calls.
5051
/// It won't `leave` the call, just removes it from the list.
5152
Future<void> removeActiveCall(Call call);
53+
54+
// Current app's lifecycle state.
55+
StateEmitter<LifecycleState?> get appLifecycleState;
5256
}
5357

5458
class MutableClientState implements ClientState {
@@ -61,7 +65,8 @@ class MutableClientState implements ClientState {
6165
outgoingCall = MutableStateEmitterImpl(null),
6266
connection = MutableStateEmitterImpl(
6367
ConnectionState.disconnected(user.id),
64-
);
68+
),
69+
appLifecycleState = MutableStateEmitterImpl(null);
6570

6671
final StreamVideoOptions options;
6772

@@ -89,6 +94,9 @@ class MutableClientState implements ClientState {
8994
@override
9095
User get currentUser => user.value;
9196

97+
@override
98+
final MutableStateEmitter<LifecycleState?> appLifecycleState;
99+
92100
Future<void> clear() async {
93101
activeCalls.value = [];
94102
outgoingCall.value = null;

packages/stream_video/lib/src/stream_video.dart

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ class StreamVideo extends Disposable {
557557
_logger.d(() => '[onAppState] state: $state');
558558
try {
559559
final activeCalls = _state.activeCalls.value;
560+
_state.appLifecycleState.value = state;
560561

561562
if (state.isPaused) {
562563
// Handle app paused state
@@ -860,11 +861,18 @@ class StreamVideo extends Disposable {
860861
CallPreferences? acceptCallPreferences,
861862
}) {
862863
return onRingingEvent<ActionCallAccept>(
863-
(event) => _onCallAccept(
864-
event,
865-
onCallAccepted: onCallAccepted,
866-
callPreferences: acceptCallPreferences,
867-
),
864+
(event) {
865+
// Ignore call accept event when app is in detached state on Android.
866+
// The call flow should be handled by consuming the call like in the terminated state.
867+
if (!CurrentPlatform.isAndroid ||
868+
_state.appLifecycleState.value != LifecycleState.detached) {
869+
_onCallAccept(
870+
event,
871+
onCallAccepted: onCallAccepted,
872+
callPreferences: acceptCallPreferences,
873+
);
874+
}
875+
},
868876
);
869877
}
870878

packages/stream_video_flutter/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* Added `reconnectReason` to reconnect details for sfu logs.
1212
* Fixed race condition where automatic ICE restart could interfere with fast reconnect, causing subscriber video to not recover.
1313
* [iOS] Fixed CallKit event suppression to avoid repeated mute toggle loops.
14+
* [Android] Fixed issues when accepting incoming calls from detached state (app exited via back button).
15+
* [Android] Fixed incoming call notifications not showing when the app is in a detached state (e.g., after pressing the back button).
1416

1517
## 1.2.2
1618

packages/stream_video_push_notification/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
### 🐞 Fixed
77
* [iOS] Fixed CallKit event suppression to avoid repeated mute toggle loops.
8+
* [Android] Fixed issues when accepting incoming calls from detached state (app exited via back button).
9+
* [Android] Fixed incoming call notifications not showing when the app is in a detached state (e.g., after pressing the back button).
810

911
## 1.2.2
1012
* Sync version with `stream_video_flutter` 1.2.2

packages/stream_video_push_notification/android/src/main/kotlin/io/getstream/video/flutter/stream_video_push_notification/SharedPreferencesUtils.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ fun getDataActiveCalls(context: Context?): ArrayList<Data> {
5151

5252
fun getDataActiveCallsForFlutter(context: Context?): ArrayList<Map<String, Any?>> {
5353
val json = getString(context, "ACTIVE_CALLS", "[]")
54-
return Utils.getGsonInstance().readValue(json, object : TypeReference<ArrayList<Map<String, Any?>>>() {})
54+
55+
// If context is null, getString returns null, so we need to handle that case
56+
val safeJson = json ?: "[]"
57+
return Utils.getGsonInstance().readValue(safeJson, object : TypeReference<ArrayList<Map<String, Any?>>>() {})
5558
}
5659

5760
fun putString(context: Context?, key: String, value: String?) {

packages/stream_video_push_notification/android/src/main/kotlin/io/getstream/video/flutter/stream_video_push_notification/StreamVideoPushNotificationPlugin.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ override fun onDetachedFromActivityForConfigChanges() {
375375
}
376376

377377
override fun onDetachedFromActivity() {
378-
instance.context = null
379378
instance.activity = null
380379
}
381380

0 commit comments

Comments
 (0)