Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(android): avoid service crashes #1974

Merged
merged 12 commits into from
Mar 27, 2023

Conversation

puckey
Copy link
Collaborator

@puckey puckey commented Mar 23, 2023

Based on @kyunkakata’s work at #1666 (comment)

@puckey puckey marked this pull request as ready for review March 24, 2023 11:18
@puckey
Copy link
Collaborator Author

puckey commented Mar 24, 2023

@kyunkakata did you figure out a way to consistently cause these crashes to happen? I would like to test to make sure everything is fixed now..

@kyunkakata
Copy link

The crash "Context.startForegroundService() did not then call Service.startForeground() within 5s" is easy to reproduce. Just calling setupPlayer without invoking add function. An ANR or a crash should happen.
The second one - "#1666" is diffcult to reproduce. Base on our crash logs, our users that received this type of crash is when the app was in the background and received a push notification, then the crash happens. We tried to reproduce but got no luck. So that we need to check is app in the foreground to start MusicService and is that a MusicService notification or not to ensure that the crash will not happen.

@puckey
Copy link
Collaborator Author

puckey commented Mar 24, 2023

The crash "Context.startForegroundService() did not then call Service.startForeground() within 5s" is easy to reproduce. Just calling setupPlayer without invoking add function. An ANR or a crash should happen.

Just to make sure: did the fake_audio_channel notification code in your diff fix this issue? Would it stop the anr from happening when you don't call add() quickly enough?

@puckey puckey marked this pull request as draft March 24, 2023 20:08
@puckey
Copy link
Collaborator Author

puckey commented Mar 25, 2023

The crash "Context.startForegroundService() did not then call Service.startForeground() within 5s" is easy to reproduce. Just calling setupPlayer without invoking add function. An ANR or a crash should happen.

Just to make sure: did the fake_audio_channel notification code in your diff fix this issue? Would it stop the anr from happening when you don't call add() quickly enough?

So I added back the ANR fix, since it is necessary when you don't want to start the exoplayer notification within 5 seconds of starting MusicService. I also reject the setupPlayer promise with error code android_cannot_setup_player_in_background and have adjusted the example app implementation to retry if it failed in this way.

@kyunkakata any feedback is welcome!

@puckey puckey marked this pull request as ready for review March 25, 2023 14:30
@puckey puckey requested a review from dcvz as a code owner March 25, 2023 14:30
Copy link
Contributor

@dcvz dcvz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clever workaround! There are some typescript issues but this is looking good to go.

Thanks @puckey and @kyunkakata

example/src/App.tsx Outdated Show resolved Hide resolved
@puckey
Copy link
Collaborator Author

puckey commented Mar 27, 2023

Fixed the ts issues, so should be good to go

- reject promise when calling setupPlayer in the background
- in demo app retry setupPlayer while it fails due to being in the background
- Add back and extract ANR fix
- Fix R import
- Remove unnecessary foreground check in NotificationState.POSTED
- use DefaultLifecycleObserver over deprecated LifecycleObserver
@dcvz dcvz merged commit b70fbd7 into doublesymmetry:main Mar 27, 2023
@MortadhaFadhlaoui
Copy link

MortadhaFadhlaoui commented Mar 28, 2023

Nice Work! Thank you everyone for the fix, but we still experience the issue, due to this line

 is NotificationState.POSTED -> {
                            startForeground(it.notificationId, it.notification)
                    }

maybe this fix should be included

if (AppForegroundTracker.foregrounded && it.notificationId == MUSIC_NOTIFICATION_ID) {
startForeground(it.notificationId, it.notification)
}
startForeground(it.notificationId, it.notification)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line causing a crash as I mentioned here, @puckey wdyt about this quick fix

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
                            startForeground(it.notificationId, it.notification)
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MortadhaFadhlaoui Could you open a new pr for this with some explanation on your changes? Thanks!

@martinmidtsund
Copy link
Contributor

I'm not entirely sure the service should be foregrounded immediately after the notification is posted. Could this, together with START_STICKY which restarts the service if killed be the reason for the mAllowForeground error? In the Pocket Casts repo they only use setForeground when they start playing sound. https://github.com/Automattic/pocket-casts-android/blob/ee8da0c095560ef64a82d3a31464491b8d713104/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackService.kt#L250

shawna-donnelly pushed a commit to heistdotcom/react-native-track-player that referenced this pull request Apr 4, 2023
* fix(android): avoid service crashes

Based on @kyunkakata’s work at doublesymmetry#1666 (comment)

* fix(android): reject setupPlayer if backgrounded

* chore(android): Remove superfluous fix

as per doublesymmetry#1974 (comment)

* fix(android): When backgrounded, call setupPlayer when it comes to foreground.

* chore(android): remove more remnants of superfluous fix

