Closed ggirotto closed 1 year ago
Hi @ggirotto, thanks for your PR & your explanation đ I will release this fix ASAP on the next release :)
I think this added code is causing my app to crash on a hard close (or maybe this is just what's catching the real error)
SwiftLiveActivitiesPlugin.swift:389 is the 'activityEventSink?.self(response)' in this section:
case .dismissed, .ended:
response["status"] = "ended"
activityEventSink?.self(response)
Stack trace:
Thread 4 Crashed:
0 libsystem_kernel.dylib 0x104108a4c __pthread_kill + 8
1 libsystem_pthread.dylib 0x10424b1d0 pthread_kill + 256
2 libsystem_c.dylib 0x18015f5ec abort + 104
3 libc++abi.dylib 0x18028bc78 abort_message + 128
4 libc++abi.dylib 0x18027d198 demangling_terminate_handler() + 300
5 libobjc.A.dylib 0x18005fbf0 _objc_terminate() + 124
6 libc++abi.dylib 0x18028b150 std::__terminate(void (*)()) + 12
7 libc++abi.dylib 0x18028db74 __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 32
8 libc++abi.dylib 0x18028db34 __cxa_throw + 132
9 libobjc.A.dylib 0x1800841d4 objc_exception_throw + 368
10 Foundation 0x180d1ba5c -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 184
11 Flutter 0x106bf63f8 -[FlutterEngine sendOnChannel:message:binaryReply:] + 264
12 Flutter 0x1071f9108 invocation function for block in SetStreamHandlerMessageHandlerOnChannel(NSObject<FlutterStreamHandler>*, NSString*, NSObject<FlutterBinaryMessenger>*, NSObject<FlutterMethodCodec>*, NSObject<FlutterTaskQueue>*) + 236
13 live_activities 0x103ebd948 thunk for @escaping @callee_unowned @convention(block) (@unowned Swift.AnyObject?) -> () + 228
14 live_activities 0x103ec8c4c closure #1 in SwiftLiveActivitiesPlugin.monitorLiveActivity<A>(_:) + 1224 (SwiftLiveActivitiesPlugin.swift:389)
15 live_activities 0x103ece39d partial apply for closure #1 in SwiftLiveActivitiesPlugin.monitorLiveActivity<A>(_:) + 1
16 live_activities 0x103ecdf55 thunk for @escaping @callee_guaranteed @Sendable @async () -> (@out A) + 1
17 live_activities 0x103ece0c1 partial apply for thunk for @escaping @callee_guaranteed @Sendable @async () -> (@out A) + 1
18 libswift_Concurrency.dylib 0x1e2c399c5 completeTaskWithClosure(swift::AsyncContext*, swift::SwiftError*) + 1
I'm still experience this issue as well. The code certainly is not causing the crash, and neither this is causing a hard crash because the exception is thrown when the app is in background.
I still couldn't find a solution to this, because it seems that Flutter framework is not calling the detach function when the engine gets destroyed.
Maybe related to this
Commenting out the added code at the top of this conversation is stopping the "crash when hard closed" issue
(I'm not currently using push notifications to update the live activities, though. I will be in the future)
Maybe adding a try/catch can help? If you can test it could be very nice đ
I tried a try/catch and still had the crash:
(been awhile since I was working in Swift very actively, so let me know if you see any issues with how I did that)
@available(iOS 16.1, *)
private func monitorLiveActivity<T : ActivityAttributes>(_ activity: Activity<T>) {
do {
try
Task {
for await state in activity.activityStateUpdates {
var response: Dictionary<String, Any> = Dictionary()
response["activityId"] = activity.id
switch state {
case .active:
monitorTokenChanges(activity)
case .dismissed, .ended:
response["status"] = "ended"
activityEventSink?.self(response)
case .stale:
response["status"] = "stale"
activityEventSink?.self(response)
@unknown default:
response["status"] = "unknown"
activityEventSink?.self(response)
}
}
}
} catch {
print("error: ");
print(error);
}
}
Also tried moving where the moving where the monitorLiveActivity function is called:
/// line 229:
if (deliveryActivity != nil) {
// monitorLiveActivity(deliveryActivity!) // TO HERE
if removeWhenAppIsKilled {
appLifecycleLifeActiviyIds.append(deliveryActivity!.id)
}
// monitorLiveActivity(deliveryActivity!) // FROM HERE
result(deliveryActivity!.id)
}
(SwiftLiveActivitiesPlugin.swift)
Same crash with both
@charlesRmajor Under what circumstances your app is crashing? The code of this PR only unregister the sinks when the app gets destroyed. Are you trying to update your live activity when your app goes to background/gets killed? If so the situation is similar as updating the live activity through push notifications and it won't work or it'll not be reliable if or without the added code.
The main question here is why the detach function is not being invoked when the Flutter engine gets destroyed.
It crashes when you hard close the app (swipe up to app selector and then swipe the app up to remove it)
I'm not currently using push notifications to update the Live Activity, but plan to before long
Added extra info to Flutter's thread https://github.com/flutter/flutter/issues/117523#issuecomment-1834547993
I don't think there's anything else we can do by now, unfortunately.
Summary: Unregister the sinks when the Flutter engine gets destroyed.
TLDR: The reason why this is necessary is because the activities can be updated and ended by using push notifications (as described in the project README). This makes possible that this function gets invoked when the app, and as a consequence Flutter engine, are killed:
https://github.com/istornz/flutter_live_activities/blob/c07dd45124b3a36a1d5583b01f5cd23c40b9b60a/ios/Classes/SwiftLiveActivitiesPlugin.swift#L341-L361
And why this is an issue? Because the app will raise the following exception:
Fatal Exception: NSInternalInconsistencyException Sending a message before the FlutterEngine has been run.
.This doesn't produce any visual inconsistency in the app, but will pollute crash tools why this fatal exception.
A more in depth discussion can be found in the following links