Browse Source

Remove the Android Auto car service and settings

merge-requests/2314/head
Nicolas Pomepuy 11 months ago
parent
commit
b78c26ce68
  1. 1
      application/resources/src/main/java/org/videolan/resources/Constants.kt
  2. 12
      application/vlc-android/AndroidManifest.xml
  3. 11
      application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
  4. 150
      application/vlc-android/src/org/videolan/vlc/car/CarScreens.kt
  5. 81
      application/vlc-android/src/org/videolan/vlc/car/VLCCarService.kt

1
application/resources/src/main/java/org/videolan/resources/Constants.kt

@ -70,7 +70,6 @@ val ACTION_REMOTE_GENERIC = "remote.".buildPkgString()
@JvmField val EXTRA_CUSTOM_ACTION_ID = "EXTRA_CUSTOM_ACTION_ID".buildPkgString()
@JvmField val EXTRA_SEEK_DELAY = "EXTRA_CUSTOM_ACTION_ID".buildPkgString()
@JvmField val EXTRA_RELATIVE_MEDIA_ID = "EXTRA_RELATIVE_MEDIA_ID".buildPkgString()
@JvmField val CAR_SETTINGS = "car.SETTINGS".buildPkgString()
const val PLAYLIST_TYPE_AUDIO = 0
const val PLAYLIST_TYPE_VIDEO = 1
const val PLAYLIST_TYPE_ALL = 2

12
application/vlc-android/AndroidManifest.xml

@ -1067,18 +1067,6 @@
</intent-filter>
</service>
<service
android:name=".car.VLCCarService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.SETTINGS"/>
</intent-filter>
<intent-filter>
<action android:name="${applicationId}.car.SETTINGS" />
</intent-filter>
</service>
<service
android:name=".MediaParsingService"
android:foregroundServiceType="dataSync" />

11
application/vlc-android/src/org/videolan/vlc/PlaybackService.kt

@ -60,7 +60,6 @@ import androidx.annotation.MainThread
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.car.app.connection.CarConnection
import androidx.car.app.notification.CarPendingIntent
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.ServiceCompat
import androidx.core.content.edit
@ -110,10 +109,8 @@ import org.videolan.resources.ACTION_REMOTE_SEEK_BACKWARD
import org.videolan.resources.ACTION_REMOTE_SEEK_FORWARD
import org.videolan.resources.ACTION_REMOTE_STOP
import org.videolan.resources.ACTION_REMOTE_SWITCH_VIDEO
import org.videolan.resources.ANDROID_AUTO_APP_PKG
import org.videolan.resources.AndroidDevices
import org.videolan.resources.AppContextProvider
import org.videolan.resources.CAR_SETTINGS
import org.videolan.resources.CUSTOM_ACTION
import org.videolan.resources.CUSTOM_ACTION_BOOKMARK
import org.videolan.resources.CUSTOM_ACTION_FAST_FORWARD
@ -163,7 +160,6 @@ import org.videolan.tools.getContextWithLocale
import org.videolan.tools.getResourceUri
import org.videolan.tools.markBidi
import org.videolan.tools.readableSize
import org.videolan.vlc.car.VLCCarService
import org.videolan.vlc.gui.AudioPlayerContainerActivity
import org.videolan.vlc.gui.dialogs.VideoTracksDialog
import org.videolan.vlc.gui.dialogs.adapters.VlcTrack
@ -1933,13 +1929,6 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
putBoolean(BrowserRoot.EXTRA_SUGGESTED, true)
putBoolean(MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true)
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O && clientPackageName == ANDROID_AUTO_APP_PKG) {
val intent = Intent(CAR_SETTINGS).apply {
component = ComponentName(ctx, VLCCarService::class.java)
}
val pendingIntent = CarPendingIntent.getCarApp(ctx, 0, intent, PendingIntent.FLAG_MUTABLE)
extras.putParcelable(MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_APPLICATION_PREFERENCES_USING_CAR_APP_LIBRARY_INTENT, pendingIntent)
}
BrowserRoot(rootId, extras)
}
}

