diff --git a/application/resources/src/main/java/org/videolan/resources/Constants.kt b/application/resources/src/main/java/org/videolan/resources/Constants.kt index 021b23bf9..eb136ef92 100644 --- a/application/resources/src/main/java/org/videolan/resources/Constants.kt +++ b/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 diff --git a/application/vlc-android/AndroidManifest.xml b/application/vlc-android/AndroidManifest.xml index a2ebbd080..f23beb540 100644 --- a/application/vlc-android/AndroidManifest.xml +++ b/application/vlc-android/AndroidManifest.xml @@ -1067,18 +1067,6 @@ - - - - - - - - - - diff --git a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt index 52ccd2771..ec2939ca1 100644 --- a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt +++ b/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) } } diff --git a/application/vlc-android/src/org/videolan/vlc/car/CarScreens.kt b/application/vlc-android/src/org/videolan/vlc/car/CarScreens.kt deleted file mode 100644 index f94c17e58..000000000 --- a/application/vlc-android/src/org/videolan/vlc/car/CarScreens.kt +++ /dev/null @@ -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() - } -} diff --git a/application/vlc-android/src/org/videolan/vlc/car/VLCCarService.kt b/application/vlc-android/src/org/videolan/vlc/car/VLCCarService.kt deleted file mode 100644 index 06864f14b..000000000 --- a/application/vlc-android/src/org/videolan/vlc/car/VLCCarService.kt +++ /dev/null @@ -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) -}