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

Feature/14 play on tv #77

Merged
merged 8 commits into from
Mar 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions android/DartsScorecard/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.firebase.crashlytics'
apply from: '../scripts/android_common.gradle'
apply from: '../scripts/versioning.gradle'
Expand All @@ -20,14 +19,16 @@ android {
applicationIdSuffix ".dev"
}
release {
shrinkResources true
shrinkResources false // Resource shrinker cannot be used for multi-apk applications
}
}

sourceSets.main {
jniLibs.srcDir 'libs'
jni.srcDirs = [] //disable automatic ndk-build call
}

dynamicFeatures = [':sounds']
}

dependencies {
Expand All @@ -51,19 +52,23 @@ dependencies {
implementation "com.google.firebase:firebase-config:$fbConfig"
implementation "com.google.firebase:firebase-database:$fbDatabase"
implementation "com.google.firebase:firebase-ads:$fbAds"
implementation "com.google.firebase:firebase-crashlytics:$fbCrash"
implementation "com.google.android.play:core:$playCore"
implementation "com.google.android.play:core-ktx:$playCoreKtx"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"

implementation "androidx.core:core-ktx:$xCore"
implementation "androidx.room:room-runtime:$room"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle"
implementation "androidx.constraintlayout:constraintlayout:$xConstraint"
implementation "androidx.preference:preference-ktx:$xPreferences"

implementation "com.github.bumptech.glide:glide:$glide"
implementation "com.github.yalantis:jellytoolbar:$jelly"
implementation "de.hdodenhof:circleimageview:$circleImageView"
implementation "com.airbnb.android:lottie:$lottieVersion"
implementation "com.google.code.gson:gson:$gson"

implementation "com.google.firebase:firebase-crashlytics:$fbCrash"

// Leaks
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanary"

Expand Down
1 change: 0 additions & 1 deletion android/DartsScorecard/app/release/output.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nl.entreco.dartsscorecard

import android.app.Application
import android.os.StrictMode
import com.google.android.play.core.splitcompat.SplitCompatApplication
import nl.entreco.dartsscorecard.di.application.AppComponent
import nl.entreco.dartsscorecard.di.application.AppModule
import nl.entreco.dartsscorecard.di.application.DaggerAppComponent
Expand All @@ -10,7 +11,7 @@ import nl.entreco.dartsscorecard.di.application.DaggerAppComponent
/**
* Created by Entreco on 14/11/2017.
*/
class App : Application() {
class App : SplitCompatApplication() {

val appComponent: AppComponent by lazy {
DaggerAppComponent.builder().appModule(AppModule(this)).build()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package nl.entreco.dartsscorecard.base

import android.app.Activity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import android.os.Bundle
import android.view.MenuItem
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.MenuItem
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import nl.entreco.dartsscorecard.App
import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.di.viewmodel.ViewModelComponent
Expand All @@ -19,7 +19,7 @@ import nl.entreco.dartsscorecard.faq.WtfActivity
*/
abstract class ViewModelActivity : AppCompatActivity() {

private val styler by lazy { Styler( this) }
private val styler by lazy { Styler(this) }

val Activity.app: App
get() = application as App
Expand All @@ -28,7 +28,8 @@ abstract class ViewModelActivity : AppCompatActivity() {
@Suppress("UNCHECKED_CAST")
inline fun <reified VM : ViewModel> viewModelProvider(
mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
crossinline provider: () -> VM) = lazy(mode) {
crossinline provider: () -> VM,
) = lazy(mode) {
ViewModelProvider(this, object : ViewModelProvider.Factory {
override fun <T1 : ViewModel> create(aClass: Class<T1>) =
provider() as T1
Expand All @@ -37,7 +38,8 @@ abstract class ViewModelActivity : AppCompatActivity() {

inline fun <reified VM> componentProvider(
mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
crossinline provider: (ViewModelComponent) -> VM) = lazy(mode) {
crossinline provider: (ViewModelComponent) -> VM,
) = lazy(mode) {
val component = app.appComponent.plus(ViewModelModule(this))
provider(component)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package nl.entreco.dartsscorecard.beta
import android.view.View
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.bottomsheet.BottomSheetBehavior
import kotlinx.android.synthetic.main.include_beta_detail.view.voteFab
import nl.entreco.dartsscorecard.databinding.ActivityBetaBinding
import kotlin.math.abs
import kotlin.math.max
Expand All @@ -15,7 +14,7 @@ class BetaAnimator(binding: ActivityBetaBinding) {

private val behaviour: BottomSheetBehavior<View> = BottomSheetBehavior.from(binding.sheet)
private val appBar = binding.includeToolbar.betaAppbar
private val animator = BetaAnimatorHandler(appBar, binding.includeToolbar.toolbar, binding.sheet, binding.sheet.voteFab)
private val animator = BetaAnimatorHandler(appBar, binding.includeToolbar.toolbar, binding.sheet, binding.includeBetaDetail.voteFab)
internal var toggler: Toggler? = null
internal var swapper: Swapper? = null

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package nl.entreco.dartsscorecard.di.play

import dagger.Subcomponent
import nl.entreco.dartsscorecard.dynamic.DynamicInstaller
import nl.entreco.dartsscorecard.dynamic.Installer
import nl.entreco.dartsscorecard.play.Play01Navigator
import nl.entreco.dartsscorecard.play.Play01ViewModel
import nl.entreco.dartsscorecard.play.input.InputViewModel
Expand All @@ -22,6 +24,7 @@ interface Play01Component {
fun inputViewModel(): InputViewModel
fun statViewModel(): LiveStatViewModel
fun finishUsecase(): GetFinishUsecase
fun installer() : Installer
fun billing() : BillingRepo
fun ads(): AdViewModel
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,44 @@ package nl.entreco.dartsscorecard.di.play

import android.content.ComponentName
import android.content.Context
import android.media.MediaPlayer
import android.media.SoundPool
import com.google.android.play.core.splitinstall.SplitInstallManager
import com.google.android.play.core.splitinstall.SplitInstallManagerFactory
import com.google.android.play.core.splitinstall.SplitInstallRequest
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import dagger.Module
import dagger.Provides
import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.archive.ArchiveJobService
import nl.entreco.dartsscorecard.archive.ArchiveServiceLauncher
import nl.entreco.dartsscorecard.di.profile.ProfileScope
import nl.entreco.dartsscorecard.dynamic.DynamicInstaller
import nl.entreco.dartsscorecard.dynamic.Installer
import nl.entreco.dartsscorecard.dynamic.NoInstaller
import nl.entreco.dartsscorecard.dynamic.NoMusicRepository
import nl.entreco.dartsscorecard.dynamic.NoSoundRepository
import nl.entreco.dartsscorecard.dynamic.SoundModuleProvider
import nl.entreco.dartsscorecard.play.Play01Activity
import nl.entreco.data.billing.PlayBillingRepository
import nl.entreco.data.description.RemoteMatchDescriptionRepository
import nl.entreco.data.sound.LocalMusicRepository
import nl.entreco.data.sound.LocalSoundRepository
import nl.entreco.data.sound.SoundMapper
import nl.entreco.domain.beta.donations.MakePurchaseResponse
import nl.entreco.domain.mastercaller.MusicRepository
import nl.entreco.domain.mastercaller.SoundRepository
import nl.entreco.domain.repository.AudioPrefRepository
import nl.entreco.domain.repository.BillingRepo
import nl.entreco.domain.repository.MatchDescriptionRepository
import nl.entreco.domain.repository.MusicRepository
import nl.entreco.domain.repository.SoundRepository
import nl.entreco.liblog.Logger
import nl.entreco.shared.scopes.ActivityScope
import nl.entreco.shared.scopes.ApplicationScope
import java.lang.ref.WeakReference

private const val DYNAMIC_PROVIDER = "nl.entreco.dartsscorecard.sounds.DynamicSoundProvider"
private const val SOUNDS = "sounds"

/**
* Created by Entreco on 14/11/2017.
*/
@Module
class Play01Module(
private val activity: Play01Activity,
private val listener: (MakePurchaseResponse) -> Unit
private val listener: (MakePurchaseResponse) -> Unit,
) {

@Provides
Expand All @@ -51,23 +56,51 @@ class Play01Module(

@Provides
@Play01Scope
fun provideSoundMapper(): SoundMapper {
return SoundMapper()
fun provideSplitInstallManager(@ActivityScope context: Context): SplitInstallManager {
return SplitInstallManagerFactory.create(context)
}

@Provides
@Play01Scope
fun provideSplitInstallRequest() = SplitInstallRequest.newBuilder()
.addModule(SOUNDS)
.build()

@Provides
@Play01Scope
fun provideSoundRepository(
@ActivityScope context: Context,
splitInstallManager: SplitInstallManager,
prefs: AudioPrefRepository,
): SoundRepository {
return if (splitInstallManager.installedModules.contains(SOUNDS)) {
val provider = Class.forName(DYNAMIC_PROVIDER).kotlin.objectInstance as? SoundModuleProvider
val updatedContext = context.createPackageContext(context.packageName, 0)
provider?.provideSoundRepository(updatedContext.applicationContext, prefs) ?: NoSoundRepository()
} else NoSoundRepository()
}

@Provides
@Play01Scope
fun provideSoundRepository(@ActivityScope context: Context, @Play01Scope mapper: SoundMapper, @Play01Scope prefs: AudioPrefRepository): SoundRepository {
val soundPool = SoundPool.Builder().setMaxStreams(2).build()
return LocalSoundRepository(context, soundPool, prefs, mapper)
fun provideMusicRepository(
@ActivityScope context: Context,
splitInstallManager: SplitInstallManager,
): MusicRepository {
return if (splitInstallManager.installedModules.contains(SOUNDS)) {
val provider = Class.forName(DYNAMIC_PROVIDER).kotlin.objectInstance as? SoundModuleProvider
val updatedContext = context.createPackageContext(context.packageName, 0)
provider?.provideMusicRepository(updatedContext.applicationContext) ?: NoMusicRepository()
} else NoMusicRepository()
}

@Provides
@Play01Scope
fun provideMusicRepository(@ActivityScope context: Context): MusicRepository {
val mediaPlayer = MediaPlayer.create(context, R.raw.pdc_tune)
mediaPlayer.isLooping = true
return LocalMusicRepository(mediaPlayer)
fun provideDynamicInstaller(
splitInstallRequest: SplitInstallRequest,
splitInstallManager: SplitInstallManager,
): Installer {
return if (splitInstallManager.installedModules.contains(SOUNDS)) NoInstaller()
else DynamicInstaller(splitInstallRequest, splitInstallManager)
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package nl.entreco.dartsscorecard.dynamic

import com.google.android.play.core.ktx.status
import com.google.android.play.core.splitinstall.SplitInstallManager
import com.google.android.play.core.splitinstall.SplitInstallRequest
import com.google.android.play.core.splitinstall.SplitInstallSessionState
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus

class DynamicInstaller(
private val request: SplitInstallRequest,
private val manager: SplitInstallManager,
) : Installer {

private var mySessionId = 0

override fun install(callback: SoundInstalledCallback) {
val installListener = InstallListener(callback)
manager.registerListener(installListener)
manager.startInstall(request)
.addOnCompleteListener { }
.addOnSuccessListener { mySessionId = it }
.addOnFailureListener { callback.onError() }
}
}

class InstallListener(
private val callback: SoundInstalledCallback,
) : SplitInstallStateUpdatedListener {

override fun onStateUpdate(state: SplitInstallSessionState) {
when (state.status()) {
SplitInstallSessionStatus.DOWNLOADING -> {
val totalBytes = state.totalBytesToDownload()
val bytes = state.bytesDownloaded()
callback.onProgress(bytes, totalBytes)
}
SplitInstallSessionStatus.INSTALLED -> {

// After a module is installed, you can start accessing its content or
// fire an intent to start an activity in the installed module.
// For other use cases, see access code and resources from installed modules.

// If the request is an on demand module for an Android Instant App
// running on Android 8.0 (API level 26) or higher, you need to
// update the app context using the SplitInstallHelper API.
callback.onComplete()
}
SplitInstallSessionStatus.CANCELED,
SplitInstallSessionStatus.CANCELING,
SplitInstallSessionStatus.DOWNLOADED,
SplitInstallSessionStatus.FAILED,
SplitInstallSessionStatus.INSTALLING,
SplitInstallSessionStatus.PENDING,
SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION,
SplitInstallSessionStatus.UNKNOWN -> {
callback.onDebug(state.status())
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package nl.entreco.dartsscorecard.dynamic

interface Installer {
fun install(callback: SoundInstalledCallback)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package nl.entreco.dartsscorecard.dynamic

class NoInstaller : Installer {
override fun install(callback: SoundInstalledCallback) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package nl.entreco.dartsscorecard.dynamic

import nl.entreco.domain.mastercaller.MusicRepository

class NoMusicRepository: MusicRepository {

override fun play() {}

override fun pause() {}

override fun resume() {}

override fun stop() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nl.entreco.dartsscorecard.dynamic

import nl.entreco.domain.mastercaller.Sound
import nl.entreco.domain.mastercaller.SoundRepository

class NoSoundRepository : SoundRepository {

override fun play(sound: Sound) {}

override fun release() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package nl.entreco.dartsscorecard.dynamic

interface SoundInstalledCallback {
fun onComplete()
fun onProgress(bytes: Long, totalBytes: Long)
fun onError()
fun onDebug(status: Int)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nl.entreco.dartsscorecard.dynamic

import android.content.Context
import nl.entreco.dartsscorecard.di.play.Play01Scope
import nl.entreco.domain.mastercaller.MusicRepository
import nl.entreco.domain.mastercaller.SoundRepository
import nl.entreco.domain.repository.AudioPrefRepository

interface SoundModuleProvider {
fun provideSoundRepository(context: Context, @Play01Scope prefs: AudioPrefRepository): SoundRepository
fun provideMusicRepository(context: Context): MusicRepository
}
Loading