mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-18 18:17:43 +03:00
Merge branch '471' into 'master'
Release canditate 4.7.1 See merge request ultrasonic/ultrasonic!1107
This commit is contained in:
commit
7b8d1dec9b
12
fastlane/metadata/android/en-US/changelogs/129.txt
Normal file
12
fastlane/metadata/android/en-US/changelogs/129.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
### Fixes
|
||||||
|
- Fix a bug in 4.7.0 that repeat mode was activated by default.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- Added custom buttons for shuffling the current queue and setting repeat mode (Android Auto)
|
||||||
|
- Properly handling nested directory structures (Android Auto)
|
||||||
|
- Add a toast when adding tracks to the playlist
|
||||||
|
- Allow pinning when offline
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- Update koin
|
||||||
|
- Update media3 to v1.1.0
|
@ -4,6 +4,7 @@ gradle = "8.1.1"
|
|||||||
|
|
||||||
navigation = "2.6.0"
|
navigation = "2.6.0"
|
||||||
gradlePlugin = "8.1.0"
|
gradlePlugin = "8.1.0"
|
||||||
|
androidxcar = "1.2.0"
|
||||||
androidxcore = "1.10.1"
|
androidxcore = "1.10.1"
|
||||||
ktlint = "0.43.2"
|
ktlint = "0.43.2"
|
||||||
ktlintGradle = "11.5.0"
|
ktlintGradle = "11.5.0"
|
||||||
@ -49,6 +50,7 @@ kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin"
|
|||||||
ktlintGradle = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlintGradle" }
|
ktlintGradle = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlintGradle" }
|
||||||
detekt = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detekt" }
|
detekt = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detekt" }
|
||||||
|
|
||||||
|
car = { module = "androidx.car.app:app", version.ref = "androidxcar" }
|
||||||
core = { module = "androidx.core:core-ktx", version.ref = "androidxcore" }
|
core = { module = "androidx.core:core-ktx", version.ref = "androidxcore" }
|
||||||
design = { module = "com.google.android.material:material", version.ref = "materialDesign" }
|
design = { module = "com.google.android.material:material", version.ref = "materialDesign" }
|
||||||
annotations = { module = "androidx.annotation:annotation", version.ref = "androidSupport" }
|
annotations = { module = "androidx.annotation:annotation", version.ref = "androidSupport" }
|
||||||
@ -103,4 +105,4 @@ apacheCodecs = { module = "commons-codec:commons-codec", version.ref
|
|||||||
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
|
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||||
|
@ -12,8 +12,8 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.moire.ultrasonic"
|
applicationId "org.moire.ultrasonic"
|
||||||
versionCode 128
|
versionCode 129
|
||||||
versionName "4.7.0"
|
versionName "4.7.1"
|
||||||
|
|
||||||
minSdkVersion versions.minSdk
|
minSdkVersion versions.minSdk
|
||||||
targetSdkVersion versions.targetSdk
|
targetSdkVersion versions.targetSdk
|
||||||
@ -81,6 +81,7 @@ android {
|
|||||||
disable 'ObsoleteLintCustomCheck'
|
disable 'ObsoleteLintCustomCheck'
|
||||||
// We manage dependencies on Gitlab with RenovateBot
|
// We manage dependencies on Gitlab with RenovateBot
|
||||||
disable 'GradleDependency'
|
disable 'GradleDependency'
|
||||||
|
disable 'AndroidGradlePluginVersion'
|
||||||
textReport true
|
textReport true
|
||||||
checkDependencies true
|
checkDependencies true
|
||||||
}
|
}
|
||||||
@ -100,6 +101,7 @@ dependencies {
|
|||||||
exclude group: "com.android.support"
|
exclude group: "com.android.support"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implementation libs.car
|
||||||
implementation libs.core
|
implementation libs.core
|
||||||
implementation libs.design
|
implementation libs.design
|
||||||
implementation libs.multidex
|
implementation libs.multidex
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
|
<uses-sdk tools:overrideLibrary="androidx.car.app" />
|
||||||
|
|
||||||
<supports-screens
|
<supports-screens
|
||||||
android:anyDensity="true"
|
android:anyDensity="true"
|
||||||
android:largeScreens="true"
|
android:largeScreens="true"
|
||||||
|
@ -7,7 +7,10 @@
|
|||||||
|
|
||||||
package org.moire.ultrasonic.playback
|
package org.moire.ultrasonic.playback
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.car.app.connection.CarConnection
|
||||||
import androidx.media3.common.HeartRating
|
import androidx.media3.common.HeartRating
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_ALBUMS
|
import androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_ALBUMS
|
||||||
@ -97,6 +100,7 @@ const val PLAY_COMMAND = "play "
|
|||||||
@Suppress("TooManyFunctions", "LargeClass", "UnusedPrivateMember")
|
@Suppress("TooManyFunctions", "LargeClass", "UnusedPrivateMember")
|
||||||
class AutoMediaBrowserCallback : MediaLibraryService.MediaLibrarySession.Callback, KoinComponent {
|
class AutoMediaBrowserCallback : MediaLibraryService.MediaLibrarySession.Callback, KoinComponent {
|
||||||
|
|
||||||
|
private val applicationContext: Context by inject()
|
||||||
private val activeServerProvider: ActiveServerProvider by inject()
|
private val activeServerProvider: ActiveServerProvider by inject()
|
||||||
|
|
||||||
private val serviceJob = SupervisorJob()
|
private val serviceJob = SupervisorJob()
|
||||||
@ -115,6 +119,7 @@ class AutoMediaBrowserCallback : MediaLibraryService.MediaLibrarySession.Callbac
|
|||||||
private val placeholderButton = getPlaceholderButton()
|
private val placeholderButton = getPlaceholderButton()
|
||||||
|
|
||||||
private var heartIsCurrentlyOn = false
|
private var heartIsCurrentlyOn = false
|
||||||
|
private var customRepeatModeSet = false
|
||||||
|
|
||||||
// This button is used for an unstarred track, and its action will star the track
|
// This button is used for an unstarred track, and its action will star the track
|
||||||
private val heartButtonToggleOn =
|
private val heartButtonToggleOn =
|
||||||
@ -230,7 +235,7 @@ class AutoMediaBrowserCallback : MediaLibraryService.MediaLibrarySession.Callbac
|
|||||||
commandButton.sessionCommand?.let { availableSessionCommands.add(it) }
|
commandButton.sessionCommand?.let { availableSessionCommands.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
session.player.repeatMode = Player.REPEAT_MODE_ALL
|
configureRepeatMode(session.player)
|
||||||
|
|
||||||
return MediaSession.ConnectionResult.accept(
|
return MediaSession.ConnectionResult.accept(
|
||||||
availableSessionCommands.build(),
|
availableSessionCommands.build(),
|
||||||
@ -238,6 +243,42 @@ class AutoMediaBrowserCallback : MediaLibraryService.MediaLibrarySession.Callbac
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun configureRepeatMode(player: Player) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
Timber.d("Car app library available, observing CarConnection")
|
||||||
|
|
||||||
|
val originalRepeatMode = player.repeatMode
|
||||||
|
|
||||||
|
var lastCarConnectionType = -1
|
||||||
|
|
||||||
|
CarConnection(applicationContext).type.observeForever {
|
||||||
|
if (lastCarConnectionType == it)
|
||||||
|
return@observeForever
|
||||||
|
|
||||||
|
lastCarConnectionType = it
|
||||||
|
|
||||||
|
Timber.d("CarConnection type changed to %s", it)
|
||||||
|
|
||||||
|
when (it) {
|
||||||
|
CarConnection.CONNECTION_TYPE_PROJECTION ->
|
||||||
|
if (!customRepeatModeSet) {
|
||||||
|
Timber.d("[CarConnection] Setting repeat mode to ALL")
|
||||||
|
player.repeatMode = Player.REPEAT_MODE_ALL
|
||||||
|
customRepeatModeSet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
CarConnection.CONNECTION_TYPE_NOT_CONNECTED ->
|
||||||
|
if (customRepeatModeSet) {
|
||||||
|
Timber.d("[CarConnection] Resetting repeat mode")
|
||||||
|
player.repeatMode = originalRepeatMode
|
||||||
|
customRepeatModeSet = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
Timber.d("Car app library not available")
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPostConnect(session: MediaSession, controller: MediaSession.ControllerInfo) {
|
override fun onPostConnect(session: MediaSession, controller: MediaSession.ControllerInfo) {
|
||||||
if (controller.controllerVersion != 0) {
|
if (controller.controllerVersion != 0) {
|
||||||
// Let Media3 controller (for instance the MediaNotificationProvider)
|
// Let Media3 controller (for instance the MediaNotificationProvider)
|
||||||
@ -369,6 +410,7 @@ class AutoMediaBrowserCallback : MediaLibraryService.MediaLibrarySession.Callbac
|
|||||||
|
|
||||||
PlaybackService.CUSTOM_COMMAND_REPEAT_MODE -> {
|
PlaybackService.CUSTOM_COMMAND_REPEAT_MODE -> {
|
||||||
customCommandFuture = Futures.immediateFuture(SessionResult(RESULT_SUCCESS))
|
customCommandFuture = Futures.immediateFuture(SessionResult(RESULT_SUCCESS))
|
||||||
|
customRepeatModeSet = true
|
||||||
|
|
||||||
session.player.setNextRepeatMode()
|
session.player.setNextRepeatMode()
|
||||||
session.updateCustomCommands()
|
session.updateCustomCommands()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user