androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.76k stars 423 forks source link

Implement LifecycleService in MediaSessionService and DownloadService #187

Open yschimke opened 2 years ago

yschimke commented 2 years ago

LifecycleOwner is a lifecycle aware option for Services. There is a base class LifecycleService which manages this, or you can implement LifecycleOwner and use ServiceLifecycleDispatcher

See https://developer.android.com/reference/androidx/lifecycle/LifecycleService https://developer.android.com/reference/androidx/lifecycle/ServiceLifecycleDispatcher

and https://www.daniweb.com/programming/mobile-development/tutorials/537446/android-native-how-to-implement-lifecycleowner-in-a-service

marcbaechinger commented 2 years ago

Can you briefly educate me in how you would use the MediaSessionService in you app or library when it is lifecycle aware and dispatches the events accordingly?

I'm asking because onCreate/onDestroy is fairly simple in a service. What events are you interested in and what is depending on these? How would a media library service developer use the bind/start events?

yschimke commented 2 years ago

You can get a CoroutineScope for the current component (Service, Activity) such as

https://github.com/google/horologist/blob/10fb61ff97458dbbe004039eca2f94a320ac69da/media-sample/src/main/java/com/google/android/horologist/mediasample/di/PlaybackServiceModule.kt#L202-L208

    @ServiceScoped
    @Provides
    fun serviceCoroutineScope(
        service: Service
    ): CoroutineScope {
        return (service as LifecycleOwner).lifecycleScope
    }

Also instead of hardcoding events in onCreate, onDestroy - you can attach them to the lifecycle

https://github.com/google/horologist/blob/10fb61ff97458dbbe004039eca2f94a320ac69da/media-sample/src/main/java/com/google/android/horologist/mediasample/di/PlaybackServiceModule.kt#L266-L273

                (service as LifecycleOwner).lifecycle.addObserver(
                    object :
                        DefaultLifecycleObserver {
                        override fun onDestroy(owner: LifecycleOwner) {
                            it.release()
                        }
                    }
                )

Both really helpful when you have something like Hilt that means you create instances inside your DI modules, instead of directly in the Service implementation.

yschimke commented 2 years ago

If you follow the lead of Activities, the typical baseclass in a compose app is now

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        ContextAware,
        LifecycleOwner,
        ViewModelStoreOwner,
        ...

So this is basically adopting the same approach here.

sampengilly commented 12 months ago

I think unfortunately there's always going to need to be a class cast in the Dependency Injection module here even if media3 provides an out of the box implementation of the LifecycleOwner, since Hilt's Service scoping only provides the platform Service class, not a LifecycleService.

It would also force the media3 libraries to expose the lifecycle components library to consumers, so I wonder if there's a way to do it in a composable way? Or through a custom listener for when the service is destroyed, similar to how a ViewModelScoped component in Hilt gets a listener binding for when the ViewModel is cleared.

I agree that this would be useful as I'm also looking at keeping the direct Service overriding code minimal and instead building/providing the dependencies to the Service as part of Dependency Injection and scoping things to the Service lifecycle from there

anonym24 commented 9 months ago

Any news?