150
application/vlc-android/src/org/videolan/vlc/car/CarScreens.kt

@ -1,150 +0,0 @@
/*
* ************************************************************************
* CarScreens.kt
* *************************************************************************
* Copyright © 2023 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc.car
import android.content.Intent
import androidx.annotation.StringRes
import androidx.car.app.CarContext
import androidx.car.app.CarToast
import androidx.car.app.Screen
import androidx.car.app.model.Action
import androidx.car.app.model.ItemList
import androidx.car.app.model.ListTemplate
import androidx.car.app.model.LongMessageTemplate
import androidx.car.app.model.ParkedOnlyOnClickListener
import androidx.car.app.model.Row
import androidx.car.app.model.SectionedItemList
import androidx.car.app.model.Template
import androidx.car.app.model.Toggle
import androidx.core.content.edit
import org.videolan.resources.AppContextProvider
import org.videolan.tools.ENABLE_ANDROID_AUTO_SEEK_BUTTONS
import org.videolan.tools.ENABLE_ANDROID_AUTO_SPEED_BUTTONS
import org.videolan.tools.KEY_PLAYBACK_SPEED_AUDIO_GLOBAL
import org.videolan.tools.Settings
import org.videolan.vlc.PlaybackService
import org.videolan.vlc.R
import org.videolan.vlc.gui.preferences.PreferencesActivity
class CarSettingsScreen(carContext: CarContext) : Screen(carContext) {
override fun onGetTemplate(): Template {
val controlItems = ItemList.Builder().apply {
addItem(buildBrowsableRow(R.string.audio, AutoControlScreen(carContext)))
}.build()
val helpItems = ItemList.Builder().apply {
addItem(buildBrowsableRow(R.string.podcast_mode,
LongMessageScreen(carContext, R.string.podcast_mode, R.string.podcast_mode_help, R.string.podcast_mode_genres)))
addItem(buildBrowsableRow(R.string.voice_control,
LongMessageScreen(carContext, R.string.voice_control, R.string.voice_control_help)))
}.build()
val moreItems = ItemList.Builder().apply {
addItem(Row.Builder().apply {
setTitle(AppContextProvider.appContext.getString(R.string.open_on_phone))
setOnClickListener(ParkedOnlyOnClickListener.create(::openPreferencesOnPhone))
}.build())
}.build()
return ListTemplate.Builder().apply {
setHeaderAction(Action.BACK)
setTitle(AppContextProvider.appContext.getString(R.string.preferences))
addSectionedList(SectionedItemList.create(controlItems, AppContextProvider.appContext.getString(R.string.controls_prefs_category)))
addSectionedList(SectionedItemList.create(helpItems, AppContextProvider.appContext.getString(R.string.help)))
addSectionedList(SectionedItemList.create(moreItems, AppContextProvider.appContext.getString(R.string.more_preferences)))
}.build()
}
private fun buildBrowsableRow(@StringRes title: Int, screen: Screen): Row {
return Row.Builder().apply {
setBrowsable(true)
setTitle(AppContextProvider.appContext.getString(title))
setOnClickListener { screenManager.push(screen) }
}.build()
}
private fun openPreferencesOnPhone() {
val intent = Intent(carContext, PreferencesActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
}
carContext.startActivity(intent)
CarToast.makeText(carContext, AppContextProvider.appContext.getText(R.string.prefs_opened_on_phone), CarToast.LENGTH_SHORT).show()
}
}
class LongMessageScreen(carContext: CarContext, @StringRes private val titleRes: Int, @StringRes private val messageRes: Int, @StringRes private val messageRes2: Int? = null) : Screen(carContext) {
override fun onGetTemplate(): Template {
val title = AppContextProvider.appContext.getString(titleRes)
val message = messageRes2?.let {
AppContextProvider.appContext.getString(messageRes).format(AppContextProvider.appContext.getString(it))
} ?: AppContextProvider.appContext.getString(messageRes)
return LongMessageTemplate.Builder(message).apply {
setHeaderAction(Action.BACK)
setTitle(title)
}.build()
}
}
class AutoControlScreen(carContext: CarContext) : Screen(carContext) {
override fun onGetTemplate(): Template {
val itemList = ItemList.Builder().apply {
addItem(buildToggleRow(R.string.audio_playback_speed_global,
R.string.audio_playback_speed_global_summary,
KEY_PLAYBACK_SPEED_AUDIO_GLOBAL))
addItem(buildToggleRow(
R.string.enable_android_auto_speed_buttons,
R.string.enable_android_auto_speed_buttons_summary,
ENABLE_ANDROID_AUTO_SPEED_BUTTONS))
addItem(buildToggleRow(
R.string.enable_android_auto_seek_buttons,
R.string.enable_android_auto_seek_buttons_summary,
ENABLE_ANDROID_AUTO_SEEK_BUTTONS))
}.build()
return ListTemplate.Builder().apply {
setSingleList(itemList)
setHeaderAction(Action.BACK)
setTitle(AppContextProvider.appContext.getString(R.string.audio))
}.build()
}
private fun buildToggleRow(@StringRes titleRes: Int, @StringRes summaryRes: Int, key: String, defValue: Boolean = false): Row {
val settings = Settings.getInstance(carContext)
val onCheckedListener = Toggle.OnCheckedChangeListener { isChecked ->
settings.edit { putBoolean(key, isChecked) }
// Invoke publishState to update the Android Auto UI
PlaybackService.updateState()
}
return Row.Builder().apply {
setTitle(AppContextProvider.appContext.getString(titleRes))
addText(AppContextProvider.appContext.getString(summaryRes))
setToggle(Toggle.Builder(onCheckedListener).apply {
setChecked(settings.getBoolean(key, defValue))
}.build())
}.build()
}
}

81
application/vlc-android/src/org/videolan/vlc/car/VLCCarService.kt

@ -1,81 +0,0 @@
/*
* ************************************************************************
* VLCCarService.kt
* *************************************************************************
* Copyright © 2023 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc.car
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.os.Build
import androidx.activity.OnBackPressedCallback
import androidx.annotation.RequiresApi
import androidx.car.app.CarAppService
import androidx.car.app.ScreenManager
import androidx.car.app.Session
import androidx.car.app.validation.HostValidator
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import org.videolan.resources.ANDROID_AUTO_APP_PKG
import org.videolan.vlc.util.AccessControl
@RequiresApi(Build.VERSION_CODES.O)
class VLCCarService : CarAppService() {
override fun createHostValidator(): HostValidator {
return if (applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0) {
HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
} else {
HostValidator.Builder(applicationContext).apply {
AccessControl.getKeysByPackage(ANDROID_AUTO_APP_PKG).forEach { key ->
addAllowedHost(ANDROID_AUTO_APP_PKG, key.replace(":", ""))
}
}.build()
}
}
override fun onCreateSession() = SettingsSession()
}
class SettingsSession : Session(), DefaultLifecycleObserver {
init {
lifecycle.addObserver(this@SettingsSession)
}
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
carContext.onBackPressedDispatcher.addCallback(this@SettingsSession, object : OnBackPressedCallback(true) {
/**
* Finish the app when the back button is pressed on the root menu
*/
override fun handleOnBackPressed() {
val screenManager = carContext.getCarService(ScreenManager::class.java)
when {
screenManager.stackSize > 1 -> screenManager.pop()
else -> carContext.finishCarApp()
}
}
})
}
override fun onCreateScreen(intent: Intent) = CarSettingsScreen(carContext)
}
Loading…
Cancel
Save