* chore(android): remove unused imports

* chore(android): inline MusicModule#eventHandler

since it is never mutated..

* chore(android): simplify readableArrayToTrackList

* chore(android): remove unnecessary try catch from setupPlayer

* chore(android): refactor MusicModule#getConstants()

* fix(android): add back anr fix and reject promise when in bg

- reject promise when calling setupPlayer in the background
- in demo app retry setupPlayer while it fails due to being in the background
- Add back and extract ANR fix
- Fix R import
- Remove unnecessary foreground check in NotificationState.POSTED
- use DefaultLifecycleObserver over deprecated LifecycleObserver

* chore(docs): background error thrown in setupPlayer
shawna-donnelly pushed a commit to heistdotcom/react-native-track-player that referenced this pull request Apr 4, 2023
* fix(android): avoid service crashes

Based on @kyunkakata’s work at doublesymmetry#1666 (comment)

* fix(android): reject setupPlayer if backgrounded

* chore(android): Remove superfluous fix

as per doublesymmetry#1974 (comment)

* fix(android): When backgrounded, call setupPlayer when it comes to foreground.

* chore(android): remove more remnants of superfluous fix

* chore(android): remove unused imports

* chore(android): inline MusicModule#eventHandler

since it is never mutated..

* chore(android): simplify readableArrayToTrackList

* chore(android): remove unnecessary try catch from setupPlayer

* chore(android): refactor MusicModule#getConstants()

* fix(android): add back anr fix and reject promise when in bg

- reject promise when calling setupPlayer in the background
- in demo app retry setupPlayer while it fails due to being in the background
- Add back and extract ANR fix
- Fix R import
- Remove unnecessary foreground check in NotificationState.POSTED
- use DefaultLifecycleObserver over deprecated LifecycleObserver

* chore(docs): background error thrown in setupPlayer
@jspizziri
Copy link
Collaborator

@martinmidtsund care to submit a PR or test your theory on a fork?

@martinmidtsund
Copy link
Contributor

@jspizziri Yes, I'll be testing this and can submit a PR. Can't set a timeline though, don't know when I will get the time.

@puckey
Copy link
Collaborator Author

puckey commented Apr 12, 2023

I'm not entirely sure the service should be foregrounded immediately after the notification is posted. Could this, together with START_STICKY which restarts the service if killed be the reason for the mAllowForeground error? In the Pocket Casts repo they only use setForeground when they start playing sound. https://github.com/Automattic/pocket-casts-android/blob/ee8da0c095560ef64a82d3a31464491b8d713104/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackService.kt#L250

I wonder though – isn't there a big chance the app will be in the background already by the time the sound starts playing? i.e. the users changes the track and moves to another app directly

@martinmidtsund
Copy link
Contributor

I wonder though – isn't there a big chance the app will be in the background already by the time the sound starts playing? i.e. the users changes the track and moves to another app directly

@puckey Yes, but don't you think in those cases the mAllowForeground is true, not false? It should be allowed to start a foreground service from the foreground, and from a notification, if I'm not mistaken. This has to be tested of course.

@puckey
Copy link
Collaborator Author

puckey commented Apr 12, 2023

@martinmidtsund shall we regroup on this with a fresh issue containing stack traces as experienced using the latest rc release? Would you mind opening one?

@martinmidtsund
Copy link
Contributor

@puckey Sorry, we are not using v4 yet, so we don't have any stack traces as of now. I could create a new issue with the stack traces we do have, but they are from v3.2.0. Not sure if that helps, but I would guess it's still the same problem in the new RCs?

hlieb53 added a commit to hlieb53/react-native-track-player that referenced this pull request Nov 9, 2023
* fix(android): avoid service crashes

Based on @kyunkakata’s work at doublesymmetry/react-native-track-player#1666 (comment)

* fix(android): reject setupPlayer if backgrounded

* chore(android): Remove superfluous fix

as per doublesymmetry/react-native-track-player#1974 (comment)

* fix(android): When backgrounded, call setupPlayer when it comes to foreground.

* chore(android): remove more remnants of superfluous fix

* chore(android): remove unused imports

* chore(android): inline MusicModule#eventHandler

since it is never mutated..

* chore(android): simplify readableArrayToTrackList

* chore(android): remove unnecessary try catch from setupPlayer

* chore(android): refactor MusicModule#getConstants()

* fix(android): add back anr fix and reject promise when in bg

- reject promise when calling setupPlayer in the background
- in demo app retry setupPlayer while it fails due to being in the background
- Add back and extract ANR fix
- Fix R import
- Remove unnecessary foreground check in NotificationState.POSTED
- use DefaultLifecycleObserver over deprecated LifecycleObserver

* chore(docs): background error thrown in setupPlayer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants