Skip to content

Commit

Permalink
refactor: Migrated from Hilt to Koin
Browse files Browse the repository at this point in the history
This commit replaces Hilt with Koin for dependency injection throughout the project.

The following changes were made:

- Removed Hilt dependencies and plugins from Gradle configuration.
- Added Koin dependencies and plugins to Gradle configuration.
- Created Koin modules to define and provide dependencies.
- Updated classes to use Koin for injecting dependencies.
- Removed Hilt annotations and replaced them with Koin equivalents.
- Updated MainActivity to use Koin for injecting ConnectionHandler.
- Updated Navigation to use koinViewModel for retrieving ViewModels.
- Updated MediaplayerService to use inject for retrieving dependencies.
- Updated ViewModels to extend KoinComponent and inject dependencies.
- Updated other classes to use Koin for injecting dependencies.
- Updated MediaplayerModule to use Koin modules for providing dependencies.
- Updated SpotifyModule to use Koin modules for providing dependencies.
- Updated MediaStoreViewModel to use KoinComponent and inject dependencies.
- Updated Spotify data classes to use KoinComponent and inject dependencies.
- Updated Spotify remote service to use KoinComponent and inject dependencies.
- Updated MediaServiceHandler to use KoinComponent and inject dependencies.
- Updated MediaLibrarySessionCallback to use KoinComponent and inject dependencies.
- Updated MediaNotificationManager to use KoinComponent.
- Updated MetadataEditorVM to use KoinComponent and inject dependencies.
- Updated MetadataBsVM to use KoinComponent and inject dependencies.
  • Loading branch information
BobbyESP committed Nov 18, 2024
1 parent 81d16d0 commit 3a6f313
Show file tree
Hide file tree
Showing 32 changed files with 274 additions and 305 deletions.
13 changes: 9 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.android.kotlin)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.hilt)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.compose.compiler)
Expand Down Expand Up @@ -121,15 +120,23 @@ android {
}
}
applicationVariants.all {
val variantName = name
sourceSets {
getByName("main") {
java.srcDir(File("build/generated/ksp/$variantName/kotlin"))
}
}
outputs.all {
(this as com.android.build.gradle.internal.api.BaseVariantOutputImpl).outputFileName =
"Metadator-${defaultConfig.versionName}-${name}.apk"
}
}

}

ksp {
arg(RoomSchemaArgProvider(File(projectDir, "schemas")))
arg("KOIN_CONFIG_CHECK", "true")
}

dependencies {
Expand Down Expand Up @@ -160,9 +167,7 @@ dependencies {
implementation(project(":app:mediaplayer"))

//---------------Dependency Injection---------------//
implementation(libs.bundles.hilt)
ksp(libs.hilt.ext.compiler)
ksp(libs.hilt.compiler)
implementation(libs.bundles.koin)

//-------------------Database-------------------//
implementation(libs.room.runtime)
Expand Down
17 changes: 13 additions & 4 deletions app/mediaplayer/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.android.kotlin)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.hilt)
alias(libs.plugins.compose.compiler)
}

Expand All @@ -26,6 +25,14 @@ android {
)
}
}
libraryVariants.all {
val variantName = name
sourceSets {
getByName("main") {
java.srcDir(File("build/generated/ksp/$variantName/kotlin"))
}
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
Expand All @@ -35,15 +42,17 @@ android {
}
}

ksp {
arg("KOIN_CONFIG_CHECK", "true")
}

dependencies {
implementation(libs.core.ktx)
implementation(libs.core.appcompat)
implementation(libs.androidx.legacy.support.v4) // Needed MediaSessionCompat.Token

//DI (Dependency Injection - Hilt)
implementation(libs.bundles.hilt)
ksp(libs.hilt.ext.compiler)
ksp(libs.hilt.compiler)
implementation(libs.bundles.koin)

//Media3
implementation(libs.bundles.media3)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package com.bobbyesp.mediaplayer.di

import android.app.PendingIntent
import android.content.Context
import android.os.Build
import androidx.annotation.OptIn
import androidx.annotation.RequiresApi
import androidx.media3.common.AudioAttributes
import androidx.media3.common.C
import androidx.media3.common.util.UnstableApi
Expand All @@ -17,87 +13,69 @@ import com.bobbyesp.mediaplayer.service.MediaServiceHandler
import com.bobbyesp.mediaplayer.service.notifications.MediaNotificationManager
import com.bobbyesp.mediaplayer.service.notifications.customLayout.MediaSessionLayoutHandler
import com.bobbyesp.mediaplayer.service.notifications.customLayout.MediaSessionLayoutHandlerImpl
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.koin.android.ext.koin.androidContext
import org.koin.core.module.Module
import org.koin.dsl.module

@OptIn(UnstableApi::class)
@Module
@InstallIn(SingletonComponent::class)
object MediaPlayerModule {
@Provides
@Singleton
fun provideAudioAttributes(): AudioAttributes =
AudioAttributes.Builder().setContentType(C.AUDIO_CONTENT_TYPE_MOVIE).setUsage(C.USAGE_MEDIA)
val mediaplayerInternalsModule: Module = module {
single {
AudioAttributes.Builder()
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
.setUsage(C.USAGE_MEDIA)
.build()
}

@Provides
@Singleton
@UnstableApi
fun providePlayer(
@ApplicationContext context: Context, audioAttributes: AudioAttributes
): ExoPlayer = ExoPlayer.Builder(context)
.setSeekBackIncrementMs(5000)
.setSeekForwardIncrementMs(5000)
.setAudioAttributes(audioAttributes, true)
.setHandleAudioBecomingNoisy(true)
.setTrackSelector(DefaultTrackSelector(context))
.setAudioAttributes(
AudioAttributes.Builder()
.setUsage(C.USAGE_MEDIA)
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
.build(), true
)
.build()

@RequiresApi(Build.VERSION_CODES.O)
@Provides
@Singleton
fun provideNotificationManager(
@ApplicationContext context: Context, player: ExoPlayer
): MediaNotificationManager = MediaNotificationManager(
context = context, player = player
)

@Provides
@Singleton
fun provideMediaLibrarySession(
@ApplicationContext context: Context,
player: ExoPlayer,
mediaLibrarySessionCallback: MediaLibrarySessionCallback,
): MediaLibrarySession =
MediaLibrarySession.Builder(context, player, mediaLibrarySessionCallback)
.setSessionActivity(
PendingIntent.getActivity(
context,
0,
context.packageManager.getLaunchIntentForPackage(context.packageName),
PendingIntent.FLAG_IMMUTABLE
)
single {
ExoPlayer.Builder(androidContext())
.setSeekBackIncrementMs(5000)
.setSeekForwardIncrementMs(5000)
.setAudioAttributes(get(), true)
.setHandleAudioBecomingNoisy(true)
.setTrackSelector(DefaultTrackSelector(androidContext()))
.setAudioAttributes(
get<AudioAttributes>(),
true
)
.build()
}

@Provides
@Singleton
fun provideServiceHandler(
player: ExoPlayer
): MediaServiceHandler =
single {
MediaServiceHandler(
player = player
player = get<ExoPlayer>()
)
}

@Provides
@Singleton
fun provideConnectionHandler(): ConnectionHandler = ConnectionHandler()
single { ConnectionHandler() }

@Provides
@Singleton
fun provideMediaSessionLayoutHandler(
@ApplicationContext context: Context,
mediaLibrarySession: MediaLibrarySession
): MediaSessionLayoutHandler =
MediaSessionLayoutHandlerImpl(context, mediaLibrarySession)
}
single {
MediaLibrarySession.Builder(
androidContext(),
get<ExoPlayer>(),
MediaLibrarySessionCallback(androidContext())
).setSessionActivity(
PendingIntent.getActivity(
androidContext(),
0,
androidContext().packageManager.getLaunchIntentForPackage(androidContext().packageName),
PendingIntent.FLAG_IMMUTABLE
)
).build()
}

single<MediaSessionLayoutHandler> {
MediaSessionLayoutHandlerImpl(
androidContext(),
get<MediaLibrarySession>()
)
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
single {
MediaNotificationManager(
context = androidContext(),
player = get()
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ import com.bobbyesp.mediaplayer.service.MediaSessionConstants.CommandToggleRepea
import com.bobbyesp.mediaplayer.service.MediaSessionConstants.CommandToggleShuffle
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.koin.core.component.KoinComponent

class MediaLibrarySessionCallback @Inject constructor(
@ApplicationContext val context: Context,
) : MediaLibrarySession.Callback {
class MediaLibrarySessionCallback(
val context: Context,
) : KoinComponent, MediaLibrarySession.Callback {

private val availableCommands = listOf(
CommandToggleShuffle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
import org.koin.core.component.KoinComponent

/**
* This class is responsible for handling media playback events and managing the state of the media player.
* It provides methods to control the media player such as play, pause, stop, and seek.
* It also provides methods to manage the media queue such as set, add, and remove media items.
*/
@UnstableApi
class MediaServiceHandler @Inject constructor(
class MediaServiceHandler(
private val player: ExoPlayer
) : Player.Listener, PlaybackStatsListener.Callback {
) : KoinComponent, Player.Listener, PlaybackStatsListener.Callback {

private val _mediaState = MutableStateFlow<MediaState>(MediaState.Idle)
val mediaState = _mediaState.asStateFlow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,16 @@ import androidx.media3.session.MediaSession
import com.bobbyesp.mediaplayer.service.notifications.MediaNotificationManager
import com.bobbyesp.mediaplayer.service.notifications.customLayout.MediaSessionLayoutHandler
import com.google.common.util.concurrent.MoreExecutors
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import org.koin.android.ext.android.inject

@UnstableApi
@AndroidEntryPoint
class MediaplayerService : MediaLibraryService(), MediaController.Listener {
@Inject
lateinit var mediaSession: MediaLibrarySession

@Inject
lateinit var mediaServiceHandler: MediaServiceHandler

@Inject
lateinit var notificationManager: MediaNotificationManager

@Inject
lateinit var mediaSessionLayoutHandler: MediaSessionLayoutHandler

@Inject
lateinit var connectionHandler: ConnectionHandler
val mediaSession: MediaLibrarySession by inject()
val mediaServiceHandler: MediaServiceHandler by inject()
val notificationManager: MediaNotificationManager by inject()
val mediaSessionLayoutHandler: MediaSessionLayoutHandler by inject()
val connectionHandler: ConnectionHandler by inject()

/**
* This method is called by the system every time a client explicitly starts the service by calling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
import androidx.media3.ui.PlayerNotificationManager
import com.bobbyesp.mediaplayer.R
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.koin.core.component.KoinComponent

@UnstableApi
class MediaNotificationManager @OptIn(UnstableApi::class)
@Inject constructor(
@ApplicationContext private val context: Context,
class MediaNotificationManager @OptIn(UnstableApi::class) constructor(
private val context: Context,
private val player: ExoPlayer
) {
) : KoinComponent {
private val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import com.bobbyesp.mediaplayer.R
import com.bobbyesp.mediaplayer.service.MediaSessionConstants.CommandToggleRepeatMode
import com.bobbyesp.mediaplayer.service.MediaSessionConstants.CommandToggleShuffle
import com.google.common.collect.ImmutableList
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.koin.core.component.KoinComponent

class MediaSessionLayoutHandlerImpl @Inject constructor(
@ApplicationContext private val context: Context,
class MediaSessionLayoutHandlerImpl(
private val context: Context,
private val mediaSession: MediaLibraryService.MediaLibrarySession,
) : MediaSessionLayoutHandler {
) : KoinComponent, MediaSessionLayoutHandler {

override fun updateNotificationLayout() {
val commandButtons = ImmutableList.of<CommandButton>(
Expand Down
18 changes: 16 additions & 2 deletions app/src/main/java/com/bobbyesp/metadator/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,30 @@ import android.os.Build
import androidx.core.content.getSystemService
import com.bobbyesp.crashhandler.CrashHandler.setupCrashHandler
import com.bobbyesp.crashhandler.ReportInfo
import com.bobbyesp.metadator.di.appMainViewModels
import com.bobbyesp.metadator.di.mediaplayerViewModels
import com.bobbyesp.metadator.di.utilitiesViewModels
import com.bobbyesp.metadator.features.spotify.di.spotifyMainModule
import com.bobbyesp.metadator.features.spotify.di.spotifyServicesModule
import com.tencent.mmkv.MMKV
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import mediaplayerInternalsModule
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.GlobalContext.startKoin
import kotlin.properties.Delegates

@HiltAndroidApp
class App : Application() {
override fun onCreate() {
MMKV.initialize(this)
startKoin {
androidLogger()
androidContext(this@App)
modules(mediaplayerInternalsModule)
modules(appMainViewModels, utilitiesViewModels, mediaplayerViewModels)
modules(spotifyMainModule, spotifyServicesModule)
}
packageInfo = packageManager.run {
if (Build.VERSION.SDK_INT >= 33) getPackageInfo(
packageName, PackageManager.PackageInfoFlags.of(0)
Expand Down
Loading

0 comments on commit 3a6f313

Please sign in to comment.