Skip to content

Commit

Permalink
Merge pull request #180 from KieronQuinn/release/2.3
Browse files Browse the repository at this point in the history
2.3
  • Loading branch information
KieronQuinn authored May 15, 2023
2 parents a500e59 + f2abeec commit 18a913e
Show file tree
Hide file tree
Showing 23 changed files with 780 additions and 13 deletions.
19 changes: 10 additions & 9 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ plugins {

apply plugin: 'com.google.android.gms.oss-licenses-plugin'

String DEFAULT_MANIFEST = "247:https://storage.googleapis.com/music-iq-db/updatable_ytm_db/20230402-030031/manifest.json"
String DEFAULT_MANIFEST_V3 = "3048:https://storage.googleapis.com/music-iq-db/updatable_db_v3/20230402-030031/manifest.json"
String DEFAULT_MANIFEST = "248:https://storage.googleapis.com/music-iq-db/updatable_ytm_db/20230507-030029/manifest.json"
String DEFAULT_MANIFEST_V3 = "3050:https://storage.googleapis.com/music-iq-db/updatable_db_v3/20230507-030029/manifest.json"

def tagName = '2.2.2'
def version = 222
def tagName = '2.3'
def version = 230

def getKeystoreProperties() {
def properties = new Properties()
Expand Down Expand Up @@ -111,24 +111,25 @@ protobuf {

dependencies {
//AndroidX
implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.core:core-splashscreen:1.0.0'
implementation 'androidx.core:core-splashscreen:1.0.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation "androidx.work:work-runtime-ktx:2.8.1"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.lifecycle:lifecycle-service:2.6.1"
implementation "androidx.security:security-crypto:1.0.0"

//Material UI
implementation 'com.google.android.material:material:1.8.0'
implementation 'com.google.android.material:material:1.9.0'

//MonetCompat for colours on < S
implementation 'com.github.KieronQuinn:MonetCompat:0.4.1'

//Dependency Injection
implementation "io.insert-koin:koin-android:3.3.3"
implementation "io.insert-koin:koin-android:3.4.0"

//Protobuf is used in reading data from ASI
implementation "com.google.protobuf:protobuf-javalite:3.21.9"
Expand Down Expand Up @@ -179,7 +180,7 @@ dependencies {
kapt "com.google.dagger:hilt-compiler:2.41"

//OSS libraries activity
implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
implementation 'com.google.android.gms:play-services-oss-licenses:17.0.1'

//Better Link Movement Method for inline links
implementation 'me.saket:better-link-movement-method:2.2.0'
Expand Down
4 changes: 2 additions & 2 deletions app/release/output-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 222,
"versionName": "2.2.2",
"versionCode": 230,
"versionName": "2.3",
"outputFile": "app-release.apk"
}
],
Expand Down
19 changes: 17 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,17 @@

<application
android:name=".AmbientMusicMod"
android:allowBackup="true"
android:allowBackup="false"
android:fullBackupContent="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:enableOnBackInvokedCallback="true"
android:theme="@style/Theme.AmbientMusicMod.Splash"
android:usesCleartextTraffic="${usesCleartextTraffic}">
android:usesCleartextTraffic="${usesCleartextTraffic}"
tools:targetApi="tiramisu">
<activity
android:name=".ui.activities.MainActivity"
android:exported="true">
Expand Down Expand Up @@ -74,6 +77,18 @@
</intent-filter>
</receiver>

<receiver
android:name=".receivers.ExternalAccessReceiver"
android:exported="true">
<intent-filter>
<action android:name="${applicationId}.action.ENABLE" />
<action android:name="${applicationId}.action.DISABLE" />
<action android:name="${applicationId}.action.TOGGLE" />
<action android:name="${applicationId}.action.RUN_RECOGNITION" />
<action android:name="${applicationId}.action.RUN_ONLINE_RECOGNITION" />
</intent-filter>
</receiver>

<service android:name=".service.AmbientMusicModForegroundService" />

<service
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import com.kieronquinn.app.ambientmusicmod.repositories.BedtimeRepository
import com.kieronquinn.app.ambientmusicmod.repositories.BedtimeRepositoryImpl
import com.kieronquinn.app.ambientmusicmod.repositories.DeviceConfigRepository
import com.kieronquinn.app.ambientmusicmod.repositories.DeviceConfigRepositoryImpl
import com.kieronquinn.app.ambientmusicmod.repositories.EncryptedSettingsRepository
import com.kieronquinn.app.ambientmusicmod.repositories.EncryptedSettingsRepositoryImpl
import com.kieronquinn.app.ambientmusicmod.repositories.ExternalAccessRepository
import com.kieronquinn.app.ambientmusicmod.repositories.ExternalAccessRepositoryImpl
import com.kieronquinn.app.ambientmusicmod.repositories.JobsRepository
import com.kieronquinn.app.ambientmusicmod.repositories.JobsRepositoryImpl
import com.kieronquinn.app.ambientmusicmod.repositories.RecognitionRepository
Expand Down Expand Up @@ -88,6 +92,8 @@ import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.SettingsViewModel
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.SettingsViewModelImpl
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.advanced.SettingsAdvancedViewModel
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.advanced.SettingsAdvancedViewModelImpl
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.advanced.externalaccess.SettingsAdvancedExternalAccessViewModel
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.advanced.externalaccess.SettingsAdvancedExternalAccessViewModelImpl
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.advanced.gain.SettingsAdvancedGainBottomSheetViewModel
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.advanced.gain.SettingsAdvancedGainBottomSheetViewModelImpl
import com.kieronquinn.app.ambientmusicmod.ui.screens.settings.bedtime.SettingsBedtimeViewModel
Expand Down Expand Up @@ -152,6 +158,7 @@ class AmbientMusicMod: Application() {
private val repositoriesModule = module {
single<ApiRepository> { ApiRepositoryImpl(get()) }
single<SettingsRepository> { SettingsRepositoryImpl(get()) }
single<EncryptedSettingsRepository> { EncryptedSettingsRepositoryImpl(get()) }
single<DeviceConfigRepository>(createdAtStart = true) { DeviceConfigRepositoryImpl(get(), get()) }
single<RootNavigation> { RootNavigationImpl() }
single<ContainerNavigation> { ContainerNavigationImpl() }
Expand All @@ -169,6 +176,7 @@ class AmbientMusicMod: Application() {
single<BackupRestoreRepository> { BackupRestoreRepositoryImpl(get(), get(), get(), get(), get()) }
single<BatteryOptimisationRepository> { BatteryOptimisationRepositoryImpl(get()) }
single<JobsRepository>(createdAtStart = true) { JobsRepositoryImpl(get(), get(), get()) }
single<ExternalAccessRepository> { ExternalAccessRepositoryImpl(get(), get(), get()) }
single { BlurProvider.getBlurProvider(resources) }
single { createMarkwon() }
single { Gson() }
Expand Down Expand Up @@ -213,6 +221,7 @@ class AmbientMusicMod: Application() {
viewModel<ContributorsViewModel> { ContributorsViewModelImpl(get()) }
viewModel<BatteryOptimisationViewModel> { BatteryOptimisationViewModelImpl(get(), get(), get()) }
viewModel<SettingsExtraCountryPickerViewModel> { SettingsExtraCountryPickerViewModelImpl(get()) }
viewModel<SettingsAdvancedExternalAccessViewModel> { SettingsAdvancedExternalAccessViewModelImpl(get(), get()) }
}

private val tracklistModule = module {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sealed class GenericSettingsItem(val type: GenericSettingsItemType): BaseSetting
@DrawableRes
val icon: Int,
val enabled: Boolean = true,
val onLongClick: (() -> Unit)? = null,
val onClick: () -> Unit
): GenericSettingsItem(GenericSettingsItemType.SETTING)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.kieronquinn.app.ambientmusicmod.receivers

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.kieronquinn.app.ambientmusicmod.BuildConfig
import com.kieronquinn.app.ambientmusicmod.repositories.ExternalAccessRepository
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

class ExternalAccessReceiver: BroadcastReceiver(), KoinComponent {

companion object {
private const val ACTION_ENABLE = "${BuildConfig.APPLICATION_ID}.action.ENABLE"
private const val ACTION_DISABLE = "${BuildConfig.APPLICATION_ID}.action.DISABLE"
private const val ACTION_TOGGLE = "${BuildConfig.APPLICATION_ID}.action.TOGGLE"

private const val ACTION_RUN_RECOGNITION =
"${BuildConfig.APPLICATION_ID}.action.RUN_RECOGNITION"
private const val ACTION_RUN_ONLINE_RECOGNITION =
"${BuildConfig.APPLICATION_ID}.action.RUN_ONLINE_RECOGNITION"
}

private val externalAccess by inject<ExternalAccessRepository>()

override fun onReceive(context: Context, intent: Intent) {
when(intent.action) {
ACTION_ENABLE -> externalAccess.onEnable(intent)
ACTION_DISABLE -> externalAccess.onDisable(intent)
ACTION_TOGGLE -> externalAccess.onToggle(intent)
ACTION_RUN_RECOGNITION -> externalAccess.onRecognise(intent, false)
ACTION_RUN_ONLINE_RECOGNITION -> externalAccess.onRecognise(intent, true)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.kieronquinn.app.ambientmusicmod.repositories

import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys
import com.kieronquinn.app.ambientmusicmod.BuildConfig
import com.kieronquinn.app.ambientmusicmod.repositories.BaseSettingsRepository.AmbientMusicModSetting
import com.kieronquinn.app.ambientmusicmod.utils.extensions.randomSecureString
import java.security.KeyStore

interface EncryptedSettingsRepository {

val encryptionAvailable: Boolean

val externalAccessEnabled: AmbientMusicModSetting<Boolean>
val externalAccessRequireToken: AmbientMusicModSetting<Boolean>
val externalAccessToken: AmbientMusicModSetting<String>
val externalAccessToggleEnabled: AmbientMusicModSetting<Boolean>
val externalAccessRecognitionEnabled: AmbientMusicModSetting<Boolean>

}

class EncryptedSettingsRepositoryImpl(
context: Context
): BaseSettingsRepositoryImpl(), EncryptedSettingsRepository {

companion object {
const val EXTERNAL_ACCESS_TOKEN_LENGTH = 16

private const val EXTERNAL_ACCESS_ENABLED = "external_access_enabled"
private const val DEFAULT_EXTERNAL_ACCESS_ENABLED = false

private const val EXTERNAL_ACCESS_REQUIRE_TOKEN = "external_access_require_token"
private const val DEFAULT_EXTERNAL_ACCESS_REQUIRE_TOKEN = true

private const val EXTERNAL_ACCESS_TOKEN = "external_access_token"
private val DEFAULT_EXTERNAL_ACCESS_TOKEN = randomSecureString(EXTERNAL_ACCESS_TOKEN_LENGTH)

private const val EXTERNAL_ACCESS_TOGGLE_ENABLED = "external_access_toggle_enabled"
private const val DEFAULT_EXTERNAL_ACCESS_TOGGLE_ENABLED = true

private const val EXTERNAL_ACCESS_RECOGNITION_ENABLED = "external_access_recognition_enabled"
private const val DEFAULT_ACCESS_EXTERNAL_RECOGNITION_ENABLED = true

private fun tryLoadSharedPreferences(context: Context): SharedPreferences? {
//Regular load, should work 99% of the time
getSharedPreferences(context)?.let {
return it
}
//If failed, delete the key and start again
deleteMasterKeyEntry()
//If it still fails, nothing we can do
return getSharedPreferences(context)
}

private fun getSharedPreferences(context: Context): SharedPreferences? {
return try {
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
EncryptedSharedPreferences.create(
"${BuildConfig.APPLICATION_ID}_encrypted_prefs",
mainKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}catch (e: Exception) {
//Failed to load shared prefs
null
}
}

private fun deleteMasterKeyEntry() {
try {
KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
deleteEntry("_androidx_security_master_key_")
}
}catch (e: Exception){
//Failed to delete key
}
}
}

private val encryptedSharedPreferences by lazy {
tryLoadSharedPreferences(context)
}

override val sharedPreferences
get() = encryptedSharedPreferences ?: throw RuntimeException("Encrypted prefs failed to load")

override val encryptionAvailable = encryptedSharedPreferences != null

override val externalAccessEnabled =
boolean(EXTERNAL_ACCESS_ENABLED, DEFAULT_EXTERNAL_ACCESS_ENABLED)

override val externalAccessRequireToken =
boolean(EXTERNAL_ACCESS_REQUIRE_TOKEN, DEFAULT_EXTERNAL_ACCESS_REQUIRE_TOKEN)

override val externalAccessToken =
string(EXTERNAL_ACCESS_TOKEN, DEFAULT_EXTERNAL_ACCESS_TOKEN)

override val externalAccessToggleEnabled =
boolean(EXTERNAL_ACCESS_TOGGLE_ENABLED, DEFAULT_EXTERNAL_ACCESS_TOGGLE_ENABLED)

override val externalAccessRecognitionEnabled =
boolean(EXTERNAL_ACCESS_RECOGNITION_ENABLED, DEFAULT_ACCESS_EXTERNAL_RECOGNITION_ENABLED)

}
Loading

0 comments on commit 18a913e

Please sign in to comment.