[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 813de42e38 -s ours
am skip reason: subject contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Car/Media/+/15154804
Change-Id: I079a5802c59aba8fb4cf2446053ae95e4c374d7f
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bdb2b9b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+# Python
+*.pyc
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index c7536fc..152ef44 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
android_app {
name: "CarMediaApp",
@@ -21,7 +25,7 @@
resource_dirs: ["res"],
- required: ["privapp_whitelist_com.android.car.media"],
+ required: ["allowed_privapp_com.android.car.media"],
certificate: "platform",
@@ -44,6 +48,7 @@
"car-apps-common",
"car-media-common",
"car-ui-lib",
+ "car-uxr-client-lib",
],
product_variables: {
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 43e1fbe..4d823c4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -53,11 +53,14 @@
<activity
android:name=".MediaDispatcherActivity"
android:theme="@android:style/Theme.NoDisplay"
+ android:exported="true"
android:launchMode="singleTask">
<meta-data android:name="distractionOptimized" android:value="true"/>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.INFO" />
+ <category android:name="android.intent.category.APP_MUSIC" />
</intent-filter>
<intent-filter>
<action android:name="android.car.intent.action.MEDIA_TEMPLATE" />
@@ -66,7 +69,8 @@
</activity>
<service
- android:name=".service.MediaConnectorService">
+ android:name=".service.MediaConnectorService"
+ android:exported="true">
<intent-filter>
<action android:name="com.android.car.media.MEDIA_CONNECTION"/>
</intent-filter>
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..e91b525
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,8 @@
+[Hook Scripts]
+checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
+ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
+overlayable_resource_hook = ${REPO_ROOT}/packages/apps/Car/tests/tools/rro/verify-overlayable.py -r res -e res/values/overlayable.xml res/xml/automotive_app_desc.xml -o res/values/overlayable.xml
+
+[Builtin Hooks]
+commit_msg_changeid_field = true
+commit_msg_test_field = true
diff --git a/res/color/progress_bar_thumb_inner_ring_color.xml b/res/color/progress_bar_thumb_inner_ring_color.xml
new file mode 100644
index 0000000..d3a9d4e
--- /dev/null
+++ b/res/color/progress_bar_thumb_inner_ring_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="@color/car_ui_rotary_focus_fill_color"/>
+ <item android:color="@android:color/transparent"/>
+</selector>
diff --git a/res/color/progress_bar_thumb_outer_ring_color.xml b/res/color/progress_bar_thumb_outer_ring_color.xml
new file mode 100644
index 0000000..1bc1926
--- /dev/null
+++ b/res/color/progress_bar_thumb_outer_ring_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="@color/car_ui_rotary_focus_stroke_color"/>
+ <item android:color="@android:color/transparent"/>
+</selector>
diff --git a/res/drawable/grid_item_background.xml b/res/drawable/grid_item_background.xml
deleted file mode 100644
index 0b57a5c..0000000
--- a/res/drawable/grid_item_background.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright 2019 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<ripple
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/car_card_ripple_background">
- <item android:id="@android:id/mask">
- <shape android:shape="rectangle">
- <solid android:color="@android:color/white"/>
- <corners android:radius="@dimen/media_browse_grid_item_background_radius"/>
- </shape>
- </item>
-</ripple>
\ No newline at end of file
diff --git a/res/drawable/seekbar_foreground.xml b/res/drawable/seekbar_foreground.xml
new file mode 100644
index 0000000..3942e21
--- /dev/null
+++ b/res/drawable/seekbar_foreground.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- SeekBar highlight is drawn when it's focused but not in direct manipulation mode. When
+ in direct manipulation mode (android:state_selected="true"), the highlight is drawn on
+ the thumb instead. -->
+ <item android:state_selected="false" android:state_focused="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/car_ui_rotary_focus_fill_color"/>
+ <stroke android:width="@dimen/car_ui_rotary_focus_stroke_width"
+ android:color="@color/car_ui_rotary_focus_stroke_color"/>
+ </shape>
+ </item>
+</selector>
diff --git a/res/drawable/seekbar_background.xml b/res/drawable/seekbar_progress.xml
similarity index 95%
rename from res/drawable/seekbar_background.xml
rename to res/drawable/seekbar_progress.xml
index ec08455..3e68a73 100644
--- a/res/drawable/seekbar_background.xml
+++ b/res/drawable/seekbar_progress.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2016, The Android Open Source Project
+ Copyright 2020, The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/res/drawable/seekbar_thumb.xml b/res/drawable/seekbar_thumb.xml
index 1d0b4a1..eb0c253 100644
--- a/res/drawable/seekbar_thumb.xml
+++ b/res/drawable/seekbar_thumb.xml
@@ -14,10 +14,28 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid android:color="@color/progress_bar_thumb_color"/>
- <size
- android:width="@dimen/playback_seekbar_thumb_width"
- android:height="@dimen/playback_seekbar_thumb_height"/>
-</shape>
\ No newline at end of file
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/thumb_center">
+ <shape android:shape="oval">
+ <solid android:color="@color/progress_bar_thumb_color"/>
+ <size android:width="@dimen/playback_seekbar_thumb_width"
+ android:height="@dimen/playback_seekbar_thumb_height"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="ring"
+ android:innerRadius="@dimen/playback_seekbar_thumb_inner_ring_inner_radius"
+ android:thickness="@dimen/playback_seekbar_thumb_inner_ring_thickness"
+ android:useLevel="false">
+ <solid android:color="@color/progress_bar_thumb_inner_ring_color"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="ring"
+ android:innerRadius="@dimen/playback_seekbar_thumb_outer_ring_inner_radius"
+ android:thickness="@dimen/playback_seekbar_thumb_outer_ring_thickness"
+ android:useLevel="false">
+ <solid android:color="@color/progress_bar_thumb_outer_ring_color"/>
+ </shape>
+ </item>
+</layer-list>
diff --git a/res/layout/browse_node.xml b/res/layout/browse_node.xml
new file mode 100644
index 0000000..11cdaf5
--- /dev/null
+++ b/res/layout/browse_node.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Clone the top guideline since we don't need the others here. -->
+ <Space
+ android:id="@+id/ui_content_top_guideline2"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginTop="@dimen/car_ui_toolbar_first_row_height"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ />
+
+ <ImageView
+ android:id="@+id/error_icon"
+ android:layout_width="@dimen/missing_permission_icon_size"
+ android:layout_height="@dimen/missing_permission_icon_size"
+ app:layout_constraintTop_toBottomOf="@+id/ui_content_top_guideline2"
+ app:layout_constraintBottom_toTopOf="@+id/error_message"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintVertical_chainStyle="packed"
+ android:src="@drawable/error_illustration"
+ android:visibility="gone"
+ android:tint="@color/icon_tint"/>
+
+ <TextView
+ android:id="@+id/error_message"
+ android:layout_width="wrap_content"
+ style="@style/ErrorTextStyle"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/browse_state_error_margin_top"
+ app:layout_constraintTop_toBottomOf="@+id/error_icon"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:maxLines="3"
+ android:text="@string/nothing_to_play"
+ android:visibility="gone"/>
+
+ <com.android.car.ui.FocusArea
+ android:id="@+id/focus_area"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent">
+ <com.android.car.ui.recyclerview.CarUiRecyclerView
+ android:id="@+id/browse_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:visibility="gone"
+ app:layoutStyle="grid"
+ app:numOfColumns="@integer/num_browse_columns"/>
+ </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/fragment_browse.xml b/res/layout/fragment_browse.xml
index 60216a9..597c48c 100644
--- a/res/layout/fragment_browse.xml
+++ b/res/layout/fragment_browse.xml
@@ -15,56 +15,21 @@
limitations under the License.
-->
<androidx.constraintlayout.widget.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <ImageView
- android:id="@+id/error_icon"
- android:layout_width="@dimen/missing_permission_icon_size"
- android:layout_height="@dimen/missing_permission_icon_size"
- app:layout_constraintTop_toBottomOf="@+id/app_bar"
- app:layout_constraintBottom_toTopOf="@+id/error_message"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintVertical_chainStyle="packed"
- android:src="@drawable/error_illustration"
- android:visibility="gone"
- android:tint="@color/icon_tint"/>
+ <include layout="@layout/ui_guides"/>
- <TextView
- android:id="@+id/error_message"
- android:layout_width="wrap_content"
- style="@style/ErrorTextStyle"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/browse_state_error_margin_top"
- app:layout_constraintTop_toBottomOf="@+id/error_icon"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- android:maxLines="3"
- android:text="@string/nothing_to_play"
- android:visibility="gone" />
-
- <com.android.car.ui.recyclerview.CarUiRecyclerView
- android:id="@+id/browse_list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clickable="true"
- android:focusable="true"
- android:clipToPadding="false"
- android:visibility="gone"
- app:layoutStyle="grid"
- app:numOfColumns="@integer/num_browse_columns"
- />
-
- <com.android.car.media.widgets.AppBarView
- android:id="@+id/app_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ <FrameLayout
+ android:id="@+id/browse_content_area"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ app:layout_constraintStart_toStartOf="@+id/ui_content_start_guideline"
+ app:layout_constraintEnd_toEndOf="@+id/ui_content_end_guideline"
app:layout_constraintTop_toTopOf="parent"
- app:showMenuItemsWhileSearching="false"
+ app:layout_constraintBottom_toTopOf="@+id/ui_content_bottom_guideline"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/fragment_error.xml b/res/layout/fragment_error.xml
index 872adc2..ab06840 100644
--- a/res/layout/fragment_error.xml
+++ b/res/layout/fragment_error.xml
@@ -17,38 +17,48 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/error_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <com.android.car.apps.common.UxrTextView
- android:id="@+id/error_message"
- style="@style/FullScreenErrorMessageStyle"
- android:layout_marginHorizontal="@dimen/fragment_error_message_margin_x"
+ <include layout="@layout/ui_guides"/>
+
+ <com.android.car.ui.FocusArea
+ android:layout_width="0dp"
+ android:layout_height="0dp"
app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/app_bar"
- app:layout_constraintBottom_toTopOf="@+id/error_button"
- />
+ app:layout_constraintStart_toStartOf="@+id/ui_content_start_guideline"
+ app:layout_constraintEnd_toEndOf="@+id/ui_content_end_guideline"
+ app:layout_constraintTop_toBottomOf="@+id/ui_content_top_guideline"
+ app:layout_constraintBottom_toBottomOf="@+id/ui_content_bottom_guideline">
- <com.android.car.apps.common.UxrButton
- android:id="@+id/error_button"
- style="@style/FullScreenErrorButtonStyle"
- android:layout_marginTop="@dimen/fragment_error_button_margin_top"
- android:layout_marginBottom="@dimen/fragment_error_button_margin_bottom"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/error_message"
- app:layout_constraintBottom_toBottomOf="parent"
- />
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:layout_constraintVertical_chainStyle="packed">
- <com.android.car.media.widgets.AppBarView
- android:id="@+id/app_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:layout_constraintTop_toTopOf="parent"
- app:showMenuItemsWhileSearching="false"
- />
+ <com.android.car.apps.common.UxrTextView
+ android:id="@+id/error_message"
+ style="@style/FullScreenErrorMessageStyle"
+ android:layout_marginHorizontal="@dimen/fragment_error_message_margin_x"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/error_button"
+ />
+
+ <com.android.car.apps.common.UxrButton
+ android:id="@+id/error_button"
+ style="@style/FullScreenErrorButtonStyle"
+ android:layout_marginTop="@dimen/fragment_error_button_margin_top"
+ android:layout_marginBottom="@dimen/fragment_error_button_margin_bottom"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/error_message"
+ app:layout_constraintBottom_toBottomOf="parent"
+ />
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ </com.android.car.ui.FocusArea>
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/fragment_playback.xml b/res/layout/fragment_playback.xml
index 50eeb3e..d9503c1 100644
--- a/res/layout/fragment_playback.xml
+++ b/res/layout/fragment_playback.xml
@@ -21,12 +21,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/app_bar_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_first_row_height"/>
+ <include layout="@layout/ui_guides"/>
<Space
android:id="@+id/control_bar_first_row_guideline"
@@ -50,30 +45,22 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
- <com.android.car.ui.toolbar.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:title="@string/fragment_playback_title"
- app:layout_constraintTop_toTopOf="parent"
- app:car_ui_state="subpage"/>
-
<include
style="@style/MetadataContainerStyle"
android:id="@+id/metadata_container"
layout="@layout/metadata_normal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@id/app_bar_guideline"
+ app:layout_constraintTop_toBottomOf="@id/ui_content_top_guideline"
app:layout_constraintBottom_toTopOf="@+id/control_bar_first_row_guideline"/>
- <!-- @id/seek_bar should be hidden when @id/control_bar_scrim is expanded, and shown when the
- scrim is collapsed. Since its visibility is also controlled by MetadataController, it could
- become visible again even if the scrim is still expanded. To solve that we add a wrapper around
- it and hide/show the wrapper when the scrim is expanded/collapsed.-->
- <FrameLayout
+ <!-- @id/playback_seek_bar should be hidden when @id/control_bar_scrim is expanded, and shown
+ when the scrim is collapsed. Since its visibility is also controlled by MetadataController, it
+ could become visible again even if the scrim is still expanded. To solve that we add a wrapper
+ around it and hide/show the wrapper when the scrim is expanded/collapsed.-->
+ <com.android.car.ui.FocusArea
style="@style/SeekBarStyle"
- android:id="@+id/seek_bar_container"
+ android:id="@+id/playback_seek_bar_container"
android:layout_gravity="center"
android:layout_marginStart="@dimen/playback_seekbar_margin_x"
android:layout_marginEnd="@dimen/playback_seekbar_margin_x"
@@ -82,27 +69,26 @@
app:layout_constraintTop_toBottomOf="@+id/metadata_container"
app:layout_constraintBottom_toTopOf="@+id/control_bar_first_row_guideline">
<SeekBar
- android:id="@+id/seek_bar"
+ android:id="@+id/playback_seek_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
- android:focusable="false"
android:paddingEnd="@dimen/playback_seekbar_padding_x"
android:paddingStart="@dimen/playback_seekbar_padding_x"
- android:progressDrawable="@drawable/seekbar_background"
+ android:progressDrawable="@drawable/seekbar_progress"
android:thumb="@drawable/seekbar_thumb"
android:thumbOffset="@dimen/playback_seekbar_thumb_offset"
android:splitTrack="false"
android:progressTint="@color/progress_bar_highlight"
android:progressBackgroundTint="@color/progress_bar_background"
- android:background="@null"/>
- </FrameLayout>
+ android:foreground="@drawable/seekbar_foreground"/>
+ </com.android.car.ui.FocusArea>
<Space
android:id="@+id/queue_list_top_constraint"
android:layout_width="match_parent"
android:layout_height="@dimen/fragment_playback_queue_overlap_top"
- app:layout_constraintBottom_toBottomOf="@+id/app_bar_guideline"/>
+ app:layout_constraintBottom_toBottomOf="@+id/ui_content_top_guideline"/>
<Space
android:id="@+id/queue_list_bottom_constraint"
@@ -110,8 +96,7 @@
android:layout_height="@dimen/fragment_playback_queue_overlap_bottom"
app:layout_constraintTop_toTopOf="@+id/control_bar_first_row_guideline"/>
- <!-- The queue_container is a workaround for a bug in PagedRecyclerView (b/136669451). -->
- <RelativeLayout
+ <com.android.car.ui.FocusArea
android:id="@+id/queue_container"
android:layout_width="match_parent"
android:layout_height="0dp"
@@ -125,7 +110,7 @@
android:fadeScrollbars="true"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="@dimen/queue_fading_edge_length"/>
- </RelativeLayout>
+ </com.android.car.ui.FocusArea>
<include
layout="@layout/scrim_overlay"
@@ -137,14 +122,18 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
- <com.android.car.media.common.PlaybackControlsActionBar
- android:id="@+id/playback_controls"
- style="@style/ControlBar"
+ <com.android.car.ui.FocusArea
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/control_bar_margin_x"
android:layout_marginBottom="@dimen/control_bar_margin_bottom"
- app:columns="5"
- app:enableOverflow="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
+ app:layout_constraintEnd_toEndOf="parent">
+ <com.android.car.media.common.PlaybackControlsActionBar
+ android:id="@+id/playback_controls"
+ style="@style/ControlBar"
+ app:columns="5"
+ app:enableOverflow="true"/>
+ </com.android.car.ui.FocusArea>
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/media_activity.xml b/res/layout/media_activity.xml
index fd4a687..2cd6e34 100644
--- a/res/layout/media_activity.xml
+++ b/res/layout/media_activity.xml
@@ -20,6 +20,12 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <com.android.car.ui.FocusParkingView
+ android:id="@+id/fpv"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
@@ -28,27 +34,24 @@
/>
<FrameLayout
- android:id="@+id/search_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone"
- />
-
- <FrameLayout
android:id="@+id/error_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
/>
- <com.android.car.media.common.MinimizedPlaybackControlBar
- android:id="@+id/minimized_playback_controls"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ <com.android.car.ui.FocusArea
+ style="@style/MinimizedControlBar"
android:layout_marginHorizontal="@dimen/minimized_control_bar_margin_x"
android:layout_marginBottom="@dimen/minimized_control_bar_margin_bottom"
- android:layout_gravity="bottom"
- />
+ android:layout_gravity="center|bottom">
+ <com.android.car.media.common.MinimizedPlaybackControlBar
+ android:id="@+id/minimized_playback_controls"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ />
+ </com.android.car.ui.FocusArea>
<FrameLayout
android:id="@+id/playback_container"
diff --git a/res/layout/media_browse_grid_icons_item.xml b/res/layout/media_browse_grid_icons_item.xml
index 6445c03..6e0887a 100644
--- a/res/layout/media_browse_grid_icons_item.xml
+++ b/res/layout/media_browse_grid_icons_item.xml
@@ -17,23 +17,29 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:focusable="true"
- android:clickable="true"
- android:foreground="@drawable/grid_item_background"
android:padding="@dimen/media_browse_grid_item_padding"
android:layout_marginBottom="@dimen/media_browse_grid_item_margin_bottom">
- <ImageView
- android:id="@+id/thumbnail"
- android:layout_width="@dimen/media_browse_grid_icons_item_art_size"
- android:layout_height="@dimen/media_browse_grid_icons_item_art_size"
- android:scaleType="centerCrop"
+ <FrameLayout
+ android:id="@+id/item_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:focusable="true"
+ android:foreground="?android:attr/selectableItemBackground"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
+ app:layout_constraintEnd_toEndOf="parent">
+
+ <ImageView
+ android:id="@+id/thumbnail"
+ android:layout_width="@dimen/media_browse_grid_icons_item_art_size"
+ android:layout_height="@dimen/media_browse_grid_icons_item_art_size"
+ android:scaleType="centerCrop"/>
+
+ </FrameLayout>
<ImageView
android:id="@+id/download_icon_with_title"
@@ -69,7 +75,7 @@
android:includeFontPadding="false"
android:duplicateParentState="true"
app:layout_constraintStart_toEndOf="@+id/explicit_icon_with_title"
- app:layout_constraintTop_toBottomOf="@+id/thumbnail"
+ app:layout_constraintTop_toBottomOf="@+id/item_container"
app:layout_constraintEnd_toEndOf="parent"/>
<ImageView
diff --git a/res/layout/media_browse_grid_item.xml b/res/layout/media_browse_grid_item.xml
index 1a96024..229a674 100644
--- a/res/layout/media_browse_grid_item.xml
+++ b/res/layout/media_browse_grid_item.xml
@@ -17,24 +17,30 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:focusable="true"
- android:clickable="true"
- android:foreground="@drawable/grid_item_background"
android:padding="@dimen/media_browse_grid_item_padding"
android:layout_marginBottom="@dimen/media_browse_grid_item_margin_bottom">
- <com.android.car.media.common.FixedRatioImageView
- android:id="@+id/thumbnail"
+ <FrameLayout
+ android:id="@+id/item_container"
android:layout_width="match_parent"
- android:layout_height="0dp"
- android:scaleType="centerCrop"
- app:aspect_ratio="1"
- app:layout_constraintTop_toTopOf="parent"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:focusable="true"
+ android:foreground="?android:attr/selectableItemBackground"
+ app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
+ app:layout_constraintTop_toTopOf="parent">
+
+ <com.android.car.media.common.FixedRatioImageView
+ android:id="@+id/thumbnail"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:scaleType="centerCrop"
+ app:aspect_ratio="1"/>
+
+ </FrameLayout>
<ImageView
android:id="@+id/download_icon_with_title"
@@ -68,7 +74,7 @@
android:includeFontPadding="false"
android:duplicateParentState="true"
app:layout_constraintStart_toEndOf="@+id/explicit_icon_with_title"
- app:layout_constraintTop_toBottomOf="@+id/thumbnail"
+ app:layout_constraintTop_toBottomOf="@+id/item_container"
app:layout_constraintEnd_toEndOf="parent"/>
<ImageView
diff --git a/res/layout/media_browse_header_item.xml b/res/layout/media_browse_header_item.xml
index 3e17f98..1fa6d47 100644
--- a/res/layout/media_browse_header_item.xml
+++ b/res/layout/media_browse_header_item.xml
@@ -16,7 +16,7 @@
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/container"
+ android:id="@+id/item_container"
android:layout_width="match_parent"
android:layout_height="@dimen/media_browse_header_item_height"
android:layout_marginHorizontal="@dimen/media_browse_header_item_margin_x">
diff --git a/res/layout/media_browse_list_icons_item.xml b/res/layout/media_browse_list_icons_item.xml
index a5db077..9c8d972 100644
--- a/res/layout/media_browse_list_icons_item.xml
+++ b/res/layout/media_browse_list_icons_item.xml
@@ -17,7 +17,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/container"
+ android:id="@+id/item_container"
android:layout_width="match_parent"
android:layout_height="@dimen/media_browse_list_item_height"
android:paddingStart="@dimen/media_browse_list_item_icon_margin_start"
diff --git a/res/layout/media_browse_list_item.xml b/res/layout/media_browse_list_item.xml
index bd71f8f..52c2d50 100644
--- a/res/layout/media_browse_list_item.xml
+++ b/res/layout/media_browse_list_item.xml
@@ -17,7 +17,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/container"
+ android:id="@+id/item_container"
android:layout_width="match_parent"
android:layout_height="@dimen/media_browse_list_item_height"
android:paddingStart="@dimen/media_browse_list_item_icon_margin_start"
diff --git a/res/layout/queue_list_item.xml b/res/layout/queue_list_item.xml
index e4b77c8..a77187c 100644
--- a/res/layout/queue_list_item.xml
+++ b/res/layout/queue_list_item.xml
@@ -16,7 +16,7 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/container"
+ android:id="@+id/item_container"
android:layout_width="match_parent"
android:layout_height="@dimen/queue_list_item_height"
android:paddingEnd="@dimen/queue_list_item_padding_x"
diff --git a/res/layout/ui_guides.xml b/res/layout/ui_guides.xml
new file mode 100644
index 0000000..a2312f7
--- /dev/null
+++ b/res/layout/ui_guides.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <Space
+ android:id="@+id/ui_content_start_guideline"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="0dp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ />
+
+ <Space
+ android:id="@+id/ui_content_top_guideline"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginTop="@dimen/car_ui_toolbar_first_row_height"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ />
+
+ <Space
+ android:id="@+id/ui_content_end_guideline"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_marginRight="0dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ />
+
+ <Space
+ android:id="@+id/ui_content_bottom_guideline"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginBottom="0dp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ />
+
+</merge>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index e42042a..b01f0df 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Soek liedjies, kunstenaars, en meer …"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Wat Speel"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Iets is fout. Probeer later."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Kan dit nie op die oomblik doen nie"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Hierdie program kan nie dit doen nie"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Meld aan om hierdie program te gebruik"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premiumtoegang word vereis"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Luister tans op te veel toestelle"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Daardie inhoud word geblokkeer"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Kan nie daardie inhoud hier kry nie"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Speel reeds daardie inhoud"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Kan nie meer snitte oorslaan nie"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Kon nie voltooi word nie. Probeer weer."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Daar is niks anders op die waglys nie"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Koppel tans aan media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Klankinstellings"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Wissel programme"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 73a9e28..c6842b1 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"ማህደረ መረጃ"</string>
<string name="search_hint" msgid="5401750426238148416">"ዘፈኖችን፣ አርቲስቶችን እና ተጨማሪ ይፈልጉ..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"አሁን እየተጫወተ ያለ"</string>
- <string name="default_error_message" msgid="6365377134388091079">"የሆነ ችግር አለ። በኋላ ይሞክሩ።"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"አሁን ይህን ማድረግ አይቻልም"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ይህ መተግበሪያ ይህን ማድረግ አይችልም"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ይህን መተግበሪያ ለመጠቀም በመለያ ይግቡ"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ፕሪሚየም መዳረሻ ያስፈልጋል"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"በጣም ብዙ መሣሪያዎችን በማዳመጥ ላይ"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ይዘቱ ታግዷል"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ይዘቱን እዚህ ማግኘት አልተቻለም"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ይዘቱ አስቀድሞ በመጫወት ላይ"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ተጨማሪ ትራኮችን መዝለል አአይቻልም"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"መጨረስ አልተቻለም። እንደገና ይሞክሩ።"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"ሌላ ምንም ነገር ወረፋ አልያዘም"</string>
<string name="service_notification_title" msgid="8085444675783592744">"ከሚዲያ ጋር በመገናኘት ላይ"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"የድምፅ ቅንብሮች"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"መተግበሪያዎችን ቀያይር"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 4638554..5a3c04e 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"الوسائط"</string>
<string name="search_hint" msgid="5401750426238148416">"البحث في الأغاني والفنانين والمزيد..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"التعرُّف التلقائي على الموسيقى"</string>
- <string name="default_error_message" msgid="6365377134388091079">"حدث خطأ. يُرجى المحاولة لاحقًا."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"يتعذر على التطبيق تنفيذ هذا الإجراء في الوقت الحالي."</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"يتعذّر على التطبيق تنفيذ هذا الإجراء."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"سجّل دخولك لاستخدام هذا التطبيق."</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"مطلوب الحصول على إذن الوصول المميَّز."</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"يتم الآن الاستماع على أجهزة أكثر من الحد المسموح به."</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"تم حظر هذا المحتوى."</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"لا يمكن الحصول على هذا المحتوى من هنا."</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"جارٍ تشغيل هذا المحتوى."</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"لا يمكن تخطي المزيد من المقاطع الصوتية."</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"تعذر الإنهاء. يُرجى إعادة المحاولة."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"لم يتم وضع أي مقطع صوتي آخر في قائمة الانتظار."</string>
<string name="service_notification_title" msgid="8085444675783592744">"الاتصال بالوسائط"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"إعدادات الصوت"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"تبديل التطبيقات"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index ed1aa09..b3c4830 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"মিডিয়া"</string>
<string name="search_hint" msgid="5401750426238148416">"গান, শিল্পী আৰু অধিক..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"এতিয়া এয়া প্লে\' হৈ আছে"</string>
- <string name="default_error_message" msgid="6365377134388091079">"কিবা ভুল হ’ল। পাছত চেষ্টা কৰক।"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"সেইটো এই মুহূৰ্তত কৰিব নোৱাৰি"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"এই এপ্টোৱে সেইটো কৰিব নোৱাৰে"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"এই এপ্টো ব্যৱহাৰ কৰিবলৈ ছাইন ইন কৰক"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"প্ৰিমিয়াম এক্সেছৰ প্ৰয়োজন"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"বহুকেইটা ডিভাইচত শুনি আছে"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"সেই সমলটো অৱৰোধ কৰা আছে"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"সেই সমলটো ইয়াত পাব নোৱাৰি"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"সেই সমলটো ইতিমধ্যে প্লে’ হৈ আছে"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"আৰু ট্ৰেক এৰি যাব নোৱাৰি"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"সম্পূর্ণ কৰিব পৰা নগ’ল। আকৌ চেষ্টা কৰক।"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"শাৰীত অন্য একো নাই"</string>
<string name="service_notification_title" msgid="8085444675783592744">"মিডিয়াৰ সৈতে সংযোগ কৰি থকা হৈছে"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ধ্বনিৰ ছেটিংসমূহ"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"এপসমূহ সলনি কৰক"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index d27aa62..2d73a56 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Mahnı, ifaçı və s. axtarın"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"İndi oxudulur"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Xəta baş verdi. Sonra cəhd edin."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Hazırda onu etmək olmur"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Bu tətbiq onu edə bilmir"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Bu tətbiqi istifadə etmək üçün daxil olun"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium giriş tələb olunur"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Çox cihazda dinləmə aşkarlanıb"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Bu məzmun bloklanıb"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Bu məzmunu əldə etmək mümkün deyil"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Hazırda bu məzmun oxudulur"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Başqa treki keçmək mümkün deyil"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Bitirmək mümkün olmadı. Yenidən cəhd edin."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Növbədə başqa heç nə yoxdur"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Mediaya qoşulur"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Səs ayarları"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Tətbiqləri dəyişdirin"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 4ec1c1b..690453b 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Mediji"</string>
<string name="search_hint" msgid="5401750426238148416">"Tražite pesme, izvođače i drugo..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Trenutno svira"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Nešto nije u redu. Probajte kasnije."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Trenutno ne može to da uradi"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ova aplikacija ne može to da uradi"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Prijavite se da biste koristili ovu aplikaciju"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Potreban je premijum pristup"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Slušate na previše uređaja"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Taj sadržaj je blokiran"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Ne možete da dobijete taj sadržaj ovde"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Taj sadržaj se već reprodukuje"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Ne možete više da preskačete pesme"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nismo uspeli da dovršimo radnju. Probajte ponovo."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ništa drugo nije stavljeno u red"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Povezuje se sa medijima"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Podešavanja zvuka"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Pređi na drugu aplikaciju"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 42c7933..f52921a 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Мультымедыя"</string>
<string name="search_hint" msgid="5401750426238148416">"Шукайце кампазіцыі…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Зараз іграе"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Узнікла памылка. Паўтарыце спробу пазней."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Не ўдаецца выканаць гэты запыт"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Праграме не ўдалося выканаць гэты запыт"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Увайдзіце, каб выкарыстоўваць гэту праграму"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Патрэбны платны доступ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Праслухоўваецца занадта шмат прылад"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Гэта змесціва заблакіравана"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Не ўдалося загрузіць змесціва ў гэтым рэгіёне"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Гэта змесціва ўжо прайграецца"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Не ўдалося прапусціць іншыя трэкі"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Не ўдалося завяршыць. Паўтарыце спробу."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"У чарзе пуста"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Ідзе падключэнне да мультымедыя"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Налады гуку"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Змяніць праграму"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 4e20fe8..c646700 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Мултимедия"</string>
<string name="search_hint" msgid="5401750426238148416">"Търсете песни, изпълнители и др..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Сега слушате"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Нещо не е наред. Опитайте по-късно."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Понастоящем тази заявка не може да се изпълни"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Приложението не може да изпълни тази заявка"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Влезте в профила си, за да използвате това приложение"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"За достъп се изисква платен профил"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Слуша се на твърде много устройства"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Това съдържание е блокирано"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Това съдържание не е налице за региона ви"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Това съдържание вече се възпроизвежда"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Не могат да се пропускат повече записи"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Не можа да завърши. Опитайте отново."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Нищо друго не е поставено на опашка"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Установява се връзка с мултимедията"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Настройки за звука"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Превключване на приложенията"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 3e5cec7..9b02b93 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"মিডিয়া"</string>
<string name="search_hint" msgid="5401750426238148416">"গান, শিল্পী ও অনেক কিছু খুঁজুন..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"এখন চলছে"</string>
- <string name="default_error_message" msgid="6365377134388091079">"কোনও সমস্যা হয়েছে। পরে চেষ্টা করুন।"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"এখন এটি করা যাবে না"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"এই অ্যাপটি এটি করতে পারবে না"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"এই অ্যাপ ব্যবহার করতে সাইন-ইন করুন"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium অ্যাক্সেস প্রয়োজন"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"একাধিক ডিভাইসে শুনছেন"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"এই কন্টেন্টটি ব্লক করা হয়েছে"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"এই কন্টেন্টটি এখানে পাওয়া যাবে না"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"কন্টেন্টটি আগে থেকেই চলছে"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"আর কোনও ট্র্যাক এড়িয়ে যেতে পারবেন না"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"সম্পূর্ণ করা যায়নি। আবার চেষ্টা করুন।"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"আর কিছুই অপেক্ষমাণ নয়"</string>
<string name="service_notification_title" msgid="8085444675783592744">"মিডিয়াতে কানেক্ট করা হচ্ছে"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"সাউন্ড সেটিংস"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"অ্যাপ সুইচ করুন"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 41e548c..fb4de24 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Mediji"</string>
<string name="search_hint" msgid="5401750426238148416">"Pretražite pjesme, izvođače i još mnogo toga..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Trenutno se reproducira"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Nešto nije uredu. Pokušajte kasnije."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Taj zahtjev trenutno nije moguće izvršiti"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ova aplikacija ne može izvršiti taj zahtjev"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Prijavite se da koristite ovu aplikaciju"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Potreban je premijum pristup"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Previše je uređaja na kojima se sluša"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Sadržaj je blokiran"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Nije moguće preuzeti taj sadržaj ovdje"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Reproduciranje tog sadržaja je već u toku"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Ne možete više preskakati numere"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Dovršavanje nije uspjelo. Pokušajte ponovo."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ništa više nije postavljeno u red čekanja"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Povezivanje s medijima"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Postavke zvuka"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Prebaci aplikacije"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 5e0ebbc..8ed94b7 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Multimèdia"</string>
<string name="search_hint" msgid="5401750426238148416">"Cerca cançons, artistes i més…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Està sonant"</string>
- <string name="default_error_message" msgid="6365377134388091079">"S\'ha produït un error. Prova-ho més tard."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Aquesta acció no es pot dur a terme ara mateix"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Aquesta aplicació no pot fer això"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Inicia la sessió per fer servir aquesta aplicació"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Es requereix accés Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"S\'està escoltant en massa dispositius"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"El contingut està bloquejat"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"El contingut no està disponible en aquesta regió"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ja s\'està reproduint aquest contingut"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"No es poden saltar més cançons"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"No s\'ha pogut acabar. Torna-ho a provar."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"No hi ha res més a la cua"</string>
<string name="service_notification_title" msgid="8085444675783592744">"S\'està connectant a la font multimèdia"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Configuració del so"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Canvia d\'aplicació"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 22cb6d3..3395351 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Média"</string>
<string name="search_hint" msgid="5401750426238148416">"Vyhledávejte skladby, interprety apod..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Co to hraje"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Někde se stala chyba. Zkuste to později."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Tuto akci teď nelze provést"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Tuto akci aplikace nedokáže provést"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Chcete-li aplikaci použít, přihlaste se"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Je vyžadován prémiový přístup"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Poslech je aktivován v příliš mnoha zařízeních"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Obsah je blokován"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Tento obsah tu nelze načíst"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Tento obsah se už přehrává"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Další skladby nelze přeskočit"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nelze dokončit. Zkuste to znovu."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ve frontě není nic dalšího"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Připojování k médiu"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Nastavení zvuku"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Přepnout aplikace"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 31636a9..d95fd56 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Medie"</string>
<string name="search_hint" msgid="5401750426238148416">"Søg efter sange og kunstnere m.m..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Afspiller nu"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Der er noget galt. Prøv senere."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Det er ikke muligt lige nu"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Det kan denne app ikke gøre"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Log ind for at bruge denne app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Dette kræver en Premium-konto"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Du lytter på for mange enheder"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Indholdet er blokeret"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Der er ikke adgang til indholdet her"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Indholdet afspilles allerede"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Du kan ikke springe over flere numre"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Handlingen kunne ikke afsluttes. Prøv igen."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Der er ikke mere i køen"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Opretter forbindelse til medie"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Lydindstillinger"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Skift mellem apps"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index f05c6a4..1c385c3 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Medien"</string>
<string name="search_hint" msgid="5401750426238148416">"Nach Songs, Künstlern und mehr suchen"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Aktuelle Wiedergabe"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Ein Fehler ist aufgetreten. Versuch es später noch mal."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Das ist gerade nicht möglich"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Diese App kann das nicht"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Damit du diese App verwenden kannst, musst du dich zuerst anmelden"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premiumzugriff erforderlich"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Es wird auf zu vielen Geräten gleichzeitig gestreamt"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Der Inhalt ist gesperrt"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Der Inhalt kann hier nicht abgerufen werden"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Der Inhalt wird bereits wiedergegeben"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Du kannst keine weiteren Titel überspringen"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Die Aktion konnte nicht abgeschlossen werden. Versuch es noch mal."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Es ist sonst nichts in der Warteschlange"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Verbindung zu Medien wird hergestellt"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Toneinstellungen"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Apps wechseln"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 970656e..b92faf8 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Πολυμέσα"</string>
<string name="search_hint" msgid="5401750426238148416">"Αναζ. τραγ., καλλιτ…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Ακούγεται τώρα"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε αργότερα."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Δεν είναι δυνατή η εκτέλεση του αιτήματος αυτήν τη στιγμή."</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Δεν είναι δυνατή η εκτέλεση του αιτήματος από αυτήν την εφαρμογή."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Συνδεθείτε, για να χρησιμοποιήσετε αυτήν την εφαρμογή"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Απαιτείται premium πρόσβαση."</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Ακρόαση πάρα πολλών συσκευών."</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Αυτό το περιεχόμενο είναι αποκλεισμένο."</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Δεν είναι δυνατή η λήψη αυτού του περιεχομένου εδώ."</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Γίνεται ήδη αναπαραγωγή αυτού του περιεχομένου."</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Δεν είναι δυνατή η παράβλεψη περισσότερων κομματιών."</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Δεν ήταν δυνατή η ολοκλήρωση. Δοκιμάστε ξανά."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Δεν υπάρχει κάτι άλλο στην ουρά."</string>
<string name="service_notification_title" msgid="8085444675783592744">"Σύνδεση σε πολυμέσα"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Ρυθμίσεις ήχου"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Να γίνει εναλλαγή μεταξύ εφαρμογών"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 5b2faed..7d6f5ee 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Search songs, artists and more…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Something’s wrong. Try later."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Can’t do that right now"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"This app can’t do that"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Sign in to use this app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium access required"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Listening on too many devices"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"That content is blocked"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Can’t get that content here"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Already playing that content"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Can’t skip any more tracks"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Couldn’t finish. Try again."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nothing else is queued up"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Connecting to media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Sound settings"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Switch apps"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 5b2faed..7d6f5ee 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Search songs, artists and more…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Something’s wrong. Try later."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Can’t do that right now"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"This app can’t do that"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Sign in to use this app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium access required"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Listening on too many devices"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"That content is blocked"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Can’t get that content here"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Already playing that content"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Can’t skip any more tracks"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Couldn’t finish. Try again."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nothing else is queued up"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Connecting to media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Sound settings"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Switch apps"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 5b2faed..7d6f5ee 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Search songs, artists and more…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Something’s wrong. Try later."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Can’t do that right now"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"This app can’t do that"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Sign in to use this app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium access required"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Listening on too many devices"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"That content is blocked"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Can’t get that content here"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Already playing that content"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Can’t skip any more tracks"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Couldn’t finish. Try again."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nothing else is queued up"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Connecting to media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Sound settings"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Switch apps"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 5b2faed..7d6f5ee 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Search songs, artists and more…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Something’s wrong. Try later."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Can’t do that right now"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"This app can’t do that"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Sign in to use this app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium access required"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Listening on too many devices"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"That content is blocked"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Can’t get that content here"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Already playing that content"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Can’t skip any more tracks"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Couldn’t finish. Try again."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nothing else is queued up"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Connecting to media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Sound settings"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Switch apps"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 5537906..a76105f 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Search songs, artists, and more..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Something’s wrong. Try later."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Can’t do that right now"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"This app can’t do that"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Sign in to use this app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium access required"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Listening on too many devices"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"That content is blocked"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Can’t get that content here"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Already playing that content"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Can’t skip any more tracks"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Couldn’t finish. Try again."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nothing else is queued up"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Connecting to media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Sound Settings"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Switch apps"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 6b0b4f8..8c5beaf 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Multimedia"</string>
<string name="search_hint" msgid="5401750426238148416">"Busca artistas y más"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Está Sonando"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Se produjo un error. Vuelve a intentarlo más tarde."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"No se puede realizar esa acción en este momento"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Esta app no puede realizar esa acción"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Accede para usar esta app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Se requiere acceso Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Se está escuchando contenido en demasiados dispositivos"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ese contenido está bloqueado"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"No se puede acceder a ese contenido en esta región"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ya se está reproduciendo ese contenido"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"No se pueden omitir más pistas"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"No se pudo completar la acción. Vuelve a intentarlo."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"No hay más contenido en la cola"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Estableciendo conexión con la fuente de contenido multimedia"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Configuración de sonido"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Cambiar de app"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 900e074..1816f7e 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Multimedia"</string>
<string name="search_hint" msgid="5401750426238148416">"Buscar canciones, artistas, etc."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Reproduciendo"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Se ha producido un error. Inténtalo más tarde."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"No se puede hacer en estos momentos"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"No se puede hacer con esta aplicación"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Inicia sesión para utilizar esta aplicación"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Se necesita acceso premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Se está escuchando en demasiados dispositivos"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ese contenido está bloqueado"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Aquí no se puede reproducir ese contenido"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ya se está reproduciendo ese contenido"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"No se pueden saltar más pistas"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"No se ha podido finalizar. Inténtalo de nuevo."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"No hay nada más en la cola"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Conectando con la fuente de contenido multimedia"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Ajustes de sonido"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Cambiar de aplicación"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 63fbb6a..a690e6d 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Meedia"</string>
<string name="search_hint" msgid="5401750426238148416">"Lugude, esitajate ja muu otsimine …"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Hetkel mängimas"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Midagi on valesti. Proovige hiljem."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Seda ei saa praegu teha"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"See rakendus ei saa seda teha"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Rakenduse kasutamiseks logige sisse"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Vaja on Premium-tasemel juurdepääsu"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Kuulatakse liiga paljudes seadmetes"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"See sisu on blokeeritud"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Seda sisu ei saa siin esitada"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Seda sisu juba esitatakse"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Rohkem lugusid ei saa vahele jätta"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Ei saanud lõpetada. Proovige uuesti."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Midagi muud pole järjekorras"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Meediaga ühendamine"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Heliseaded"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Rakenduste vahetamine"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index cf7313a..aca4209 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Multimedia-edukia"</string>
<string name="search_hint" msgid="5401750426238148416">"Bilatu abestiak, artistak eta beste…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Orain erreproduzitzen"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Arazoren bat izan da. Saiatu geroago."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Ezin da egin halakorik une honetan"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Aplikazio honek ezin du egin halakorik"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Aplikazioa erabiltzeko, hasi saioa"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium sarbidea behar da"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Gailu gehiegitatik jasotzen ari da soinua"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Eduki hori blokeatuta dago"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Ezin da eskuratu eduki hori lurralde honetan"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Dagoeneko ari da erreproduzitzen eduki hori"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Ezin da saltatu pista gehiagorik"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Ezin izan da amaitu ekintza. Saiatu berriro."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ez dago beste ezer ilaran"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Multimedia-edukiaren iturburura konektatzen"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Soinuaren ezarpenak"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Aldatu aplikazioa"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index d9406d2..af2f072 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"رسانه"</string>
<string name="search_hint" msgid="5401750426238148416">"جستجوی آهنگها، هنرمندان و موارد دیگر..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"درحال پخش"</string>
- <string name="default_error_message" msgid="6365377134388091079">"مشکلی رخ داد. بعداً امتحان کنید."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"درحالحاضر انجام نمیشود"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"این برنامه قادر به انجام آن نیست."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"برای استفاده از این به برنامه، به سیستم وارد شوید"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"دسترسی ممتاز لازم است"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"درحال پخش در تعداد زیادی دستگاه"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"این محتوا مسدود شده است"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"نمیتوان این محتوا را در اینجا دریافت کرد"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"از قبل درحال پخش است"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"از هیچ آهنگ دیگری نمیتوان رد شد"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"پایان نیافت. دوباره امتحان کنید."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"هیچ مورد دیگری در صف پخش نیست"</string>
<string name="service_notification_title" msgid="8085444675783592744">"درحال اتصال به رسانه"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"تنظیمات صدا"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"عوض کردن برنامه"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 0c1617f..2ce0f38 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Hae mm. kappaleita…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Musiikintunnistus"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Jotain meni pieleen.. Yritä myöhemmin."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Tämä ei juuri nyt onnistu"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Sovellus ei tue ominaisuutta"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Kirjaudu sisään käyttääksesi tätä sovellusta"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Edellyttää premium-tilausta"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Kuuntelu käynnissä liian monella laitteella"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Tämä sisältö on estetty"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Sisältö ei ole saatavilla tällä"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Se toistetaan jo"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Enimmäismäärä kappaleita ohitettu"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Toiminto keskeytyi. Yritä uudelleen."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ei muuta jonossa"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Yhdistetään mediaan"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Ääniasetukset"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Sovelluksen vaihtaminen"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index ec67c07..aea1742 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Média"</string>
<string name="search_hint" msgid="5401750426238148416">"Rechercher chansons, artistes et plus…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"En cours de lecture"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Quelque chose ne va pas. Réessayez plus tard."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Impossible d\'effectuer cette action pour le moment"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Cette application ne peut pas effectuer cette action"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Connectez-vous pour utiliser cette application"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Un accès Premium est requis"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Écoute en cours sur trop d\'appareils"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ce contenu est bloqué"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Impossible d\'obtenir ce contenu ici"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ce contenu est déjà en cours de lecture"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Impossible de passer à d\'autres chansons"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Impossible de terminer. Réessayez."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Rien d\'autre n\'est dans la file d\'attente"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Connexion au contenu multimédia en cours…"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Paramètres sonores"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Changer d\'application"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 34263ab..aab6fc1 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Médias"</string>
<string name="search_hint" msgid="5401750426238148416">"Titres, artistes…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"En écoute"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Il y a un problème. Réessayez plus tard."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Impossible d\'effectuer cette opération pour le moment"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Cette application ne peut pas effectuer cette opération"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Connectez-vous pour utiliser cette application"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Accès Premium requis"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Écoute en cours sur trop d\'appareils"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ce contenu est bloqué"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Impossible d\'accéder à ce contenu ici"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ce contenu est déjà en cours de lecture"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Impossible de passer d\'autres titres"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Impossible de terminer l\'action. Veuillez réessayer."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Aucun autre titre dans la file d\'attente"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Se connecter au contenu multimédia"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Paramètres audio"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Changer d\'application"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 7fba204..4efb241 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Contido multimedia"</string>
<string name="search_hint" msgid="5401750426238148416">"Busca cancións, artistas…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Está soando"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Produciuse un problema. Téntao máis tarde."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Nestes momentos non se pode facer iso"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Esta aplicación non pode facer iso"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Inicia sesión para utilizar esta aplicación"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Requírese acceso premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Estase escoitando contido en demasiados dispositivos"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ese contido está bloqueado"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Aquí non se pode acceder a ese contido"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Xa se está reproducindo ese contido"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Non se poden saltar máis pistas"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Non se puido completar a acción. Téntao de novo."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Non hai nada máis na cola"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Conectando co dispositivo multimedia"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Configuración do son"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Cambiar de aplicación"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 3cefc06..d3b29da 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"મીડિયા"</string>
<string name="search_hint" msgid="5401750426238148416">"ગીત, લેખકો અને વધુ શોધો..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"હમણાં વાગી રહ્યું છે"</string>
- <string name="default_error_message" msgid="6365377134388091079">"કંઈક ખોટું થયું. પછીથી પ્રયાસ કરો."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"તે અત્યારે કરી શકતા નથી"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"આ ઍપ તે કરી શકતી નથી"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"આ ઍપનો ઉપયોગ કરવા માટે સાઇન ઇન કરો"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"પ્રીમિયમ ઍક્સેસ જરૂરી છે"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"ઘણા બધા ડિવાઇસ પર સાંભળી રહ્યાં છે"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"તે કન્ટેન્ટ બ્લૉક કર્યું છે"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"તે કન્ટેન્ટ અહીં મેળવી શકતા નથી"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"તે કન્ટેન્ટ પહેલાંથી ચલાવી રહ્યાં છે"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"કોઈ વધુ ટ્રૅક છોડી શકતા નથી"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"સમાપ્ત કરી શક્યાં નથી. ફરી પ્રયાસ કરો."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"બીજું કંઈ કતારમાં નથી"</string>
<string name="service_notification_title" msgid="8085444675783592744">"મીડિયા સાથે કનેક્ટ કરી રહ્યાં છીએ"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"સાઉન્ડના સેટિંગ"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ઍપ સ્વિચ કરો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index d04b28d..7ab9c79 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"मीडिया"</string>
<string name="search_hint" msgid="5401750426238148416">"गाने, कलाकार वगैरह खोजें"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"अभी चल रहा है"</string>
- <string name="default_error_message" msgid="6365377134388091079">"कोई गड़बड़ी हुई. बाद में कोशिश करें."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"अभी नहीं किया जा सकता"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"इस ऐप्लिकेशन पर यह काम नहीं करेगा"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"इस ऐप्लिकेशन का इस्तेमाल करने के लिए साइन इन करें"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"इसके लिए Premium का ऐक्सेस ज़रूरी है"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"आप इसे बहुत सारे डिवाइस पर चला रहे/रही हैं"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"सामग्री पर रोक लगा दी गई है"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"वह सामग्री यहां नहीं चलाई जा सकती"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"वह सामग्री पहले से ही चल रही है"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"इससे ज़्यादा गाने नहीं छोड़े जा सकते"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"कार्रवाई पूरी नहीं हो सकी. फिर से कोशिश करें."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"कतार में और कुछ नहीं है"</string>
<string name="service_notification_title" msgid="8085444675783592744">"मीडिया स्रोत से कनेक्ट किया जा रहा है"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"आवाज़ की सेटिंग"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ऐप्लिकेशन स्विच करें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 54b23a2..7b719ce 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Mediji"</string>
<string name="search_hint" msgid="5401750426238148416">"Pretražite pjesme..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Upravo svira"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Nešto nije u redu. Pokušajte kasnije."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Trenutačno to ne možemo učiniti"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ova aplikacija nema tu mogućnost"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Prijavite se za upotrebu te aplikacije."</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Potreban je pristup uz dodatnu naplatu"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Slušate na previše uređaja"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Taj je sadržaj blokiran"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Taj sadržaj nije dostupan ovdje"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Taj se sadržaj već reproducira"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Ne možete više preskakati pjesme"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Završavanje nije uspjelo. Pokušajte ponovo."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nema više ničeg u redu čekanja"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Povezivanje s medijem"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Postavke zvuka"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Promijeni aplikaciju"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index d823bf0..279bd1d 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Média"</string>
<string name="search_hint" msgid="5401750426238148416">"Dalok, előadók és egyebek keresése…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Hiba történt. Próbálja újra később."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Jelenleg nem lehetséges"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ez az alkalmazás nem képes erre"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Az alkalmazás használatához jelentkezzen be"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Prémium hozzáférés szükséges"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Túl sok eszköz van használatban"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"A tartalom le van tiltva"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Nem lehet betölteni a tartalmat"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"A tartalom lejátszása már folyamatban van"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Nem lehet több számot átugrani"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nem sikerült befejezni. Próbálja újra."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Semmi más nincs a sorban"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Csatlakozás a médiaforráshoz"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Hangbeállítások"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Alkalmazásváltás"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 1160e26..f6e4455 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Մուլտիմեդիա"</string>
<string name="search_hint" msgid="5401750426238148416">"Որոնեք երգեր, կատարողներ և այլն…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Այժմ հնչում է"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Սխալ առաջացավ: Փորձեք ավելի ուշ։"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Այս պահին հնարավոր չէ անել դա"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Այս հավելվածը չի աջակցվում"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Մուտք գործեք՝ հավելվածն օգտագործելու համար"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Անհրաժեշտ է պրեմիում հաշիվ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Սարքերի քանակը գերազանցվել է"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Բովանդակությունն արգելափակված է"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Բովանդակությունն անհասանելի է այս տարածաշրջանում"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Բովանդակությունն արդեն նվագարկվում է"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Հնարավոր չէ այլ կատարումներ բաց թողնել"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Չհաջողվեց ավարտել: Նորից փորձեք։"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Հերթացանկի սկիզբ կամ վերջ"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Միանում է մեդիայի աղբյուրին"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Ձայնի կարգավորումներ"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Անցնել մյուս հավելված"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 7195f2d..b27cc2b 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Telusuri lagu, artis, dll..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Terjadi masalah. Coba nanti."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Tidak dapat melakukannya saat ini"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Aplikasi ini tidak dapat melakukannya"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Login untuk menggunakan aplikasi ini"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Perlu akses premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Terlalu banyak perangkat digunakan untuk mendengarkan"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Konten tersebut diblokir"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Tidak bisa mendapatkan konten tersebut di sini"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Sedang memutar konten tersebut"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Tidak dapat melewati lagu lagi"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Tidak dapat diselesaikan. Coba lagi."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Tidak ada lagi yang mengantre"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Menghubungkan ke media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Setelan Suara"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Beralih aplikasi"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 554bd44..9759532 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Efni"</string>
<string name="search_hint" msgid="5401750426238148416">"Leita að lögum, flytjendum og fleira..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Í spilun"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Eitthvað er ekki í lagi. Reyna síðar."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Ekki er hægt að framkvæma þetta eins og er"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Forritið getur ekki framkvæmt þetta"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Skráðu þig inn til að nota þetta forrit"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium-aðgangur er nauðsynlegur"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Hlustað í of mörgum tækjum"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Þetta efni er á bannlista"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Efnið er ekki tiltækt hér"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Þegar að spila þetta efni"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Ekki er hægt að sleppa fleiri lögum"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Ekki tókst að ljúka aðgerð. Reyndu aftur."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ekkert annað er í röð"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Tengist við efni"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Hljóðstillingar"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Skipta um forrit"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index a66b2e2..5eec9a5 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Contenuti multimediali"</string>
<string name="search_hint" msgid="5401750426238148416">"Cerca brani, artisti e non solo…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Si è verificato un problema. Riprova più tardi."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Al momento non è possibile svolgere l\'operazione"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Questa app non supporta l\'azione richiesta"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Accedi per usare questa app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"È necessario l\'accesso Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Ascolto attivo su troppi dispositivi"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Contenuti bloccati"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Qui non è possibile scaricare questi contenuti"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Contenuti già in riproduzione"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Impossibile saltare altre tracce"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Impossibile completare. Riprova."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nient\'altro in coda"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Connessione ai contenuti multimediali"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Impostazioni audio"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Cambia app"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index ab71498..122ff04 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"מדיה"</string>
<string name="search_hint" msgid="5401750426238148416">"חיפוש שירים, אומנים…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"מושמע עכשיו"</string>
- <string name="default_error_message" msgid="6365377134388091079">"משהו השתבש. יש לנסות מאוחר יותר."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"לא ניתן לבצע את הפעולה הזו כרגע"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"אי אפשר לבצע פעולה זו באפליקציה הזו"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"יש להיכנס לחשבון כדי להשתמש באפליקציה הזו"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"נדרשת גישה ל-Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"בהאזנה ליותר מדי מכשירים"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"התוכן הזה חסום"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"לא ניתן לקבל את התוכן הזה כאן"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"התוכן הזה כבר פועל"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"לא ניתן לדלג יותר על טראקים"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"לא ניתן היה לסיים. יש לנסות שוב."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"אין עוד שירים ברשימת השירים"</string>
<string name="service_notification_title" msgid="8085444675783592744">"מתבצעת התחברות למדיה"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"הגדרות צליל"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"מעבר בין אפליקציות"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index fd7d81b..e852ad6 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"メディア"</string>
<string name="search_hint" msgid="5401750426238148416">"曲、アーティストなどを検索..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"この曲なに?"</string>
- <string name="default_error_message" msgid="6365377134388091079">"エラーが発生しました。しばらくしてからお試しください。"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"現在、利用できません"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"このアプリではサポートされていません"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"このアプリを使用するにはログインしてください"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"プレミアム アカウントが必要です"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"再生しているデバイスが多すぎます"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"このコンテンツはブロックされています"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"このコンテンツはこの地域では再生できません"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"このコンテンツはすでに再生中です"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"これ以上トラックをスキップできません"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"完了できません。もう一度お試しください。"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"キューが一杯で追加できません"</string>
<string name="service_notification_title" msgid="8085444675783592744">"メディアに接続中"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"音声の設定"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"アプリの切り替え"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 90ad8e2..c870292 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"მედია"</string>
<string name="search_hint" msgid="5401750426238148416">"სიმღ., მუსიკოს. და ა.შ. ძიება..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"რა უკრავს"</string>
- <string name="default_error_message" msgid="6365377134388091079">"რაღაც შეცდომაა. ცადეთ მოგვიანებით."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ამჟამად ამის გაკეთება შეუძლებელია"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ეს აპი ამას ვერ გააკეთებს"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ამ აპით სარგებლობისთვის შედით სისტემაში"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"საჭიროა პრემიუმ ტიპის წვდომა"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"მოსმენა მიმდინარეობს მეტისმეტად ბევრ მოწყობილობაზე"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ეს კონტენტი დაბლოკილია"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ამ კონტენტს აქ ვერ მიიღებთ"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ეს კონტენტი უკვე იკვრება"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"მეტ ჩანაწერს ვერ გამოტოვებთ"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"დასრულება ვერ მოხერხდა. ცადეთ ხელახლა."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"რიგში აღარაფერია"</string>
<string name="service_notification_title" msgid="8085444675783592744">"მიმდინარეობს მედიასთან დაკავშირება"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ხმის პარამეტრები"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"აპების გადართვა"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 3c98b57..aef87d7 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Meдиа"</string>
<string name="search_hint" msgid="5401750426238148416">"Әнді, орындаушыны, т.б. іздеу..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Қазір ойнатылуда"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Бірдеңе дұрыс емес. Кейінірек қайталап көріңіз."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Мұны дәл қазір істеу мүмкін емес."</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Бұл қолданба мұны істей алмайды."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Осы қолданбаны пайдалану үшін есептік жазбаға кіріңіз."</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Премиум рұқсат қажет."</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Бұл мазмұн тым көп құрылғыларда тыңдалып жатыр."</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Бұл мазмұнға тыйым салынған."</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Мазмұнды алу мүмкін емес."</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Бұл мазмұн әлдеқашан ойнатылып жатыр."</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Басқа тректерді өткізіп жіберу мүмкін емес."</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Аяқталмады. Қайталап көріңіз."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Кезекке басқа ештеңе қойылмаған."</string>
<string name="service_notification_title" msgid="8085444675783592744">"Медиамазмұн көзіне жалғау"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Дыбыс параметрлері"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Қолданбалар арасында ауысу"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 70daabc..7601110 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"មេឌៀ"</string>
<string name="search_hint" msgid="5401750426238148416">"ស្វែងរកចម្រៀង សិល្បករ និងអ្វីៗជាច្រើនទៀត..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"ឥឡូវកំពុងចាក់"</string>
- <string name="default_error_message" msgid="6365377134388091079">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមនៅពេលក្រោយ។"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"មិនអាចធ្វើតាមសំណើនោះឥឡូវនេះបានទេ"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"កម្មវិធីនេះមិនអាចធ្វើតាមសំណើនោះបានទេ"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ចូលគណនី ដើម្បីប្រើកម្មវិធីនេះ"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"តម្រូវឱ្យមានការចូលប្រើលំដាប់ខ្ពស់"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"កំពុងស្ដាប់នៅលើឧបករណ៍ច្រើនពេក"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ខ្លឹមសារនោះត្រូវបានទប់ស្កាត់"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"មិនអាចទាញយកខ្លឹមសារនោះនៅទីនេះបានទេ"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"កំពុងចាក់ខ្លឹមសារនោះស្រាប់ហើយ"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"មិនអាចរំលងចម្រៀងបានទៀតទេ"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"មិនអាចបញ្ចប់បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"មិនមានអ្វីផ្សេងទៀតនៅក្នុងជួរទេ"</string>
<string name="service_notification_title" msgid="8085444675783592744">"កំពុងភ្ជាប់មេឌៀ"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ការកំណត់សំឡេង"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ប្ដូរកម្មវិធី"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 97f5067..49a150f 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"ಮಾಧ್ಯಮ"</string>
<string name="search_hint" msgid="5401750426238148416">"ಹಾಡು, ಕಲಾವಿದರು, ಇನ್ನಷ್ಟು ಹುಡುಕಿ..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ನಂತರ ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ಸದ್ಯಕ್ಕೆ ಅದನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ಈ ಆ್ಯಪ್ನಿಂದ ಅದನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ಈ ಆ್ಯಪ್ ಬಳಸಲು ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ಪ್ರೀಮಿಯಂ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"ಹಲವಾರು ಸಾಧನಗಳಲ್ಲಿ ಆಲಿಸಲಾಗುತ್ತಿದೆ"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ವಿಷಯವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ಆ ವಿಷಯವನ್ನು ಇಲ್ಲಿ ಪಡೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ಈಗಾಗಲೇ ಆ ವಿಷಯವನ್ನು ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ಇನ್ನು ಮುಂದೆ ಟ್ರ್ಯಾಕ್ಗಳನ್ನು ಸ್ಕಿಪ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"ಪೂರ್ಣಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"ಸರದಿಯಲ್ಲಿ ಯಾವುದು ಬಾಕಿ ಉಳಿದಿಲ್ಲ"</string>
<string name="service_notification_title" msgid="8085444675783592744">"ಮೀಡಿಯಾಕ್ಕೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ಧ್ವನಿ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಿಸಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 104f8cc..e5ed5a6 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"미디어"</string>
<string name="search_hint" msgid="5401750426238148416">"노래, 아티스트 등을 검색하세요..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"지금 재생 중"</string>
- <string name="default_error_message" msgid="6365377134388091079">"문제가 발생했습니다. 나중에 다시 시도하세요."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"지금은 요청하신 작업을 할 수 없습니다."</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"이 앱에서는 요청하신 작업을 지원하지 않습니다."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"이 앱을 사용하려면 로그인하세요."</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"프리미엄 액세스 권한이 필요합니다."</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"너무 많은 기기에서 스트리밍하고 있습니다."</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"차단된 콘텐츠입니다."</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"이 지역에서 재생할 수 없는 콘텐츠입니다."</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"요청하신 콘텐츠를 이미 재생 중입니다."</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"트랙을 더이상 건너뛸 수 없습니다."</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"완료할 수 없습니다. 다시 시도하세요."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"현재 재생목록이 비어있습니다."</string>
<string name="service_notification_title" msgid="8085444675783592744">"미디어에 연결 중"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"소리 설정"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"앱 전환"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 493acdc..b9801ec 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Медиа"</string>
<string name="search_hint" msgid="5401750426238148416">"Ырларды, аткаруучуларды издөө ж.б..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Эмне ойноп жатат?"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Бир жерден ката кетти. Бир аздан кийин кайталап көрүңүз."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Аны азыр аткаруу мүмкүн эмес"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Бул колдонмо аны аткара албайт"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Бул колдонмону пайдалануу үчүн аккаунтуңузга кириңиз"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Артыкчылыктуу кирүү мүмкүнчүлүгү талап кылынат"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Өтө көп түзмөк угулууда"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ал мазмун бөгөттөлгөн"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Ал мазмунду алуу мүмкүн эмес"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ал мазмун ойнотулууда"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Эми тректерди өткөрүп жиберүүгө болбойт"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Аягына чыккан жок. Кайталап көрүңүз."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Кезекте эч нерсе жок"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Медиа булагына туташууда"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Добуштун жөндөөлөрү"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Колдонмолорду которуштуруу"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 8abc6f9..1ad1ed4 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"ສື່"</string>
<string name="search_hint" msgid="5401750426238148416">"ຊອກຫາເພງ, ສິນລະປິນ ແລະ ອື່ນໆອີກ..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"ມີບ່າງຢ່າງຜິດພາດ. ລອງໃໝ່ພາຍຫຼັງ."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ບໍ່ສາມາດເຮັດໄດ້ຕອນນີ້"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ແອັບນີ້ບໍ່ສາມາດເຮັດສິ່ງນັ້ນໄດ້"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ເຂົ້າສູ່ລະບົບເພື່ອໃຊ້ແອັບນີ້"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ຕ້ອງມີສິດເຂົ້າເຖິງລະດັບພຣີມຽມ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"ກຳລັງຟັງຢູ່ໃນຫຼາຍອຸປະກອນເກີນໄປ"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ເນື້ອຫານັ້ນຖືກບລັອກໄວ້"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ບໍ່ສາມາດຮັບເນື້ອຫານັ້ນຢູ່ບ່ອນນີ້"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ຫຼິ້ນເນື້ອຫານັ້ນແລ້ວ"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ຂ້າມເພງບໍ່ໄດ້ອີກແລ້ວ"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"ບໍ່ສາມາດສຳເລັດໄດ້. ລອງໃໝ່."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"ບໍ່ມີລາຍການອື່ນໃນຄິວ"</string>
<string name="service_notification_title" msgid="8085444675783592744">"ກຳລັງເຊື່ອມຕໍ່ກັບສື່"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ການຕັ້ງຄ່າສຽງ"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ສະຫຼັບແອັບ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 30c3aff..783d241 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Medija"</string>
<string name="search_hint" msgid="5401750426238148416">"Ieškokite dainų, atlikėjų ir daugiau..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Dabar leidžiama"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Kažkas nepavyko. Bandykite vėliau."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Negalima atlikti to veiksmo dabar"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ši programa negali atlikti to veiksmo"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Prisijunkite, kad galėtumėte naudoti šią programą"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Būtina mokama prieiga"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Klausoma naudojant per daug įrenginių"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Tas turinys užblokuotas"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Negalima gauti to turinio čia"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Tas turinys jau leidžiamas"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Daugiau takelių praleisti nebegalima"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nepavyko užbaigti. Bandykite dar kartą."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Eilėje nieko nebėra"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Prisijungiama prie medijos"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Garso nustatymai"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Perjungti programas"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 7a25cd3..f542298 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Multivide"</string>
<string name="search_hint" msgid="5401750426238148416">"Meklēt dziesmas u.c."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Tagad atskaņo"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Radās problēma. Mēģiniet vēlāk."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Pašlaik nevar veikt šo darbību."</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Šo darbību nevar veikt šajā lietotnē."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Pierakstieties, lai izmantotu šo lietotni."</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Nepieciešama maksas piekļuve"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Klausīšanās notiek pārāk daudz ierīcēs."</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Šis saturs ir bloķēts."</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Nevar šeit parādīt šo saturu."</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Šis saturs jau tiek atskaņots."</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Vairs nevar izlaist nevienu ierakstu."</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nevarēja pabeigt. Mēģiniet vēlreiz."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Rindā vairs nav nekā cita."</string>
<string name="service_notification_title" msgid="8085444675783592744">"Notiek savienojuma izveide ar multivides avotu"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Skaņas iestatījumi"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Pārslēgt lietotnes"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 2fd3aca..923dc72 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Аудиовизуелни содржини"</string>
<string name="search_hint" msgid="5401750426238148416">"Пребарувај песни, изведувачи и друго…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Нешто не е во ред. Обидете се подоцна."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Не може да се направи тоа во моментов"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Апликацијава не може да го направи тоа"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Најавете се за да ја користите апликацијава"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Потребен е пристап со Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Се слуша на премногу уреди"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Таа содржина е блокирана"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Не може да се добие таа содржина тука"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Веќе е пуштена таа содржина"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Не може да прескокне повеќе песни"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Не може да заврши. Обидете се повторно."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Веќе ништо не чека на ред"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Се поврзува со аудиовизуелниот извор"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Поставки за звукот"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Променете ја апликацијата"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index b6337b1..84f293e 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"മീഡിയ"</string>
<string name="search_hint" msgid="5401750426238148416">"പാട്ടും ആർട്ടിസ്റ്റും മറ്റും തിരയൂ..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"ഇപ്പോൾ കേൾക്കുന്നത്"</string>
- <string name="default_error_message" msgid="6365377134388091079">"എന്തോ കുഴപ്പം സംഭവിച്ചു. പിന്നീട് ശ്രമിക്കുക."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"അത് ഇപ്പോൾ ചെയ്യാനാവില്ല"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ഈ ആപ്പിന് അത് ചെയ്യാനാവില്ല"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ഈ ആപ്പ് ഉപയോഗിക്കാൻ സെെൻ ഇൻ ചെയ്യുക"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"പ്രീമിയം ആക്സസ് ആവശ്യമാണ്"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"നിരവധി ഉപകരണങ്ങളിൽ കേൾക്കുന്നു"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ആ ഉള്ളടക്കം ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ആ ഉള്ളടക്കം ഇവിടെ ലഭിക്കില്ല"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ആ ഉള്ളടക്കം നിലവിൽ പ്ലേ ചെയ്യുകയാണ്"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ഇനിയും ട്രാക്കുകൾ ഒഴിവാക്കാനാവില്ല"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"പൂർത്തിയാക്കാനായില്ല. വീണ്ടും ശ്രമിക്കൂ."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"ഒന്നും ക്യൂവിലില്ല"</string>
<string name="service_notification_title" msgid="8085444675783592744">"മീഡിയയിലേക്ക് കണക്റ്റ് ചെയ്യുന്നു"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ശബ്ദ ക്രമീകരണം"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ആപ്പുകൾ മാറുക"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 46fd785..31dce33 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Медиа"</string>
<string name="search_hint" msgid="5401750426238148416">"Дуу, уран бүтээлчид болон бусад зүйлийг хайх..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Ямар нэг асуудал гарлаа. Дараа оролдоно уу."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Яг одоо үүнийг хийх боломжгүй"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Энэ аппаар үүнийг хийх боломжгүй"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Энэ аппыг ашиглахын тулд нэвтэрнэ үү"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium хандалт шаардлагатай"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Хэт олон төхөөрөмж сонсож байна"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ийм контентыг блоклодог"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Ийм контентыг энд авах боломжгүй"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ийм контентыг аль хэдийн тоглуулж байна"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Бичлэг дахин алгасах боломжгүй"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Дуусгаж чадсангүй. Дахин оролдоно уу."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Дууны жагсаалтад юу ч алга"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Медиад холбогдож байна"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Дууны тохиргоо"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Аппуудыг сэлгэх"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index ecf7592..2c497b1 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"मीडिया"</string>
<string name="search_hint" msgid="5401750426238148416">"गाणी, कलाकार व बरेच शोधा…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"काहीतरी चूकले. नंतर प्रयत्न करा."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ते याक्षणी केले जाऊ शकत नाही"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"हे ॲप ते करू शकत नाही"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"हे अॅप वापरण्यासाठी साइन इन करा"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"प्रीमियम ॲक्सेस आवश्यक आहे"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"अनेक डिव्हाइसवर ऐकत आहे"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"तो आशय ब्लॉक केलेला आहे"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"तो आशय येथे आणू शकत नाही"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"तो आधीच आशय प्ले केला जात आहे"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"आणखी ट्रॅक वगळू शकत नाही"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"पूर्ण करता आले नाही. पुन्हा प्रयत्न करा."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"इतर काहीही क्यू केलेले नाही"</string>
<string name="service_notification_title" msgid="8085444675783592744">"मीडियाशी कनेक्ट करत आहे"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"आवाजाची सेटिंग्ज"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"अॅप्स स्विच करा"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 3dae631..16e2f2b 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Cari lagu, artis dll..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Ada yang tidak kena. Cuba nanti."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Tidak dapat berbuat demikian sekarang"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Apl ini tidak dapat berbuat demikian"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Log masuk untuk menggunakan apl ini"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Akses premium diperlukan"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Mendengar pada terlalu banyak peranti"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Kandungan itu disekat"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Tidak boleh mendapatkan kandungan itu di sini"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Sudah pun memainkan kandungan itu"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Tidak boleh melangkau sebarang lagu lagi"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Tidak dapat diselesaikan. Cuba lagi."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Tiada lagu lain dalam baris gilir"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Menyambung ke media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Tetapan Bunyi"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Tukar apl"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index fef3e1f..9b312d2 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"မီဒီယာ"</string>
<string name="search_hint" msgid="5401750426238148416">"အရာများစွာ ရှာပါ..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"ယခု ဖွင့်နေသည်"</string>
- <string name="default_error_message" msgid="6365377134388091079">"တစ်ခုခု မှားနေသည်။ နောက်မှ စမ်းကြည့်ပါ။"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"၎င်းကို ယခု မပြုလုပ်နိုင်ပါ"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ဤအက်ပ်က ၎င်းကို မပြုလုပ်နိုင်ပါ"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ဤအက်ပ်အသုံးပြုရန် လက်မှတ်ထိုးဝင်ပါ"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ပရီမီယံ အသုံးပြုခွင့် လိုအပ်သည်"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"စက်ပစ္စည်းအများအပြားတွင် နားထောင်နေသည်"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ထိုအကြောင်းအရာကို ပိတ်ထားသည်"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ထိုအကြောင်းအရာကို ဤနေရာတွင် မရရှိနိုင်ပါ"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ထိုအကြောင်းအရာကို ဖွင့်နေပြီဖြစ်သည်"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"နောက်ထပ်သီချင်းပုဒ်များ ကျော်၍မရတော့ပါ"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"အပြီးသတ်၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"အခြားစီထားသည်များ မရှိပါ"</string>
<string name="service_notification_title" msgid="8085444675783592744">"မီဒီယာသို့ ချိတ်ဆက်ခြင်း"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"အသံဆက်တင်များ"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"အက်ပ်များပြောင်းခြင်း"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 78a470c..9af65d5 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Medier"</string>
<string name="search_hint" msgid="5401750426238148416">"Søk etter sanger, artister med mer"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Spilles nå"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Noe gikk galt. Prøv senere."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Du kan ikke gjøre det akkurat nå"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Denne appen kan ikke gjøre det"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Logg på for å bruke denne appen"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premiumtilgang kreves"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Du lytter på for mange enheter"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Innholdet er blokkert"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Innholdet er ikke tilgjengelig her"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Du spiller allerede av innholdet"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Kan ikke hoppe over flere spor"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Kunne ikke fullføre. Prøv igjen."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ingenting annet står i køen"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Kobler til media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Lydinnstillinger"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Bytt app"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index aa135bb..9be29f5 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"मिडिया"</string>
<string name="search_hint" msgid="5401750426238148416">"गीत, कलाकार र थप खोज्नु…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"अहिले प्ले भइरहेको"</string>
- <string name="default_error_message" msgid="6365377134388091079">"केही चिज गडबड छ। पछि प्रयास गर्नुहोस्।"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"त्यो कार्य अहिले नै गर्न सकिँदैन"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"यो एपले त्यो कार्य गर्न सक्दैन"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"यो एप प्रयोग गर्न साइन इन गर्नुहोस्"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"प्रिमियममाथिको पहुँच आवश्यक छ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"अत्यधिक यन्त्रहरूमा सुन्दै"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"त्यो सामग्रीमाथि रोक लगाइएको छ"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"त्यो सामग्री यहाँ प्राप्त गर्न सकिँदैन"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"त्यो सामग्री पहिलेदेखि नै प्ले भइरहेको छ"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"कुनै पनि थप ट्रयाकहरू छाड्न सकिँदैन"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"समाप्त गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"यसदेखि बाहेक केही पङ्क्तिबद्ध गरिएको छैन"</string>
<string name="service_notification_title" msgid="8085444675783592744">"मिडियामा जोड्दै"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ध्वनिसम्बन्धी सेटिङ"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"एउटा एपबाट अर्को एपमा जानुहोस्"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 3af6ffa..c282851 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Zoek nummers, artiesten en meer..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Er is iets misgegaan. Probeer het later opnieuw."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Kan dat nu niet doen"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Deze app kan dat niet doen"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Log in om deze app te gebruiken"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium-toegang vereist"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Er wordt op te veel apparaten geluisterd"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Die content is geblokkeerd"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Kan die content hier niet krijgen"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Die content wordt al afgespeeld"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Kan geen tracks meer overslaan"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Kan niet voltooien. Probeer het opnieuw."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Er staat niets anders in de wachtrij"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Verbinden met media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Geluidsinstellingen"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Schakelen tussen apps"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 664cc65..97b029d 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"ମିଡିଆ"</string>
<string name="search_hint" msgid="5401750426238148416">"ଗୀତ, କଳାକାର, ଏବଂ ଅନେକ ସନ୍ଧାନ କରନ୍ତୁ..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"ଏବେ ଚାଲୁଅଛି"</string>
- <string name="default_error_message" msgid="6365377134388091079">"କିଛି ସମସ୍ୟା ଅଛି। ପରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ବର୍ତ୍ତମାନ ତାହା କରିପାରିବ ନାହିଁ"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ଏହି ଆପ୍ ତାହା କରିପାରିବ ନାହିଁ"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ଏହି ଆପ୍ ବ୍ୟବହାର କରିବାକୁ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ପ୍ରିମିୟମ୍ ଆକ୍ସେସ୍ର ଆବଶ୍ୟକ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"ଅନେକ ଡିଭାଇସ୍ରେ ଶୁଣାଯାଉଛି"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ସେହି ବିଷୟବସ୍ତୁ ବ୍ଲକ୍ କରାଯାଇଛି"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ଏଠାରେ ସେହି ବିଷୟବସ୍ତୁ ପାଇବେ ନାହିଁ"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ପୂର୍ବରୁ ସେହି ବିଷୟବସ୍ତୁ ଖେଳାଯାଉଛି"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ଅଧିକ ଟ୍ରାକ୍ ବାଦ୍ ଦେଇପାରିବ ନାହିଁ"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"ସମାପ୍ତ କରାଯାଇ ପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"ଅନୁକ୍ରମରେ ଆଉ କିଛି ନାହିଁ"</string>
<string name="service_notification_title" msgid="8085444675783592744">"ମିଡ଼ିଆ ସହ ସଂଯୋଗ ହେଉଛି"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ସାଉଣ୍ଡ ସେଟିଂସ୍"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ଆପଗୁଡ଼ିକୁ ବଦଳାନ୍ତୁ"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 019ae5d..80105f6 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"ਮੀਡੀਆ"</string>
<string name="search_hint" msgid="5401750426238148416">"ਗੀਤ, ਕਲਾਕਾਰ ਖੋਜੋ, ਹੋਰ"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"ਹੁਣੇ ਚੱਲ ਰਿਹਾ ਹੈ"</string>
- <string name="default_error_message" msgid="6365377134388091079">"ਕੋਈ ਗੜਬੜ ਹੈ। ਬਾਅਦ ਵਿੱਚ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ਫਿਲਹਾਲ ਇਹ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ਇਹ ਐਪ ਇਹ ਨਹੀਂ ਕਰ ਸਕਦੀ"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ਇਸ ਐਪ ਨੂੰ ਵਰਤਣ ਲਈ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ਪ੍ਰੀਮੀਅਮ ਪਹੁੰਚ ਦੀ ਲੋੜ ਹੈ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਡੀਵਾਈਸਾਂ \'ਤੇ ਸੁਣਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ਇੱਥੇ ਇਹ ਸਮੱਗਰੀ ਨਹੀਂ ਮਿਲ ਸਕਦੀ"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ਇਹ ਸਮੱਗਰੀ ਪਹਿਲਾਂ ਹੀ ਚੱਲ ਰਹੀ ਹੈ"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ਕਿਸੇ ਹੋਰ ਟਰੈਕ ਨੂੰ ਛੱਡਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"ਪੂਰਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"ਹੋਰ ਕੁਝ ਵੀ ਕਤਾਰਬੱਧ ਨਹੀਂ ਹੈ"</string>
<string name="service_notification_title" msgid="8085444675783592744">"ਮੀਡੀਆ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ਧੁਨੀ ਸੈਟਿੰਗਾਂ"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 1b901ba..6a1d293 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Multimedia"</string>
<string name="search_hint" msgid="5401750426238148416">"Np. utwór lub wykonawca"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Teraz odtwarzane"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Coś poszło nie tak. Spróbuj później."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Teraz nie można tego zrobić"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Wybrana aplikacja nie ma takiej funkcji"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Zaloguj się, by używać tej aplikacji"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Wymagany jest dostęp na poziomie premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Słuchasz zbyt wielu urządzeń"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Te materiały są zablokowane"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Te materiały są niedostępne w tym regionie"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Te materiały są już odtwarzane"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Nie można pominąć większej liczby utworów"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nie udało się dokończyć. Spróbuj ponownie."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nie ma już nic w kolejce"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Łączenie z multimediami"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Ustawienia dźwięku"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Przełącz aplikacje"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 7a178a9..80e8898 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Multimédia"</string>
<string name="search_hint" msgid="5401750426238148416">"Pesquise músicas, artistas e mais…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"A tocar"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Ocorreu um problema. Tente mais tarde."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Não é possível responder a esse pedido neste momento."</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Esta aplicação não consegue responder a esse pedido."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Inicie sessão para utilizar esta aplicação."</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Acesso premium necessário."</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"A ouvir em demasiados dispositivos."</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Esse conteúdo está bloqueado."</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Não é possível obter esse conteúdo aqui."</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Esse conteúdo já está em reprodução."</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Não é possível ignorar mais faixas."</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Não foi possível terminar. Tente novamente."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Não existem mais elementos em fila."</string>
<string name="service_notification_title" msgid="8085444675783592744">"A ligar à fonte multimédia…"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Definições de som"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Mudar de app"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 6784ad9..06ce15d 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Mídia"</string>
<string name="search_hint" msgid="5401750426238148416">"Pesq. músicas e mais"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Tocando agora"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Algo deu errado. Tente mais tarde."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Não é possível fazer isso no momento"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Não é possível fazer isso com este app"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Faça login para usar este app"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"É necessário ter acesso Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Ouvindo em muitos dispositivos"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Esse conteúdo está bloqueado"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Não é possível usar esse conteúdo aqui"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Esse conteúdo já está tocando"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Não é possível pular mais faixas"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Não foi possível concluir. Tente novamente."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Não há mais nada na fila"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Conectando à mídia"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Configurações de som"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Trocar de app"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index bbb8a83..320ca23 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Căutați cântece, artiști și altele…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Se redă acum"</string>
- <string name="default_error_message" msgid="6365377134388091079">"A apărut o problemă. Încercați mai târziu."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Acțiunea nu poate fi realizată momentan"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Aplicația nu poate realiza această acțiune"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Conectați-vă pentru a folosi aplicația"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Este necesar accesul premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Se ascultă prea multe dispozitive"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Conținutul este blocat"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Conținutul nu poate fi descărcat aici"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Conținutul se redă deja"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Nu mai pot fi omise melodii"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nu s-a putut finaliza. Încercați din nou."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Nu mai există elemente în coadă"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Se conectează la conținutul media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Setări pentru sunet"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Comutați între aplicații"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 3e8c860..22faade 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Мультимедиа"</string>
<string name="search_hint" msgid="5401750426238148416">"Песня, исполнитель…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Сейчас играет"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Ошибка. Повторите попытку позже."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Невозможно выполнить действие в данный момент."</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Действие недоступно в этом приложении."</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Чтобы использовать это приложение, войдите в аккаунт."</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Требуется премиум-доступ."</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Слишком много устройств, на которых воспроизводится аудио."</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Контент заблокирован."</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Контент недоступен в вашем регионе."</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Этот контент уже воспроизводится."</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Пропускать треки больше нельзя."</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Произошла ошибка. Повторите попытку."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"В очереди воспроизведения нет других файлов."</string>
<string name="service_notification_title" msgid="8085444675783592744">"Подключение к источнику медиаконтента"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Настройки звука"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Переключение приложений"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index dad503c..3856a35 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"මාධ්ය"</string>
<string name="search_hint" msgid="5401750426238148416">"ගීත, කලාකරුවන් සහ තවත් දේ සොයන්න..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"දැන් වාදනය වේ"</string>
- <string name="default_error_message" msgid="6365377134388091079">"යම් දෙයක් වැරදියි. පසුව උත්සාහ කරන්න."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"දැන් එය කළ නොහැක"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"මෙම යෙදුමට එය කළ නොහැක"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"මෙම යෙදුම භාවිත කිරීමට පුරන්න"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"පාරිතෝෂික ප්රවේශය අවශ්යයි"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"ඕනෑවට වඩා උපාංග මත සවන් දීම"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"එම අන්තර්ගතය අවහිර කර ඇත"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"එම අන්තර්ගතය මෙතැනින් ලබා ගත නොහැක"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"දැනටමත් එම අන්තර්ගතය වාදනය කරයි"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"තවත් ඛණ්ඩ මඟ හැරිය නොහැක"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"අවසන් කිරීමට නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"වෙන කිසිවක් පෝලිමේ නැත"</string>
<string name="service_notification_title" msgid="8085444675783592744">"මාධ්ය වෙත සබැඳීම"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ශබ්ද සැකසීම්"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"යෙදුම් මාරු කරන්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 63fa1ca..e878ec4 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Médiá"</string>
<string name="search_hint" msgid="5401750426238148416">"Hľadať skladby, interpretov a ďalší obsah…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Čo to hrá"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Vyskytol sa problém. Skúste to znova."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Teraz to nie je možné"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Táto aplikácia to nedokáže"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Ak chcete použiť túto aplikáciu, prihláste sa"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Vyžaduje sa prémiový prístup"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Počúva sa na príliš veľa zariadeniach"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Daný obsah je blokovaný"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Daný obsah tu nie je k dispozícii"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Tento obsah sa už prehráva"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Nie je možné preskočiť žiadne ďalšie stopy"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Akciu sa nepodarilo dokončiť. Skúste to znova."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Poradie je prázdne"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Pripája sa k médiu"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Nastavenia zvuku"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Prepnúť aplikácie"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 390c0b9..d9fc471 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Predstavnost"</string>
<string name="search_hint" msgid="5401750426238148416">"Poiščite skladbe, izvajalce in drugo"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Zdaj se predvaja"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Prišlo je do težave. Poskusite pozneje."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Trenutno to ni izvedljivo"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ta aplikacija ne more izvesti tega"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Prijavite se, če želite uporabljati to aplikacijo"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Potrebujete plačljiv dostop"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Poslušanje v preveč napravah"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Ta vsebina je blokirana"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Te vsebine tukaj ni mogoče pridobiti"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ta vsebina se že predvaja"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Dosegli ste omejitev preskakovanja skladb"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Ni bilo mogoče dokončati. Poskusite znova."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Čakalna vrsta je prazna"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Povezovanje s predstavnostjo"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Nastavitve zvoka"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Preklop aplikacij"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index f2acebf..6fd862d 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Kërko për këngët, artistët etj..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Po luhet tani"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Ndodhi një gabim. Provo më vonë."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Këtë nuk mund ta bësh në këtë moment"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ky aplikacion nuk mund ta bëjë këtë"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Identifikohu për të përdorur këtë aplikacion"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Kërkohet qasje Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Po dëgjon në shumë pajisje"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Kjo përmbajtje është bllokuar"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Ajo përmbajtje nuk mund të merret këtu"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Ajo përmbajtje po luhet tashmë"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Nuk mund të kapërcejë këngë të tjera"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Nuk mundi të përfundojë. Provo sërish."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Asgjë tjetër nuk është në radhë"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Po lidhet me median"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Cilësimet e zërit"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Ndërro aplikaconet"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index ba42c4b..712eec5 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Медији"</string>
<string name="search_hint" msgid="5401750426238148416">"Тражите песме, извођаче и друго..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Тренутно свира"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Нешто није у реду. Пробајте касније."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Тренутно не може то да уради"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ова апликација не може то да уради"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Пријавите се да бисте користили ову апликацију"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Потребан је премијум приступ"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Слушате на превише уређаја"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Тај садржај је блокиран"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Не можете да добијете тај садржај овде"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Тај садржај се већ репродукује"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Не можете више да прескачете песме"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Нисмо успели да довршимо радњу. Пробајте поново."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ништа друго није стављено у ред"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Повезује се са медијима"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Подешавања звука"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Пређи на другу апликацију"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 822c7a2..6a421f1 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Sök låt, artist m.m."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Nu spelas"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Något är fel. Försök igen senare."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Det går inte just nu"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Det går inte med den här appen"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Logga in om du vill använda appen"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium-konto krävs"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"För många enheter streamas"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Det innehållet har blockerats"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Det innehållet är inte tillgängligt här"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Det innehållet spelas redan"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Det går inte att hoppa över fler låtar"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Det gick inte att slutföra. Försök igen."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Inget annat har lagts i uppspelningskön"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Ansluter till mediakälla"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Ljudinställningar"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Byt app"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 4bde052..7161ca6 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Maudhui"</string>
<string name="search_hint" msgid="5401750426238148416">"Tafuta nyimbo, wasanii na zaidi..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Inayocheza Sasa"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Hitilafu fulani imetokea. Jaribu baadaye."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Imeshindwa kufanya hivyo kwa sasa"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Programu hii imeshindwa kutekeleza ombi lako"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Ingia katika akaunti ili utumie programu hii"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Unahitaji kutumia akaunti ya Kulipia"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Unasikiliza kwenye vifaa vingi mno"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Maudhui haya yamezuiwa"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Imeshindwa kupata maudhui haya hapa"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Tayari inacheza maudhui hayo"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Imeshindwa kuruka nyimbo nyingine zaidi"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Imeshindwa kumaliza. Jaribu tena."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Hakuna maudhui mengine kwenye foleni"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Inaunganisha kwenye chanzo cha maudhui"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Mipangilio ya Sauti"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Badilisha programu"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index eb44d81..831b91f 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"மீடியா"</string>
<string name="search_hint" msgid="5401750426238148416">"பாடல், கலைஞர் தேடல்"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"பாடல் விவரம்"</string>
- <string name="default_error_message" msgid="6365377134388091079">"ஏதோ தவறாகிவிட்டது. பிறகு முயலவும்."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"தற்சமயம் இதை செய்ய இயலாது"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"இந்த ஆப்ஸ் ஆதரிக்கவில்லை"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"இந்த ஆப்ஸை உபயோகிக்க உள்நுழைய வேண்டும்"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium அணுகல் தேவை"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"பல்வேறு சாதனங்களைக் கவனிக்கிறது"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"இது தடுக்கப்பட்டுள்ளது"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"அதை இங்குப் பெற முடியவில்லை"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ஏற்கெனவே அதைப் பிளே செய்து கொண்டிருக்கிறது"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"இதற்கு மேல் டிராக்குகளைத் தவிர்க்க முடியாது"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"நிறைவடையவில்லை. மீண்டும் முயலவும்."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"வேறு எதுவும் வரிசையில் இல்லை"</string>
<string name="service_notification_title" msgid="8085444675783592744">"மீடியாவுடன் இணைக்கிறது"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ஒலி அமைப்புகள்"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ஆப்ஸை மாற்றுவதற்கான பட்டன்"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 5c5180a..14cd0f4 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"మీడియా"</string>
<string name="search_hint" msgid="5401750426238148416">"పాటలు, కళాకారులు, మరిన్నింటిని వెతకండి..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"ప్రస్తుతం ప్లే అవుతున్నవి"</string>
- <string name="default_error_message" msgid="6365377134388091079">"ఏదో తప్పుగా ఉంది. తర్వాత ప్రయత్నించండి."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"దాన్ని ఇప్పుడే చేయడం సాధ్యపడదు"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"ఈ యాప్ దాన్ని చేయలేదు"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ఈ యాప్ను ఉపయోగించడానికి సైన్ ఇన్ చేయండి"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ప్రీమియం యాక్సెస్ అవసరం"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"చాలా ఎక్కువ పరికరాలలో వింటున్నారు"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"ఆ కంటెంట్ బ్లాక్ చేయబడింది"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"ఆ కంటెంట్ను ఇక్కడ పొందడం సాధ్యపడదు"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"ఇప్పటికే ఆ కంటెంట్ ప్లే అవుతోంది"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ఇక ఏ ట్రాక్లనూ దాటవేయడం సాధ్యపడదు"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"పూర్తి చేయడం సాధ్యపడలేదు. మళ్ళీ ప్రయత్నించండి."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"వరుసలో ఏమీ లేదు"</string>
<string name="service_notification_title" msgid="8085444675783592744">"మీడియాకు కనెక్ట్ చేస్తోంది"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"ధ్వని సెట్టింగ్లు"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"యాప్లను మార్చాలా?"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 928128b..dad42e0 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"สื่อ"</string>
<string name="search_hint" msgid="5401750426238148416">"ค้นหาเพลง ศิลปิน และอื่นๆ..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"กำลังเล่น"</string>
- <string name="default_error_message" msgid="6365377134388091079">"มีข้อผิดพลาดเกิดขึ้น ลองอีกครั้งในภายหลัง"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ดำเนินการดังกล่าวไม่ได้ในขณะนี้"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"แอปนี้ดำเนินการดังกล่าวไม่ได้"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"ลงชื่อเข้าใช้เพื่อใช้แอปนี้"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"ต้องมีสิทธิ์เข้าถึงระดับพรีเมียม"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"กำลังเปิดฟังจากหลายอุปกรณ์เกินไป"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"เนื้อหาดังกล่าวถูกบล็อก"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"เปิดเนื้อหาดังกล่าวไม่ได้ที่นี่"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"กำลังเล่นเนื้อหาดังกล่าวอยู่แล้ว"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"ข้ามแทร็กอื่นอีกไม่ได้แล้ว"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"ดำเนินการไม่สำเร็จ ลองอีกครั้ง"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"ไม่มีรายการอื่นในคิว"</string>
<string name="service_notification_title" msgid="8085444675783592744">"กำลังเชื่อมต่อสื่อ"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"การตั้งค่าเสียง"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"เปลี่ยนแอป"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 5adf3ce..7be88a4 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Maghanap ng kanta, artist, atbp..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Nagpi-play Ngayon"</string>
- <string name="default_error_message" msgid="6365377134388091079">"May problema. Subukan sa ibang pagkakataon."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Hindi iyon magagawa ngayon"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Hindi iyon magagawa ng app na ito"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Mag-sign in para gamitin ang app na ito"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Kailangan ng premium na access"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Nakikinig sa masyadong maraming device"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Naka-block ang content na iyon"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Hindi makukuha ang content na iyon dito"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Pine-play na ang content na iyon"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Hindi na malalaktawan ang higit pang track"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Hindi matapos. Subukan ulit."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Wala nang naka-queue"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Kumokonekta sa media"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Mga Setting ng Tunog"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Lumipat ng app"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 97b0edf..77d821b 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Medya"</string>
<string name="search_hint" msgid="5401750426238148416">"Şarkı vs. arayın..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Ne Çalıyor?"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Bir şeyler ters gitti. Daha sonra tekrar deneyin."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"İşlem şu anda gerçekleştirilemiyor"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Uygulama bu işlemi gerçekleştiremiyor"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Bu uygulamayı kullanmak için oturum açın"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Premium erişim gerekli"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Çok fazla cihazda dinleme yapılıyor"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Bu içerik engellendi"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"İçeriğe buradan erişilemiyor"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Bu içerik zaten oynatılıyor"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Daha fazla parça atlanamıyor"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Tamamlanamadı. Tekrar deneyin."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Sıraya eklenmiş başka bir şey yok"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Medyaya bağlanma"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Ses Ayarları"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Uygulama değiştir"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 48847cc..a732592 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Медіа"</string>
<string name="search_hint" msgid="5401750426238148416">"Пошук пісень, виконавців тощо…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Зараз грає"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Сталася помилка. Повторіть спробу пізніше."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Зараз неможливо виконати запит"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Додаток не підтримує цю дію"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Увійдіть, щоб використовувати цей додаток"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Потрібна підписка Premium"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Для прослуховування використовується забагато пристроїв"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Цей вміст заблоковано"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Цей вміст недоступний у вашій країні"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Цей вміст уже відтворюється"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Неможливо пропустити більше композицій"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Не вдалося закінчити. Повторіть спробу."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Черга порожня"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Підключення до джерела медіавмісту"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Налаштування звуку"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Змінити додаток"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index af82518..073a76f 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"میڈیا"</string>
<string name="search_hint" msgid="5401750426238148416">"گانے، فنکاران، اور مزید تلاش کریں..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Now Playing"</string>
- <string name="default_error_message" msgid="6365377134388091079">"کچھ غلط ہو گیا۔ بعد میں کوشش کریں۔"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"ابھی وہ ایسا نہیں کر سکتا"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"یہ ایپ ایسا نہیں کر سکتا"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"اس ایپ کا استعمال کرنے کے لیے سائن ان کریں"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"پریمیم رسائی درکار ہے"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"بہت سے آلات پر سننا"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"وہ مواد مسدود ہے"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"یہاں وہ مواد حاصل نہیں کر سکتے"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"وہ مواد پہلے سے ہی چلایا جارہا ہے"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"مزید کسی اور ٹریکس کو نظر انداز نہیں کر سکتے"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"پورا نہیں ہو سکا۔ پھر آزمائيں۔"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"مزید کچھ اور کی قطار نہیں ہے"</string>
<string name="service_notification_title" msgid="8085444675783592744">"میڈیا سے منسلک ہو رہا ہے"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"آواز کی ترتیبات"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"ایپس پر سوئچ کریں"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 02afdce..555efb3 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Media"</string>
<string name="search_hint" msgid="5401750426238148416">"Musiqa qidiruvi..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Ijro qilinmoqda"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Nimadir xato ketdi Keyinroq qayta urining."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Buni hozir amalga oshira olmaydi"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Bu ilova bu amalni bajara olmaydi"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Bu ilovadan foydalanish uchun hisobingizga kiring"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Ishonchli ruxsat kerak"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Koʻplab qurilmalar tinglanmoqda"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Bu kontent bloklangan"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Bu kontentni bu yerga olish imkonsiz"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Bu kontent allaqachon ijro etilmoqda"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Boshqa treklarni qoldirib ketish imkonsiz"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Tugallanmadi. Qaytadan urining."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Ijro navbatida boshqa fayllar mavjud emas"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Media manbaga ulanish"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Tovush sozlamalari"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Ilovalarni almashtirish"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index beb9518..9727d99 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Nội dung nghe nhìn"</string>
<string name="search_hint" msgid="5401750426238148416">"Tìm bài hát, nghệ sĩ, v.v."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Phát hiện nhạc"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Đã xảy ra lỗi. Hãy thử lại sau."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Không thể thực hiện yêu cầu đó ngay bây giờ"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Ứng dụng này không thể thực hiện yêu cầu đó"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Hãy đăng nhập để dùng ứng dụng này"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Yêu cầu quyền truy cập đặc biệt"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Đang nghe trên quá nhiều thiết bị"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Nội dung đó đã bị chặn"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Không thể xem nội dung đó tại đây"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Đang phát nội dung đó rồi"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Không thể bỏ qua bản nhạc nào nữa"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Không thể hoàn tất hành động. Hãy thử lại."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Không có nội dung nào khác trong hàng đợi"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Đang kết nối với nội dung nghe nhìn"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Cài đặt âm thanh"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Chuyển đổi ứng dụng"</string>
diff --git a/res/values-w1280dp/bools.xml b/res/values-w1280dp/bools.xml
new file mode 100644
index 0000000..a969b16
--- /dev/null
+++ b/res/values-w1280dp/bools.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<resources>
+ <bool name="set_browse_list_focus_area_highlight_above_minimized_control_bar">false</bool>
+</resources>
diff --git a/res/values-w1280dp/dimens.xml b/res/values-w1280dp/dimens.xml
index 8bc2a0f..0ff8f11 100644
--- a/res/values-w1280dp/dimens.xml
+++ b/res/values-w1280dp/dimens.xml
@@ -19,7 +19,9 @@
<!-- On wide screens, there is an additional margin below the minimized control bar.
Since you can't sum dimensions in xml, this value is:
@dimen/minimized_control_bar_height + @dimen/minimized_control_bar_margin_bottom -->
- <dimen name="browse_fragment_bottom_padding">144dp</dimen>
+ <dimen name="browse_fragment_bottom_padding">152dp</dimen>
+
+ <dimen name="minimized_control_bar_margin_bottom">@dimen/car_ui_padding_3</dimen>
<dimen name="media_browse_list_icons_item_art_margin_start">@dimen/car_ui_padding_4</dimen>
<dimen name="queue_list_item_padding_x">@dimen/car_ui_padding_4</dimen>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index ee9b3aa..b928667 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"媒体"</string>
<string name="search_hint" msgid="5401750426238148416">"搜索歌曲、音乐人等…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"正在播放"</string>
- <string name="default_error_message" msgid="6365377134388091079">"出了点问题。请稍后重试。"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"目前无法执行该操作"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"此应用无法执行该操作"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"登录才能使用此应用"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"需要有付费帐号才能访问"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"正在太多设备上同时聆听"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"该内容已遭到屏蔽"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"无法在此处获取这项内容"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"已经在播放这项内容"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"无法再跳过更多曲目"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"无法完成操作。请重试。"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"队列中没有任何其他内容"</string>
<string name="service_notification_title" msgid="8085444675783592744">"正在连接到媒体"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"声音设置"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"切换应用"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index a106414..15e6544 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"媒體"</string>
<string name="search_hint" msgid="5401750426238148416">"搜尋歌曲、演出者和更多內容…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"正在播放"</string>
- <string name="default_error_message" msgid="6365377134388091079">"發生錯誤,請稍後再試。"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"目前無法執行有關操作"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"此應用程式無法執行有關操作"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"登入即可使用此應用程式"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"需要有付費帳戶方可存取"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"過多裝置正在同時收聽"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"有關內容已封鎖"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"無法在此取得有關內容"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"已正在播放有關內容"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"無法再跳播曲目"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"無法完成操作,請再試一次。"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"序列中沒有內容"</string>
<string name="service_notification_title" msgid="8085444675783592744">"正在連接媒體"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"音效設定"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"切換應用程式"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 5b588e3..a909a72 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"媒體"</string>
<string name="search_hint" msgid="5401750426238148416">"搜尋歌曲、演出者和更多內容…"</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"正在播放"</string>
- <string name="default_error_message" msgid="6365377134388091079">"發生錯誤,請稍後再試。"</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"目前無法完成這項操作"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"這個應用程式不支援這項操作"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"如要使用這個應用程式,請登入帳戶"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"需要付費存取權"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"同時聆聽音樂的裝置過多"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"內容已遭到封鎖"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"該內容不適用於你所在地區"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"系統已開始播放該內容"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"無法再略過曲目"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"無法完成動作,請再試一次。"</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"待播清單中已無可播放的項目"</string>
<string name="service_notification_title" msgid="8085444675783592744">"正在連線到媒體"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"音效設定"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"切換應用程式"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 88ae0ab..e5807d4 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -26,18 +26,6 @@
<string name="media_app_title" msgid="94717597743776797">"Imidiya"</string>
<string name="search_hint" msgid="5401750426238148416">"Sesha izingoma, abaculi, nokuningi..."</string>
<string name="fragment_playback_title" msgid="5014481549024607614">"Okudlala manje"</string>
- <string name="default_error_message" msgid="6365377134388091079">"Kukhona okungalungile. Zama emuva kwesikhathi."</string>
- <string name="error_code_app_error" msgid="1726372057192704809">"Ayikwazi ukwenza lokho khona manje"</string>
- <string name="error_code_not_supported" msgid="1435878548411799387">"Lolu hlelo lokusebenza alukwazi ukwenza lokho"</string>
- <string name="error_code_authentication_expired" msgid="905154133202017052">"Ngena ngemvume ukuze usebenzise lolu hlelo lokusebenza"</string>
- <string name="error_code_premium_account_required" msgid="4736461331592855166">"Ukufinyelela kwe-premium kuyadingeka"</string>
- <string name="error_code_concurrent_stream_limit" msgid="1279573243715957403">"Ilalele kumadivayisi amaningi kakhulu"</string>
- <string name="error_code_parental_control_restricted" msgid="5222841294702530806">"Lokho okuqukethwe kuvinjelwe"</string>
- <string name="error_code_not_available_in_region" msgid="4106605584926645567">"Ayikwazi ukuletha lokho okuqukethwe lapha"</string>
- <string name="error_code_content_already_playing" msgid="8050972499898729459">"Isivele idlala lokho okuqukethwe"</string>
- <string name="error_code_skip_limit_reached" msgid="8926507875025988831">"Ayikwazi ukweqa amanye amathrekhi amaningi"</string>
- <string name="error_code_action_aborted" msgid="3889734248905737169">"Ayikwazanga ukuqeda. Zama futhi."</string>
- <string name="error_code_end_of_queue" msgid="2842652212154074468">"Akukho okunye okufakwe kulayini"</string>
<string name="service_notification_title" msgid="8085444675783592744">"Ixhumeka kumidiya"</string>
<string name="menu_item_sound_settings_title" msgid="58887078120809669">"Izilungiselelo zomsindo"</string>
<string name="menu_item_app_selector_title" msgid="4587248991114338595">"Shintsha izinhlelo zokusebenza"</string>
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 16d7dfa..6d3c189 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -19,9 +19,22 @@
<bool name="use_media_source_color_for_progress_bar">true</bool>
<bool name="show_time_for_now_playing_queue_list_item">true</bool>
<bool name="show_icon_for_now_playing_queue_list_item">false</bool>
+ <!-- Determines whether the mini playback controls should be shown or not. The mini playback
+ controls are used to show the user what is currently playing and give some means of
+ controlling the currently playing media (i.e play/pause, next/previous, etc). If similar
+ functionality is provided elsewhere (i.e. a persistent card in the sysui) this can be
+ disabled to minimize duplicate UI. -->
+ <bool name="show_mini_playback_controls">true</bool>
+ <!-- Determines whether clicking a playable item automatically shows the "Now Playing" screen.
+ Similar to `show_mini_playback_controls`, this can be set to false if there is some other
+ persistent means of seeing the currently playing media. -->
<bool name="switch_to_playback_view_when_playable_item_is_clicked">true</bool>
<bool name="show_thumbnail_for_queue_list_item">true</bool>
<bool name="show_subtitle_for_queue_list_item">false</bool>
<!-- Override this flag to show an icon that launches sound settings (equalizer) -->
<bool name="show_sound_settings">false</bool>
+ <!-- The minimized control bar sits on top of the FocusArea that contains the browse list. This
+ flag sets whether to move the bottom highlight of the FocusArea upward so that the
+ highlight doesn't overlap with the minimized control bar. -->
+ <bool name="set_browse_list_focus_area_highlight_above_minimized_control_bar">true</bool>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b667604..84d326e 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -40,6 +40,10 @@
<!-- Size of the thumb in the playback seekbar -->
<dimen name="playback_seekbar_thumb_height">16dp</dimen>
<dimen name="playback_seekbar_thumb_width">16dp</dimen>
+ <dimen name="playback_seekbar_thumb_inner_ring_inner_radius">8dp</dimen>
+ <dimen name="playback_seekbar_thumb_inner_ring_thickness">8dp</dimen>
+ <dimen name="playback_seekbar_thumb_outer_ring_inner_radius">16dp</dimen>
+ <dimen name="playback_seekbar_thumb_outer_ring_thickness">8dp</dimen>
<dimen name="playback_seekbar_thumb_offset">0px</dimen>
<!-- Paddings of playback seekbar -->
<dimen name="playback_seekbar_padding_x">0dp</dimen>
@@ -102,7 +106,6 @@
<dimen name="media_browse_grid_item_padding">0dp</dimen>
<dimen name="media_browse_grid_item_margin_bottom">@dimen/car_ui_padding_4</dimen>
<dimen name="media_browse_grid_item_text_margin_top">@dimen/car_ui_padding_3</dimen>
- <dimen name="media_browse_grid_item_background_radius">4dp</dimen>
<dimen name="media_browse_grid_icons_item_art_size">76dp</dimen>
diff --git a/res/values/id.xml b/res/values/id.xml
index 8f60cc7..c9d5250 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="imageDownloadTask"/>
- <item type="id" name="seek_bar_container"/>
+ <item type="id" name="playback_seek_bar_container"/>
</resources>
diff --git a/res/values/integers.xml b/res/values/integers.xml
index 16247b9..2077b00 100644
--- a/res/values/integers.xml
+++ b/res/values/integers.xml
@@ -38,13 +38,13 @@
<!-- Views to hide when opening the custom actions when the queue isn't visible. -->
<integer-array name="playback_views_to_hide_when_showing_custom_actions">
- <item>@id/seek_bar_container</item>
+ <item>@id/playback_seek_bar_container</item>
</integer-array>
<!-- Views to hide when the queue is visible (to show when the queue becomes invisible). -->
<integer-array name="playback_views_to_hide_when_queue_is_visible">
<item>@id/metadata_container</item>
- <item>@id/seek_bar_container</item>
+ <item>@id/playback_seek_bar_container</item>
</integer-array>
<!-- Views to show when the queue is visible (to hide when the queue becomes invisible). -->
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
new file mode 100644
index 0000000..b7206d0
--- /dev/null
+++ b/res/values/overlayable.xml
@@ -0,0 +1,267 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.-->
+<!--
+THIS FILE WAS AUTO GENERATED, DO NOT EDIT MANUALLY.
+REGENERATE USING packages/apps/Car/tests/tools/rro/generate-overlayable.py
+-->
+<resources>
+ <overlayable name="CarMediaApp">
+ <policy type="system|product|signature">
+ <item type="anim" name="progress_indeterminate_material"/>
+ <item type="anim" name="progress_indeterminate_rotation_material"/>
+ <item type="array" name="playback_views_to_hide_immediately_when_queue_is_visible"/>
+ <item type="array" name="playback_views_to_hide_when_queue_is_visible"/>
+ <item type="array" name="playback_views_to_hide_when_showing_custom_actions"/>
+ <item type="array" name="playback_views_to_show_immediately_when_queue_is_visible"/>
+ <item type="array" name="playback_views_to_show_when_queue_is_visible"/>
+ <item type="bool" name="queue_fading_edge_length_enabled"/>
+ <item type="bool" name="set_browse_list_focus_area_highlight_above_minimized_control_bar"/>
+ <item type="bool" name="show_icon_for_now_playing_queue_list_item"/>
+ <item type="bool" name="show_mini_playback_controls"/>
+ <item type="bool" name="show_sound_settings"/>
+ <item type="bool" name="show_subtitle_for_queue_list_item"/>
+ <item type="bool" name="show_thumbnail_for_queue_list_item"/>
+ <item type="bool" name="show_time_for_now_playing_queue_list_item"/>
+ <item type="bool" name="switch_to_playback_view_when_playable_item_is_clicked"/>
+ <item type="bool" name="use_media_source_color_for_progress_bar"/>
+ <item type="color" name="album_art_background"/>
+ <item type="color" name="appbar_view_icon_tint"/>
+ <item type="color" name="appbar_view_settings_tint"/>
+ <item type="color" name="browse_playback_bg_color"/>
+ <item type="color" name="no_content_text_color"/>
+ <item type="color" name="progress_bar_background"/>
+ <item type="color" name="progress_bar_highlight"/>
+ <item type="color" name="progress_bar_thumb_color"/>
+ <item type="color" name="progress_bar_thumb_inner_ring_color"/>
+ <item type="color" name="progress_bar_thumb_outer_ring_color"/>
+ <item type="color" name="queue_playing_icon_color"/>
+ <item type="color" name="search_bar_underline_color"/>
+ <item type="color" name="search_hint_text_color"/>
+ <item type="dimen" name="appbar_view_control_buttons_margin_end"/>
+ <item type="dimen" name="appbar_view_control_buttons_spacing"/>
+ <item type="dimen" name="appbar_view_nav_button_width"/>
+ <item type="dimen" name="appbar_view_tabs_margin_end"/>
+ <item type="dimen" name="appbar_view_tabs_margin_start"/>
+ <item type="dimen" name="appbar_view_title_margin_start"/>
+ <item type="dimen" name="apps_max_content_width"/>
+ <item type="dimen" name="art_metadata_margin"/>
+ <item type="dimen" name="browse_fragment_bottom_padding"/>
+ <item type="dimen" name="browse_fragment_top_padding"/>
+ <item type="dimen" name="browse_fragment_top_padding_stacked"/>
+ <item type="dimen" name="browse_playback_controls_height"/>
+ <item type="dimen" name="browse_spacer_height"/>
+ <item type="dimen" name="browse_state_error_margin_top"/>
+ <item type="dimen" name="browse_tab_alpha_selected"/>
+ <item type="dimen" name="browse_tab_alpha_unselected"/>
+ <item type="dimen" name="browse_tab_padding"/>
+ <item type="dimen" name="browse_tab_width"/>
+ <item type="dimen" name="controls_margin"/>
+ <item type="dimen" name="controls_spacing_inner"/>
+ <item type="dimen" name="controls_spacing_outer"/>
+ <item type="dimen" name="controls_tap_target_height"/>
+ <item type="dimen" name="controls_tap_target_width"/>
+ <item type="dimen" name="fragment_error_button_margin_bottom"/>
+ <item type="dimen" name="fragment_error_button_margin_top"/>
+ <item type="dimen" name="fragment_error_message_margin_x"/>
+ <item type="dimen" name="fragment_metadata_margin_x"/>
+ <item type="dimen" name="fragment_playback_queue_overlap_bottom"/>
+ <item type="dimen" name="fragment_playback_queue_overlap_top"/>
+ <item type="dimen" name="grid_item_spacing"/>
+ <item type="dimen" name="media_activity_close_vector_x"/>
+ <item type="dimen" name="media_activity_close_vector_y"/>
+ <item type="dimen" name="media_activity_controls_container_padding"/>
+ <item type="dimen" name="media_activity_controls_margin_start"/>
+ <item type="dimen" name="media_background_alpha"/>
+ <item type="dimen" name="media_browse_grid_icons_item_art_size"/>
+ <item type="dimen" name="media_browse_grid_item_margin_bottom"/>
+ <item type="dimen" name="media_browse_grid_item_padding"/>
+ <item type="dimen" name="media_browse_grid_item_text_margin_top"/>
+ <item type="dimen" name="media_browse_header_item_height"/>
+ <item type="dimen" name="media_browse_header_item_margin_x"/>
+ <item type="dimen" name="media_browse_indicator_size"/>
+ <item type="dimen" name="media_browse_list_icons_item_art_margin_start"/>
+ <item type="dimen" name="media_browse_list_icons_item_art_size"/>
+ <item type="dimen" name="media_browse_list_icons_item_text_margin_x"/>
+ <item type="dimen" name="media_browse_list_item_arrow_size"/>
+ <item type="dimen" name="media_browse_list_item_height"/>
+ <item type="dimen" name="media_browse_list_item_icon_margin_start"/>
+ <item type="dimen" name="media_browse_list_item_text_margin_x"/>
+ <item type="dimen" name="media_browse_list_item_thumbnail_margin_bottom"/>
+ <item type="dimen" name="media_browse_list_item_thumbnail_size"/>
+ <item type="dimen" name="media_browse_subtitle_margin_top"/>
+ <item type="dimen" name="media_scrim_alpha"/>
+ <item type="dimen" name="media_scrim_darkened_alpha"/>
+ <item type="dimen" name="metadata_subtitles_margin"/>
+ <item type="dimen" name="metadata_title_subtitle_margin"/>
+ <item type="dimen" name="minimized_control_bar_margin_bottom"/>
+ <item type="dimen" name="missing_permission_icon_size"/>
+ <item type="dimen" name="music_action_icon_inset"/>
+ <item type="dimen" name="music_action_ripple_inset"/>
+ <item type="dimen" name="playback_album_art_size"/>
+ <item type="dimen" name="playback_background_blur_radius"/>
+ <item type="dimen" name="playback_background_blur_scale"/>
+ <item type="dimen" name="playback_background_raw_image_size"/>
+ <item type="dimen" name="playback_queue_background_alpha"/>
+ <item type="dimen" name="playback_queue_button_margin_end"/>
+ <item type="dimen" name="playback_queue_list_padding_top"/>
+ <item type="dimen" name="playback_seekbar_height"/>
+ <item type="dimen" name="playback_seekbar_margin_x"/>
+ <item type="dimen" name="playback_seekbar_padding_x"/>
+ <item type="dimen" name="playback_seekbar_thumb_height"/>
+ <item type="dimen" name="playback_seekbar_thumb_inner_ring_inner_radius"/>
+ <item type="dimen" name="playback_seekbar_thumb_inner_ring_thickness"/>
+ <item type="dimen" name="playback_seekbar_thumb_offset"/>
+ <item type="dimen" name="playback_seekbar_thumb_outer_ring_inner_radius"/>
+ <item type="dimen" name="playback_seekbar_thumb_outer_ring_thickness"/>
+ <item type="dimen" name="playback_seekbar_thumb_width"/>
+ <item type="dimen" name="playback_seekbar_track_height"/>
+ <item type="dimen" name="playback_title_margin_end"/>
+ <item type="dimen" name="queue_button_background_size"/>
+ <item type="dimen" name="queue_fading_edge_length"/>
+ <item type="dimen" name="queue_list_item_height"/>
+ <item type="dimen" name="queue_list_item_padding_x"/>
+ <item type="dimen" name="queue_list_item_spacer_width"/>
+ <item type="dimen" name="queue_list_item_thumbnail_container_width"/>
+ <item type="dimen" name="queue_list_item_thumbnail_size"/>
+ <item type="dimen" name="queue_list_item_title_time_margin"/>
+ <item type="dimen" name="tab_view_icon_margin_bottom"/>
+ <item type="dimen" name="tab_view_icon_size"/>
+ <item type="drawable" name="error_illustration"/>
+ <item type="drawable" name="ic_arrow_back"/>
+ <item type="drawable" name="ic_chevron_right"/>
+ <item type="drawable" name="ic_equalizer"/>
+ <item type="drawable" name="ic_expand_less"/>
+ <item type="drawable" name="ic_expand_more"/>
+ <item type="drawable" name="ic_explicit_black"/>
+ <item type="drawable" name="ic_file_download_done_black"/>
+ <item type="drawable" name="ic_queue_button"/>
+ <item type="drawable" name="ic_search"/>
+ <item type="drawable" name="ic_settings"/>
+ <item type="drawable" name="media_app_title_background"/>
+ <item type="drawable" name="music_overflow_action_background"/>
+ <item type="drawable" name="seekbar_foreground"/>
+ <item type="drawable" name="seekbar_progress"/>
+ <item type="drawable" name="seekbar_thumb"/>
+ <item type="id" name="album_art"/>
+ <item type="id" name="album_title"/>
+ <item type="id" name="artist"/>
+ <item type="id" name="background_scrim"/>
+ <item type="id" name="browse_content_area"/>
+ <item type="id" name="browse_list"/>
+ <item type="id" name="control_bar_first_row_guideline"/>
+ <item type="id" name="control_bar_scrim"/>
+ <item type="id" name="current_time"/>
+ <item type="id" name="download_icon_with_subtitle"/>
+ <item type="id" name="download_icon_with_title"/>
+ <item type="id" name="error_button"/>
+ <item type="id" name="error_container"/>
+ <item type="id" name="error_icon"/>
+ <item type="id" name="error_message"/>
+ <item type="id" name="explicit_icon_with_subtitle"/>
+ <item type="id" name="explicit_icon_with_title"/>
+ <item type="id" name="focus_area"/>
+ <item type="id" name="fpv"/>
+ <item type="id" name="fragment_container"/>
+ <item type="id" name="imageDownloadTask"/>
+ <item type="id" name="inner_separator"/>
+ <item type="id" name="item_container"/>
+ <item type="id" name="max_time"/>
+ <item type="id" name="media_activity_root"/>
+ <item type="id" name="metadata_container"/>
+ <item type="id" name="minimized_playback_controls"/>
+ <item type="id" name="now_playing_icon"/>
+ <item type="id" name="outer_separator"/>
+ <item type="id" name="playback_background"/>
+ <item type="id" name="playback_container"/>
+ <item type="id" name="playback_controls"/>
+ <item type="id" name="playback_seek_bar"/>
+ <item type="id" name="playback_seek_bar_container"/>
+ <item type="id" name="progress_text_container"/>
+ <item type="id" name="queue_container"/>
+ <item type="id" name="queue_list"/>
+ <item type="id" name="queue_list_bottom_constraint"/>
+ <item type="id" name="queue_list_item_subtitle"/>
+ <item type="id" name="queue_list_item_title"/>
+ <item type="id" name="queue_list_item_titles_container"/>
+ <item type="id" name="queue_list_top_constraint"/>
+ <item type="id" name="right_arrow"/>
+ <item type="id" name="separator"/>
+ <item type="id" name="spacer"/>
+ <item type="id" name="subtitle"/>
+ <item type="id" name="text_start_guideline"/>
+ <item type="id" name="thumbnail"/>
+ <item type="id" name="thumbnail_container"/>
+ <item type="id" name="title"/>
+ <item type="id" name="ui_content_bottom_guideline"/>
+ <item type="id" name="ui_content_end_guideline"/>
+ <item type="id" name="ui_content_start_guideline"/>
+ <item type="id" name="ui_content_top_guideline"/>
+ <item type="id" name="ui_content_top_guideline2"/>
+ <item type="integer" name="fragment_playback_queue_fade_duration_ms"/>
+ <item type="integer" name="max_tabs"/>
+ <item type="integer" name="media_artist_max_lines"/>
+ <item type="integer" name="media_title_max_lines"/>
+ <item type="integer" name="num_app_bar_view_rows"/>
+ <item type="integer" name="num_browse_columns"/>
+ <item type="integer" name="progress_indicator_delay"/>
+ <item type="interpolator" name="trim_end_interpolator"/>
+ <item type="interpolator" name="trim_start_interpolator"/>
+ <item type="layout" name="browse_node"/>
+ <item type="layout" name="fragment_browse"/>
+ <item type="layout" name="fragment_error"/>
+ <item type="layout" name="fragment_playback"/>
+ <item type="layout" name="media_activity"/>
+ <item type="layout" name="media_browse_grid_icons_item"/>
+ <item type="layout" name="media_browse_grid_item"/>
+ <item type="layout" name="media_browse_header_item"/>
+ <item type="layout" name="media_browse_list_icons_item"/>
+ <item type="layout" name="media_browse_list_item"/>
+ <item type="layout" name="media_browse_spacer"/>
+ <item type="layout" name="metadata_normal"/>
+ <item type="layout" name="queue_list_item"/>
+ <item type="layout" name="time_progress_text"/>
+ <item type="layout" name="ui_guides"/>
+ <item type="string" name="browser_loading"/>
+ <item type="string" name="cannot_connect_to_app"/>
+ <item type="string" name="dash_separator"/>
+ <item type="string" name="fragment_playback_title"/>
+ <item type="string" name="media_app_title"/>
+ <item type="string" name="media_browse_more"/>
+ <item type="string" name="menu_item_app_selector_title"/>
+ <item type="string" name="menu_item_sound_settings_title"/>
+ <item type="string" name="nothing_to_play"/>
+ <item type="string" name="search_hint"/>
+ <item type="string" name="service_notification_title"/>
+ <item type="string" name="slash_separator"/>
+ <item type="string" name="unknown_error"/>
+ <item type="string" name="unknown_media_provider_name"/>
+ <item type="style" name="BrowseGridSubtitleStyle"/>
+ <item type="style" name="BrowseGridTitleStyle"/>
+ <item type="style" name="BrowseListItemRightArrowStyle"/>
+ <item type="style" name="BrowseListSubtitleStyle"/>
+ <item type="style" name="BrowseListTitleStyle"/>
+ <item type="style" name="BrowseSubheaderStyle"/>
+ <item type="style" name="ErrorTextStyle"/>
+ <item type="style" name="MetadataContainerStyle"/>
+ <item type="style" name="MetadataPlaybackSubtitleStyle"/>
+ <item type="style" name="MetadataPlaybackTitleStyle"/>
+ <item type="style" name="QueueListItemSubtitleStyle"/>
+ <item type="style" name="QueueListItemTimeStyle"/>
+ <item type="style" name="QueueListItemTitleStyle"/>
+ <item type="style" name="QueueListItemTitlesContainerStyle"/>
+ <item type="style" name="SeekBarStyle"/>
+ <item type="style" name="TextAppearance.NoContent"/>
+ <item type="style" name="Theme.Media"/>
+ <item type="xml" name="uxr_config"/>
+ </policy>
+ </overlayable>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 33d7f0d..258963f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -35,30 +35,7 @@
<!-- Title to display when in playback view. [CHAR LIMIT=50] -->
<string name="fragment_playback_title">Now Playing</string>
- <!-- MediaActivity default error message [CHAR LIMIT=100] -->
- <string name="default_error_message">Something’s wrong. Try later.</string>
- <!-- Error message set when the application state is invalid to fulfill the request. [CHAR LIMIT=100] -->
- <string name="error_code_app_error">Can’t do that right now</string>
- <!-- Error message set when the request is not supported by the application. [CHAR LIMIT=100] -->
- <string name="error_code_not_supported">This app can’t do that</string>
- <!-- Error message set when the request cannot be performed because authentication has expired. [CHAR LIMIT=100] -->
- <string name="error_code_authentication_expired">Sign in to use this app</string>
- <!-- Error message set when a premium account is required for the request to succeed. [CHAR LIMIT=100] -->
- <string name="error_code_premium_account_required">Premium access required</string>
- <!-- Error message set when too many concurrent streams are detected. [CHAR LIMIT=100] -->
- <string name="error_code_concurrent_stream_limit">Listening on too many devices</string>
- <!-- Error message set when the content is blocked due to parental controls. [CHAR LIMIT=100] -->
- <string name="error_code_parental_control_restricted">That content is blocked</string>
- <!-- Error message set when the content is blocked due to being regionally unavailable. [CHAR LIMIT=100] -->
- <string name="error_code_not_available_in_region">Can’t get that content here</string>
- <!-- Error message set when the requested content is already playing. [CHAR LIMIT=100] -->
- <string name="error_code_content_already_playing">Already playing that content</string>
- <!-- Error message set when the application cannot skip any more songs because skip limit is reached. [CHAR LIMIT=100] -->
- <string name="error_code_skip_limit_reached">Can’t skip any more tracks</string>
- <!-- Error message set when the action is interrupted due to some external event. [CHAR LIMIT=100] -->
- <string name="error_code_action_aborted">Couldn’t finish. Try again.</string>
- <!-- Error message set when the playback navigation (previous, next) is not possible because the queue was exhausted. [CHAR LIMIT=100] -->
- <string name="error_code_end_of_queue">Nothing else is queued up</string>
+
<!-- Title string for the service used to bind to the current media source -->
<string name="service_notification_title">Connecting to media</string>
<!-- Title of the sound settings menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
diff --git a/res/xml/uxr_config.xml b/res/xml/uxr_config.xml
new file mode 100644
index 0000000..d00c842
--- /dev/null
+++ b/res/xml/uxr_config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<Mapping xmlns:app="http://schemas.android.com/apk/res-auto">
+ <!-- We use a default value of -1 to denote UNLIMITED -->
+ <!-- When maxLength is > 0, its value is rounded up to the nearest greater odd integer. -->
+ <ListConfig
+ app:id="@+id/playback_fragment_now_playing_list_uxr_config"
+ app:maxLength="-1"
+ />
+
+ <!-- We use a default value of -1 to denote UNLIMITED -->
+ <ListConfig
+ app:id="@+id/browse_list_uxr_config"
+ app:maxLength="-1"
+ />
+</Mapping>
diff --git a/src/com/android/car/media/BrowseViewController.java b/src/com/android/car/media/BrowseViewController.java
index dd6de4b..c1869e4 100644
--- a/src/com/android/car/media/BrowseViewController.java
+++ b/src/com/android/car/media/BrowseViewController.java
@@ -16,105 +16,93 @@
package com.android.car.media;
-import static com.android.car.arch.common.LiveDataFunctions.ifThenElse;
+import static com.android.car.apps.common.util.ViewUtils.removeFromParent;
-import android.car.content.pm.CarPackageManager;
-import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
-import android.text.TextUtils;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.car.apps.common.util.ViewUtils;
import com.android.car.arch.common.FutureData;
import com.android.car.media.browse.BrowseAdapter;
+import com.android.car.media.browse.LimitedBrowseAdapter;
import com.android.car.media.common.GridSpacingItemDecoration;
import com.android.car.media.common.MediaItemMetadata;
-import com.android.car.media.common.browse.MediaBrowserViewModel;
+import com.android.car.media.common.browse.MediaBrowserViewModelImpl;
+import com.android.car.media.common.browse.MediaItemsRepository.MediaItemsLiveData;
import com.android.car.media.common.source.MediaSource;
-import com.android.car.media.widgets.AppBarView;
-import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.FocusArea;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.uxr.LifeCycleObserverUxrContentLimiter;
+import com.android.car.uxr.UxrContentLimiterImpl;
-import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
-import java.util.Objects;
-import java.util.Stack;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
/**
- * A view controller that implements the content forward browsing experience.
- *
- * This can be used to display either search or browse results at the root level. Deeper levels will
- * be handled the same way between search and browse, using a back stack to return to the root.
+ * A view controller that displays the media item children of a {@link MediaItemMetadata}.
+ * The controller manages a recycler view where the items can be displayed as a list or a grid, as
+ * well as an error icon and a message used to indicate loading and errors.
+ * The content view is initialized with 0 alpha and needs to be animated or set to to full opacity
+ * to become visible.
*/
-public class BrowseViewController extends ViewControllerBase {
+public class BrowseViewController {
private static final String TAG = "BrowseViewController";
- private static final String REGULAR_BROWSER_VIEW_MODEL_KEY
- = "com.android.car.media.regular_browser_view_model";
- private static final String SEARCH_BROWSER_VIEW_MODEL_KEY
- = "com.android.car.media.search_browser_view_model";
-
private final Callbacks mCallbacks;
-
+ private final FocusArea mFocusArea;
+ private final MediaItemMetadata mParentItem;
+ private final MediaItemsLiveData mMediaItems;
+ private final boolean mDisplayMediaItems;
+ private final LifeCycleObserverUxrContentLimiter mUxrContentLimiter;
+ private final View mContent;
private final RecyclerView mBrowseList;
private final ImageView mErrorIcon;
private final TextView mMessage;
- private final BrowseAdapter mBrowseAdapter;
- private String mSearchQuery;
+ private final LimitedBrowseAdapter mLimitedBrowseAdapter;
+
private final int mFadeDuration;
private final int mLoadingIndicatorDelay;
- private final boolean mIsSearchController;
- private final MutableLiveData<Boolean> mShowSearchResults = new MutableLiveData<>();
+
+ private final boolean mSetFocusAreaHighlightBottom;
+
private final Handler mHandler = new Handler();
- /**
- * Stores the reference to {@link MediaActivity.ViewModel#getSearchStack} or to
- * {@link MediaActivity.ViewModel#getBrowseStack}. Updated in {@link #onMediaSourceChanged}.
- */
- private Stack<MediaItemMetadata> mBrowseStack = new Stack<>();
+
private final MediaActivity.ViewModel mViewModel;
- private final MediaBrowserViewModel mRootMediaBrowserViewModel;
- private final MediaBrowserViewModel.WithMutableBrowseId mMediaBrowserViewModel;
+
private final BrowseAdapter.Observer mBrowseAdapterObserver = new BrowseAdapter.Observer() {
@Override
- protected void onPlayableItemClicked(MediaItemMetadata item) {
- hideKeyboard();
- getParent().onPlayableItemClicked(item);
+ protected void onPlayableItemClicked(@NonNull MediaItemMetadata item) {
+ mCallbacks.onPlayableItemClicked(item);
}
@Override
- protected void onBrowsableItemClicked(MediaItemMetadata item) {
- hideKeyboard();
- navigateInto(item);
+ protected void onBrowsableItemClicked(@NonNull MediaItemMetadata item) {
+ mCallbacks.onBrowsableItemClicked(item);
}
};
- private boolean mBrowseTreeHasChildren;
- private boolean mAcceptTabSelection = true;
-
/**
- * Media items to display as tabs. If null, it means we haven't finished loading them yet. If
- * empty, it means there are no tabs to show
+ * The bottom padding of the FocusArea highlight.
*/
- @Nullable
- private List<MediaItemMetadata> mTopItems;
+ private int mFocusAreaHighlightBottomPadding;
/**
- * Callbacks (implemented by the hosting Activity)
+ * Callbacks (implemented by the host)
*/
public interface Callbacks {
/**
@@ -122,134 +110,70 @@
*
* @param item item to be played.
*/
- void onPlayableItemClicked(MediaItemMetadata item);
+ void onPlayableItemClicked(@NonNull MediaItemMetadata item);
- /** Called once the list of the root node's children has been loaded. */
- void onRootLoaded();
+ /** Invoked when the user clicks on a browsable item. */
+ void onBrowsableItemClicked(@NonNull MediaItemMetadata item);
- /** Change to a new UI mode. */
- void changeMode(MediaActivity.Mode mode);
+ /** Invoked when child nodes have been removed from this controller. */
+ void onChildrenNodesRemoved(@NonNull BrowseViewController controller,
+ @NonNull Collection<MediaItemMetadata> removedNodes);
FragmentActivity getActivity();
}
- /**
- * Moves the user one level up in the browse tree. Returns whether that was possible.
- */
- private boolean navigateBack() {
- boolean result = false;
- if (!isAtTopStack()) {
- mBrowseStack.pop();
- mMediaBrowserViewModel.search(mSearchQuery);
- mMediaBrowserViewModel.setCurrentBrowseId(getCurrentMediaItemId());
- updateAppBar();
- result = true;
- }
- if (isAtTopStack()) {
- mShowSearchResults.setValue(mIsSearchController);
- }
- return result;
- }
-
- private void reopenSearch() {
- if (mIsSearchController) {
- mBrowseStack.clear();
- updateAppBar();
- mShowSearchResults.setValue(true);
- } else {
- Log.e(TAG, "reopenSearch called on browse controller");
- }
- }
-
- @NonNull
- private Callbacks getParent() {
- return mCallbacks;
- }
-
private FragmentActivity getActivity() {
return mCallbacks.getActivity();
}
/**
- * @return whether the user is at the top of the browsing stack.
+ * Creates a controller to display the children of the given parent {@link MediaItemMetadata}.
+ * This parent node can have been obtained from the browse tree, or from browsing the search
+ * results.
*/
- private boolean isAtTopStack() {
- if (mIsSearchController) {
- return mBrowseStack.isEmpty();
- } else {
- // The mBrowseStack stack includes the tab...
- return mBrowseStack.size() <= 1;
- }
+ static BrowseViewController newBrowseController(Callbacks callbacks, ViewGroup container,
+ @NonNull MediaItemMetadata parentItem, MediaItemsLiveData mediaItems,
+ int rootBrowsableHint, int rootPlayableHint) {
+ return new BrowseViewController(callbacks, container, parentItem, mediaItems,
+ rootBrowsableHint, rootPlayableHint, true);
+ }
+
+ /** Creates a controller to display the top results of a search query (in a list). */
+ static BrowseViewController newSearchResultsController(Callbacks callbacks, ViewGroup container,
+ MediaItemsLiveData mediaItems) {
+ return new BrowseViewController(callbacks, container, null, mediaItems, 0, 0, true);
}
/**
- * Creates a new instance of this controller meant to browse the root node.
- * @return a fully initialized {@link BrowseViewController}
+ * Creates a controller to "display" the children of the root: the children are actually hidden
+ * since they are shown as tabs, and the controller is only used to display loading and error
+ * messages.
*/
- public static BrowseViewController newInstance(Callbacks callbacks,
- CarPackageManager carPackageManager, ViewGroup container) {
- boolean isSearchController = false;
- return new BrowseViewController(callbacks, carPackageManager, container, isSearchController);
+ static BrowseViewController newRootController(Callbacks callbacks, ViewGroup container,
+ MediaItemsLiveData mediaItems) {
+ return new BrowseViewController(callbacks, container, null, mediaItems, 0, 0, false);
}
- /**
- * Creates a new instance of this controller meant to display search results. The root browse
- * screen will be the search results for the provided query.
- *
- * @return a fully initialized {@link BrowseViewController}
- */
- static BrowseViewController newSearchInstance(Callbacks callbacks,
- CarPackageManager carPackageManager, ViewGroup container) {
- boolean isSearchController = true;
- return new BrowseViewController(callbacks, carPackageManager, container, isSearchController);
- }
- private void updateSearchQuery(@Nullable String query) {
- mSearchQuery = query;
- mMediaBrowserViewModel.search(query);
- }
-
- /**
- * Clears search state, removes any UI elements from previous results.
- */
- @Override
- void onMediaSourceChanged(@Nullable MediaSource mediaSource) {
- super.onMediaSourceChanged(mediaSource);
-
- mBrowseTreeHasChildren = false;
-
- if (mIsSearchController) {
- updateSearchQuery(mViewModel.getSearchQuery());
- mAppBarView.setSearchQuery(mSearchQuery);
- mBrowseStack = mViewModel.getSearchStack();
- mShowSearchResults.setValue(isAtTopStack());
- } else {
- mBrowseStack = mViewModel.getBrowseStack();
- mShowSearchResults.setValue(false);
- updateTabs((mediaSource != null) ? null : new ArrayList<>());
- }
-
- mBrowseAdapter.submitItems(null, null);
- stopLoadingIndicator();
- ViewUtils.hideViewAnimated(mErrorIcon, mFadeDuration);
- ViewUtils.hideViewAnimated(mMessage, mFadeDuration);
-
- mMediaBrowserViewModel.setCurrentBrowseId(getCurrentMediaItemId());
-
- updateAppBar();
- }
-
- private BrowseViewController(Callbacks callbacks, CarPackageManager carPackageManager,
- ViewGroup container, boolean isSearchController) {
- super(callbacks.getActivity(), carPackageManager, container, R.layout.fragment_browse);
-
+ private BrowseViewController(Callbacks callbacks, ViewGroup container,
+ @Nullable MediaItemMetadata parentItem, MediaItemsLiveData mediaItems,
+ int rootBrowsableHint, int rootPlayableHint, boolean displayMediaItems) {
mCallbacks = callbacks;
- mIsSearchController = isSearchController;
+ mParentItem = parentItem;
+ mMediaItems = mediaItems;
+ mDisplayMediaItems = displayMediaItems;
+
+ LayoutInflater inflater = LayoutInflater.from(container.getContext());
+ mContent = inflater.inflate(R.layout.browse_node, container, false);
+ mContent.setAlpha(0f);
+ container.addView(mContent);
mLoadingIndicatorDelay = mContent.getContext().getResources()
.getInteger(R.integer.progress_indicator_delay);
+ mSetFocusAreaHighlightBottom = mContent.getContext().getResources().getBoolean(
+ R.bool.set_browse_list_focus_area_highlight_above_minimized_control_bar);
- mAppBarView.setListener(mAppBarListener);
+ mFocusArea = mContent.findViewById(R.id.focus_area);
mBrowseList = mContent.findViewById(R.id.browse_list);
mErrorIcon = mContent.findViewById(R.id.error_icon);
mMessage = mContent.findViewById(R.id.error_message);
@@ -258,82 +182,81 @@
FragmentActivity activity = callbacks.getActivity();
-
mViewModel = ViewModelProviders.of(activity).get(MediaActivity.ViewModel.class);
- // Browse logic for the root node
- mRootMediaBrowserViewModel = MediaBrowserViewModel.Factory.getInstanceForBrowseRoot(
- mMediaSourceVM, ViewModelProviders.of(activity));
- mRootMediaBrowserViewModel.getBrowsedMediaItems()
- .observe(activity, futureData -> onItemsUpdate(/* forRoot */ true, futureData));
-
- mRootMediaBrowserViewModel.supportsSearch().observe(activity,
- mAppBarView::setSearchSupported);
-
-
- // Browse logic for current node
- mMediaBrowserViewModel = MediaBrowserViewModel.Factory.getInstanceWithMediaBrowser(
- mIsSearchController ? SEARCH_BROWSER_VIEW_MODEL_KEY : REGULAR_BROWSER_VIEW_MODEL_KEY,
- ViewModelProviders.of(activity),
- mMediaSourceVM.getConnectedMediaBrowser());
-
mBrowseList.addItemDecoration(new GridSpacingItemDecoration(
activity.getResources().getDimensionPixelSize(R.dimen.grid_item_spacing)));
- mBrowseAdapter = new BrowseAdapter(mBrowseList.getContext());
- mBrowseList.setAdapter(mBrowseAdapter);
- mBrowseAdapter.registerObserver(mBrowseAdapterObserver);
+ GridLayoutManager manager = (GridLayoutManager) mBrowseList.getLayoutManager();
+ BrowseAdapter browseAdapter = new BrowseAdapter(mBrowseList.getContext());
+ mLimitedBrowseAdapter = new LimitedBrowseAdapter(browseAdapter, manager,
+ mBrowseAdapterObserver);
+ mBrowseList.setAdapter(mLimitedBrowseAdapter);
- mMediaBrowserViewModel.rootBrowsableHint().observe(activity,
- mBrowseAdapter::setRootBrowsableViewType);
- mMediaBrowserViewModel.rootPlayableHint().observe(activity,
- mBrowseAdapter::setRootPlayableViewType);
- LiveData<FutureData<List<MediaItemMetadata>>> mediaItems = ifThenElse(mShowSearchResults,
- mMediaBrowserViewModel.getSearchedMediaItems(),
- mMediaBrowserViewModel.getBrowsedMediaItems());
+ mUxrContentLimiter = new LifeCycleObserverUxrContentLimiter(
+ new UxrContentLimiterImpl(activity, R.xml.uxr_config));
+ mUxrContentLimiter.setAdapter(mLimitedBrowseAdapter);
+ activity.getLifecycle().addObserver(mUxrContentLimiter);
- mediaItems.observe(activity, futureData -> onItemsUpdate(/* forRoot */ false, futureData));
+ browseAdapter.setRootBrowsableViewType(rootBrowsableHint);
+ browseAdapter.setRootPlayableViewType(rootPlayableHint);
- updateAppBar();
+ mMediaItems.observe(activity, mItemsObserver);
}
- private AppBarView.AppBarListener mAppBarListener = new BasicAppBarListener() {
- @Override
- public void onTabSelected(MediaItemMetadata item) {
- if (mAcceptTabSelection) {
- showTopItem(item);
+ public MediaItemMetadata getParentItem() {
+ return mParentItem;
+ }
+
+ /** Shares the browse adapter with the given view... #local-hack. */
+ public void shareBrowseAdapterWith(RecyclerView view) {
+ view.setAdapter(mLimitedBrowseAdapter);
+ }
+
+ private final Observer<FutureData<List<MediaItemMetadata>>> mItemsObserver =
+ this::onItemsUpdate;
+
+ View getContent() {
+ return mContent;
+ }
+
+ String getDebugInfo() {
+ StringBuilder log = new StringBuilder();
+ log.append("[");
+ log.append((mParentItem != null) ? mParentItem.getTitle() : "Root");
+ log.append("]");
+ FutureData<List<MediaItemMetadata>> children = mMediaItems.getValue();
+ if (children == null) {
+ log.append(" null future data");
+ } else if (children.isLoading()) {
+ log.append(" loading");
+ } else if (children.getData() == null) {
+ log.append(" null list");
+ } else {
+ List<MediaItemMetadata> nodes = children.getData();
+ log.append(" ");
+ log.append(nodes.size());
+ log.append(" {");
+ if (nodes.size() > 0) {
+ log.append(nodes.get(0).getTitle().toString());
}
- }
-
- @Override
- public void onBack() {
- onBackPressed();
- }
-
- @Override
- public void onSearchSelection() {
- if (mIsSearchController) {
- reopenSearch();
- } else {
- mCallbacks.changeMode(MediaActivity.Mode.SEARCHING);
+ if (nodes.size() > 1) {
+ log.append(", ");
+ log.append(nodes.get(1).getTitle().toString());
}
- }
-
- @Override
- public void onHeightChanged(int height) {
- onAppBarHeightChanged(height);
- }
-
- @Override
- public void onSearch(String query) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onSearch: " + query);
+ if (nodes.size() > 2) {
+ log.append(", ...");
}
- mViewModel.setSearchQuery(query);
- updateSearchQuery(query);
+ log.append(" }");
}
- };
+ return log.toString();
+ }
+ void destroy() {
+ mCallbacks.getActivity().getLifecycle().removeObserver(mUxrContentLimiter);
+ mMediaItems.removeObserver(mItemsObserver);
+ removeFromParent(mContent);
+ }
private Runnable mLoadingIndicatorRunnable = new Runnable() {
@Override
@@ -343,19 +266,6 @@
}
};
- boolean onBackPressed() {
- boolean success = navigateBack();
- if (!success && (mIsSearchController)) {
- mCallbacks.changeMode(MediaActivity.Mode.BROWSING);
- return true;
- }
- return success;
- }
-
- boolean browseTreeHasChildren() {
- return mBrowseTreeHasChildren;
- }
-
private void startLoadingIndicator() {
// Display the indicator after a certain time, to avoid flashing the indicator constantly,
// even when performance is acceptable.
@@ -367,52 +277,36 @@
ViewUtils.hideViewAnimated(mMessage, mFadeDuration);
}
- private void navigateInto(@Nullable MediaItemMetadata item) {
- if (item != null) {
- mBrowseStack.push(item);
- mMediaBrowserViewModel.setCurrentBrowseId(item.getId());
- } else {
- mMediaBrowserViewModel.setCurrentBrowseId(null);
+ public void onCarUiInsetsChanged(@NonNull Insets insets) {
+ int leftPadding = mBrowseList.getPaddingLeft();
+ int rightPadding = mBrowseList.getPaddingRight();
+ int bottomPadding = mBrowseList.getPaddingBottom();
+ mBrowseList.setPadding(leftPadding, insets.getTop(), rightPadding, bottomPadding);
+ if (bottomPadding > mFocusAreaHighlightBottomPadding) {
+ mFocusAreaHighlightBottomPadding = bottomPadding;
}
-
- mShowSearchResults.setValue(false);
- updateAppBar();
- }
-
- /**
- * @return the current item being displayed
- */
- @Nullable
- private MediaItemMetadata getCurrentMediaItem() {
- return mBrowseStack.isEmpty() ? null : mBrowseStack.lastElement();
- }
-
- @Nullable
- private String getCurrentMediaItemId() {
- MediaItemMetadata currentItem = getCurrentMediaItem();
- return currentItem != null ? currentItem.getId() : null;
- }
-
- private void onAppBarHeightChanged(int height) {
- if (mBrowseList == null) {
- return;
- }
-
- mBrowseList.setPadding(mBrowseList.getPaddingLeft(), height,
- mBrowseList.getPaddingRight(), mBrowseList.getPaddingBottom());
+ mFocusArea.setHighlightPadding(
+ leftPadding, insets.getTop(), rightPadding, mFocusAreaHighlightBottomPadding);
+ mFocusArea.setBoundsOffset(leftPadding, insets.getTop(), rightPadding, bottomPadding);
}
void onPlaybackControlsChanged(boolean visible) {
- if (mBrowseList == null) {
- return;
- }
-
+ int leftPadding = mBrowseList.getPaddingLeft();
+ int topPadding = mBrowseList.getPaddingTop();
+ int rightPadding = mBrowseList.getPaddingRight();
Resources res = getActivity().getResources();
int bottomPadding = visible
- ? res.getDimensionPixelOffset(R.dimen.browse_fragment_bottom_padding)
- : 0;
- mBrowseList.setPadding(mBrowseList.getPaddingLeft(), mBrowseList.getPaddingTop(),
- mBrowseList.getPaddingRight(), bottomPadding);
+ ? res.getDimensionPixelOffset(R.dimen.browse_fragment_bottom_padding) : 0;
+ mBrowseList.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
+ int highlightBottomPadding = mSetFocusAreaHighlightBottom ? bottomPadding : 0;
+ if (highlightBottomPadding > mFocusAreaHighlightBottomPadding) {
+ mFocusAreaHighlightBottomPadding = highlightBottomPadding;
+ }
+ mFocusArea.setHighlightPadding(
+ leftPadding, topPadding, rightPadding, mFocusAreaHighlightBottomPadding);
+ // Set the bottom offset to bottomPadding regardless of mSetFocusAreaHighlightBottom so that
+ // RotaryService can find the correct target when the user nudges the rotary controller.
+ mFocusArea.setBoundsOffset(leftPadding, topPadding, rightPadding, bottomPadding);
ViewGroup.MarginLayoutParams messageLayout =
(ViewGroup.MarginLayoutParams) mMessage.getLayoutParams();
@@ -420,102 +314,9 @@
mMessage.setLayoutParams(messageLayout);
}
- private void hideKeyboard() {
- InputMethodManager in =
- (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
- in.hideSoftInputFromWindow(mContent.getWindowToken(), 0);
- }
-
- private void showTopItem(@Nullable MediaItemMetadata item) {
- mViewModel.getBrowseStack().clear();
- navigateInto(item);
- }
-
- /**
- * Updates the tabs displayed on the app bar, based on the top level items on the browse tree.
- * If there is at least one browsable item, we show the browse content of that node. If there
- * are only playable items, then we show those items. If there are not items at all, we show the
- * empty message. If we receive null, we show the error message.
- *
- * @param items top level items, null if the items are still being loaded, or empty list if
- * items couldn't be loaded.
- */
- private void updateTabs(@Nullable List<MediaItemMetadata> items) {
- if (Objects.equals(mTopItems, items)) {
- // When coming back to the app, the live data sends an update even if the list hasn't
- // changed. Updating the tabs then recreates the browse view, which produces jank
- // (b/131830876), and also resets the navigation to the top of the first tab...
- return;
- }
- mTopItems = items;
-
- if (mTopItems == null || mTopItems.isEmpty()) {
- mAppBarView.setItems(null);
- mAppBarView.setActiveItem(null);
- if (items != null) {
- // Only do this when not loading the tabs or we loose the saved one.
- showTopItem(null);
- }
- updateAppBar();
- return;
- }
-
- MediaItemMetadata oldTab = mViewModel.getSelectedTab();
- try {
- mAcceptTabSelection = false;
- mAppBarView.setItems(mTopItems.size() == 1 ? null : mTopItems);
- updateAppBar();
-
- if (items.contains(oldTab)) {
- mAppBarView.setActiveItem(oldTab);
- } else {
- showTopItem(items.get(0));
- }
- } finally {
- mAcceptTabSelection = true;
- }
- }
-
- private void updateAppBarTitle() {
- boolean isStacked = !isAtTopStack();
-
- final CharSequence title;
- if (isStacked) {
- // If not at top level, show the current item as title
- title = getCurrentMediaItem().getTitle();
- } else if (mTopItems == null) {
- // If still loading the tabs, force to show an empty bar.
- title = "";
- } else if (mTopItems.size() == 1) {
- // If we finished loading tabs and there is only one, use that as title.
- title = mTopItems.get(0).getTitle();
- } else {
- // Otherwise (no tabs or more than 1 tabs), show the current media source title.
- MediaSource mediaSource = mMediaSourceVM.getPrimaryMediaSource().getValue();
- title = getAppBarDefaultTitle(mediaSource);
- }
-
- mAppBarView.setTitle(title);
- }
-
- /**
- * Update elements of the appbar that change depending on where we are in the browse.
- */
- private void updateAppBar() {
- boolean isStacked = !isAtTopStack();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "App bar is in stacked state: " + isStacked);
- }
- Toolbar.State unstackedState =
- mIsSearchController ? Toolbar.State.SEARCH : Toolbar.State.HOME;
- updateAppBarTitle();
- mAppBarView.setState(isStacked ? Toolbar.State.SUBPAGE : unstackedState);
- mAppBarView.showSearchIfSupported(!mIsSearchController || isStacked);
- }
-
- private String getErrorMessage(boolean forRoot) {
- if (forRoot) {
- MediaSource mediaSource = mMediaSourceVM.getPrimaryMediaSource().getValue();
+ private String getErrorMessage() {
+ if (/*root*/ !mDisplayMediaItems) {
+ MediaSource mediaSource = mViewModel.getMediaSourceValue();
return getActivity().getString(
R.string.cannot_connect_to_app,
mediaSource != null
@@ -527,68 +328,40 @@
}
}
- /**
- * Filters the items that are valid for the root (tabs) or the current node. Returns null when
- * the given list is null to preserve its error signal.
- */
- @Nullable
- private List<MediaItemMetadata> filterItems(boolean forRoot,
- @Nullable List<MediaItemMetadata> items) {
- if (items == null) return null;
- Predicate<MediaItemMetadata> predicate = forRoot ? MediaItemMetadata::isBrowsable
- : item -> (item.isPlayable() || item.isBrowsable());
- return items.stream().filter(predicate).collect(Collectors.toList());
- }
-
- private void onItemsUpdate(boolean forRoot, FutureData<List<MediaItemMetadata>> futureData) {
-
- // Prevent showing loading spinner or any error messages if search is uninitialized
- if (mIsSearchController && TextUtils.isEmpty(mSearchQuery)) {
- return;
- }
-
- if (!forRoot && !mBrowseTreeHasChildren && !mIsSearchController) {
- // Ignore live data ghost values
- return;
- }
-
- if (futureData.isLoading()) {
- startLoadingIndicator();
+ private void onItemsUpdate(@Nullable FutureData<List<MediaItemMetadata>> futureData) {
+ if (futureData == null || futureData.isLoading()) {
ViewUtils.hideViewAnimated(mErrorIcon, 0);
ViewUtils.hideViewAnimated(mMessage, 0);
+
// TODO(b/139759881) build a jank-free animation of the transition.
mBrowseList.setAlpha(0f);
- mBrowseAdapter.submitItems(null, null);
+ mLimitedBrowseAdapter.submitItems(null, null);
- if (forRoot) {
- if (Log.isLoggable(TAG, Log.INFO)) {
- Log.i(TAG, "Loading browse tree...");
- }
- mBrowseTreeHasChildren = false;
- updateTabs(null);
+ if (futureData != null) {
+ startLoadingIndicator();
}
return;
}
stopLoadingIndicator();
- List<MediaItemMetadata> items = filterItems(forRoot, futureData.getData());
- if (forRoot) {
- boolean browseTreeHasChildren = items != null && !items.isEmpty();
- if (Log.isLoggable(TAG, Log.INFO)) {
- Log.i(TAG, "Browse tree loaded, status (has children or not) changed: "
- + mBrowseTreeHasChildren + " -> " + browseTreeHasChildren);
+ List<MediaItemMetadata> items = MediaBrowserViewModelImpl.filterItems(
+ /*root*/ !mDisplayMediaItems, futureData.getData());
+ if (mDisplayMediaItems) {
+ mLimitedBrowseAdapter.submitItems(mParentItem, items);
+
+ List<MediaItemMetadata> lastNodes =
+ MediaBrowserViewModelImpl.selectBrowseableItems(futureData.getPastData());
+ Collection<MediaItemMetadata> removedNodes =
+ MediaBrowserViewModelImpl.computeRemovedItems(lastNodes, items);
+ if (!removedNodes.isEmpty()) {
+ mCallbacks.onChildrenNodesRemoved(this, removedNodes);
}
- mBrowseTreeHasChildren = browseTreeHasChildren;
- mCallbacks.onRootLoaded();
- updateTabs(items != null ? items : new ArrayList<>());
- } else {
- mBrowseAdapter.submitItems(getCurrentMediaItem(), items);
}
- int duration = forRoot ? 0 : mFadeDuration;
+ int duration = mFadeDuration;
if (items == null) {
- mMessage.setText(getErrorMessage(forRoot));
+ mMessage.setText(getErrorMessage());
ViewUtils.hideViewAnimated(mBrowseList, duration);
ViewUtils.showViewAnimated(mMessage, duration);
ViewUtils.showViewAnimated(mErrorIcon, duration);
@@ -597,10 +370,14 @@
ViewUtils.hideViewAnimated(mBrowseList, duration);
ViewUtils.hideViewAnimated(mErrorIcon, duration);
ViewUtils.showViewAnimated(mMessage, duration);
- } else if (!forRoot) {
+ } else {
ViewUtils.showViewAnimated(mBrowseList, duration);
ViewUtils.hideViewAnimated(mErrorIcon, duration);
ViewUtils.hideViewAnimated(mMessage, duration);
}
+
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "onItemsUpdate " + getDebugInfo());
+ }
}
}
diff --git a/src/com/android/car/media/ErrorScreenController.java b/src/com/android/car/media/ErrorScreenController.java
new file mode 100644
index 0000000..bd62f81
--- /dev/null
+++ b/src/com/android/car/media/ErrorScreenController.java
@@ -0,0 +1,41 @@
+package com.android.car.media;
+
+import android.app.PendingIntent;
+import android.car.content.pm.CarPackageManager;
+import android.view.ViewGroup;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.car.media.common.PlaybackErrorViewController;
+import com.android.car.media.common.source.MediaSource;
+
+/**
+ * A view controller that displays the playback state error iif there is no browse tree.
+ */
+public class ErrorScreenController extends ViewControllerBase {
+
+ private final PlaybackErrorViewController mPlaybackErrorViewController;
+
+ ErrorScreenController(FragmentActivity activity,
+ CarPackageManager carPackageManager, ViewGroup container) {
+ super(activity, carPackageManager, container, R.layout.fragment_error);
+
+ mPlaybackErrorViewController = new PlaybackErrorViewController(mContent);
+ }
+
+ @Override
+ void onMediaSourceChanged(@Nullable MediaSource mediaSource) {
+ super.onMediaSourceChanged(mediaSource);
+
+ mAppBarController.setListener(new BasicAppBarListener());
+ mAppBarController.setTitle(getAppBarDefaultTitle(mediaSource));
+
+ mPlaybackErrorViewController.hideErrorNoAnim();
+ }
+
+ public void setError(String message, String label, PendingIntent pendingIntent,
+ boolean distractionOptimized) {
+ mPlaybackErrorViewController.setError(message, label, pendingIntent, distractionOptimized);
+ }
+}
diff --git a/src/com/android/car/media/ErrorViewController.java b/src/com/android/car/media/ErrorViewController.java
deleted file mode 100644
index e455092..0000000
--- a/src/com/android/car/media/ErrorViewController.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.android.car.media;
-
-import android.app.PendingIntent;
-import android.car.content.pm.CarPackageManager;
-import android.car.drivingstate.CarUxRestrictions;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.Nullable;
-import androidx.fragment.app.FragmentActivity;
-
-import com.android.car.apps.common.UxrButton;
-import com.android.car.apps.common.UxrTextView;
-import com.android.car.apps.common.util.ViewUtils;
-import com.android.car.media.common.source.MediaSource;
-
-/**
- * A view controller that displays the playback state error iif there is no browse tree.
- */
-public class ErrorViewController extends ViewControllerBase {
- private final String TAG = "ErrorViewController";
-
- // mErrorMessageView is defined explicitly as a UxrTextView instead of a TextView to
- // provide clarity as it may be misleading to assume that mErrorMessageView extends all TextView
- // methods. In addition, it increases discoverability of runtime issues that may occur.
- private final UxrTextView mErrorMessageView;
- private final UxrButton mErrorButton;
-
-
- ErrorViewController(FragmentActivity activity,
- CarPackageManager carPackageManager, ViewGroup container) {
- super(activity, carPackageManager, container, R.layout.fragment_error);
-
- mErrorMessageView = mContent.findViewById(R.id.error_message);
- mErrorButton = mContent.findViewById(R.id.error_button);
- }
-
- @Override
- void onMediaSourceChanged(@Nullable MediaSource mediaSource) {
- super.onMediaSourceChanged(mediaSource);
-
- mAppBarView.setListener(new BasicAppBarListener());
- mAppBarView.setTitle(getAppBarDefaultTitle(mediaSource));
-
- ViewUtils.hideViewAnimated(mErrorMessageView, 0);
- ViewUtils.hideViewAnimated(mErrorButton, 0);
- }
-
- public void setError(String message, String label, PendingIntent pendingIntent,
- boolean isDistractionOptimized) {
- mErrorMessageView.setText(message);
-
- // Only show the error button if the error is actionable.
- if (label != null && pendingIntent != null) {
- mErrorButton.setText(label);
-
- mErrorButton.setUxRestrictions(isDistractionOptimized
- ? CarUxRestrictions.UX_RESTRICTIONS_BASELINE
- : CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP);
-
- mErrorButton.setOnClickListener(v -> {
- try {
- pendingIntent.send();
- } catch (PendingIntent.CanceledException e) {
- if (Log.isLoggable(TAG, Log.ERROR)) {
- Log.e(TAG, "Pending intent canceled");
- }
- }
- });
- mErrorButton.setVisibility(View.VISIBLE);
- } else {
- mErrorButton.setVisibility(View.GONE);
- }
-
- ViewUtils.showViewAnimated(mErrorMessageView, mFadeDuration);
- ViewUtils.showViewAnimated(mErrorButton, mFadeDuration);
- }
-}
diff --git a/src/com/android/car/media/GuidelinesUpdater.java b/src/com/android/car/media/GuidelinesUpdater.java
new file mode 100644
index 0000000..e12ba84
--- /dev/null
+++ b/src/com/android/car/media/GuidelinesUpdater.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.media;
+
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Applies the insets computed by the car-ui-lib to the spacer views in ui_guides.xml. This allows
+ * the Media app to have different instances of the application bar.
+ */
+class GuidelinesUpdater implements InsetsChangedListener {
+
+ private final View mGuidedView;
+ private final Set<InsetsChangedListener> mListeners = new HashSet<>();
+
+ public GuidelinesUpdater(View guidedView) {
+ mGuidedView = guidedView;
+ }
+
+ public void addListener(InsetsChangedListener listener) {
+ mListeners.add(listener);
+ }
+
+ // Read the results of the base layout measurements and adjust the guidelines to match
+ public void onCarUiInsetsChanged(@NonNull Insets insets) {
+ View startPad = mGuidedView.findViewById(R.id.ui_content_start_guideline);
+ ConstraintLayout.LayoutParams start =
+ (ConstraintLayout.LayoutParams)startPad.getLayoutParams();
+ start.setMargins(insets.getLeft(), 0,0, 0);
+ startPad.setLayoutParams(start);
+
+ View endPad = mGuidedView.findViewById(R.id.ui_content_end_guideline);
+ ConstraintLayout.LayoutParams end = (ConstraintLayout.LayoutParams)endPad.getLayoutParams();
+ end.setMargins(0, 0, insets.getRight(), 0);
+ endPad.setLayoutParams(end);
+
+ View topPad = mGuidedView.findViewById(R.id.ui_content_top_guideline);
+ ConstraintLayout.LayoutParams top = (ConstraintLayout.LayoutParams)topPad.getLayoutParams();
+ top.setMargins(0, insets.getTop(), 0, 0);
+ topPad.setLayoutParams(top);
+
+ View bottomPad = mGuidedView.findViewById(R.id.ui_content_bottom_guideline);
+ ConstraintLayout.LayoutParams bottom =
+ (ConstraintLayout.LayoutParams)bottomPad.getLayoutParams();
+ bottom.setMargins(0, 0, 0, insets.getBottom());
+ bottomPad.setLayoutParams(bottom);
+
+ for (InsetsChangedListener listener : mListeners) {
+ listener.onCarUiInsetsChanged(insets);
+ }
+ }
+}
diff --git a/src/com/android/car/media/MediaActivity.java b/src/com/android/car/media/MediaActivity.java
index 36586d2..21f6d46 100644
--- a/src/com/android/car/media/MediaActivity.java
+++ b/src/com/android/car/media/MediaActivity.java
@@ -18,6 +18,7 @@
import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_BROWSE;
import static com.android.car.apps.common.util.VectorMath.EPSILON;
+import static com.android.car.arch.common.LiveDataFunctions.dataOf;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
@@ -26,12 +27,10 @@
import android.car.Car;
import android.car.content.pm.CarPackageManager;
import android.car.drivingstate.CarUxRestrictions;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
-import android.support.v4.media.session.PlaybackStateCompat;
import android.text.TextUtils;
import android.util.Log;
import android.util.Size;
@@ -51,28 +50,29 @@
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModelProviders;
-import com.android.car.apps.common.util.VectorMath;
import com.android.car.apps.common.util.CarPackageManagerUtils;
+import com.android.car.apps.common.util.VectorMath;
import com.android.car.apps.common.util.ViewUtils;
-import com.android.car.media.common.MediaConstants;
+import com.android.car.arch.common.FutureData;
import com.android.car.media.common.MediaItemMetadata;
import com.android.car.media.common.MinimizedPlaybackControlBar;
+import com.android.car.media.common.PlaybackErrorsHelper;
+import com.android.car.media.common.browse.MediaItemsRepository;
import com.android.car.media.common.playback.PlaybackViewModel;
import com.android.car.media.common.source.MediaSource;
-import com.android.car.media.common.source.MediaSourceViewModel;
import com.android.car.ui.AlertDialogBuilder;
import com.android.car.ui.utils.CarUxRestrictionsUtil;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import java.util.Stack;
/**
* This activity controls the UI of media. It also updates the connection status for the media app
* by broadcast.
*/
-public class MediaActivity extends FragmentActivity implements BrowseViewController.Callbacks {
+public class MediaActivity extends FragmentActivity implements MediaActivityController.Callbacks {
private static final String TAG = "MediaActivity";
/** Configuration (controlled from resources) */
@@ -82,16 +82,13 @@
private PlaybackViewModel.PlaybackController mPlaybackController;
/** Layout views */
- private View mRootView;
private PlaybackFragment mPlaybackFragment;
- private BrowseViewController mSearchController;
- private BrowseViewController mBrowseController;
+ private MediaActivityController mMediaActivityController;
private MinimizedPlaybackControlBar mMiniPlaybackControls;
private ViewGroup mBrowseContainer;
private ViewGroup mPlaybackContainer;
private ViewGroup mErrorContainer;
- private ErrorViewController mErrorController;
- private ViewGroup mSearchContainer;
+ private ErrorScreenController mErrorController;
private Toast mToast;
private AlertDialog mDialog;
@@ -121,42 +118,18 @@
/**
* Possible modes of the application UI
+ * Todo: refactor into non exclusive flags to allow concurrent modes (eg: play details & browse)
+ * (b/179292793).
*/
enum Mode {
- /** The user is browsing a media source */
+ /** The user is browsing or searching a media source */
BROWSING,
/** The user is interacting with the full screen playback UI */
PLAYBACK,
- /** The user is searching within a media source */
- SEARCHING,
/** There's no browse tree and playback doesn't work. */
FATAL_ERROR
}
- private static final Map<Integer, Integer> ERROR_CODE_MESSAGES_MAP;
-
- static {
- Map<Integer, Integer> map = new HashMap<>();
- map.put(PlaybackStateCompat.ERROR_CODE_APP_ERROR, R.string.error_code_app_error);
- map.put(PlaybackStateCompat.ERROR_CODE_NOT_SUPPORTED, R.string.error_code_not_supported);
- map.put(PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED,
- R.string.error_code_authentication_expired);
- map.put(PlaybackStateCompat.ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED,
- R.string.error_code_premium_account_required);
- map.put(PlaybackStateCompat.ERROR_CODE_CONCURRENT_STREAM_LIMIT,
- R.string.error_code_concurrent_stream_limit);
- map.put(PlaybackStateCompat.ERROR_CODE_PARENTAL_CONTROL_RESTRICTED,
- R.string.error_code_parental_control_restricted);
- map.put(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION,
- R.string.error_code_not_available_in_region);
- map.put(PlaybackStateCompat.ERROR_CODE_CONTENT_ALREADY_PLAYING,
- R.string.error_code_content_already_playing);
- map.put(PlaybackStateCompat.ERROR_CODE_SKIP_LIMIT_REACHED,
- R.string.error_code_skip_limit_reached);
- map.put(PlaybackStateCompat.ERROR_CODE_ACTION_ABORTED, R.string.error_code_action_aborted);
- map.put(PlaybackStateCompat.ERROR_CODE_END_OF_QUEUE, R.string.error_code_end_of_queue);
- ERROR_CODE_MESSAGES_MAP = Collections.unmodifiableMap(map);
- }
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -168,8 +141,6 @@
mCloseVectorY = res.getFloat(R.dimen.media_activity_close_vector_y);
mCloseVectorNorm = VectorMath.norm2(mCloseVectorX, mCloseVectorY);
-
- MediaSourceViewModel mediaSourceViewModel = getMediaSourceViewModel();
// TODO(b/151174811): Use appropriate modes, instead of just MEDIA_SOURCE_MODE_BROWSE
PlaybackViewModel playbackViewModel = getPlaybackViewModel();
ViewModel localViewModel = getInnerViewModel();
@@ -182,10 +153,7 @@
}
mMode = localViewModel.getSavedMode();
- mRootView = findViewById(R.id.media_activity_root);
-
- mediaSourceViewModel.getPrimaryMediaSource().observe(this,
- this::onMediaSourceChanged);
+ localViewModel.getBrowsedMediaSource().observe(this, this::onMediaSourceChanged);
mPlaybackFragment = new PlaybackFragment();
mPlaybackFragment.setListener(mPlaybackFragmentListener);
@@ -200,15 +168,12 @@
mBrowseContainer = findViewById(R.id.fragment_container);
mErrorContainer = findViewById(R.id.error_container);
mPlaybackContainer = findViewById(R.id.playback_container);
- mSearchContainer = findViewById(R.id.search_container);
getSupportFragmentManager().beginTransaction()
.replace(R.id.playback_container, mPlaybackFragment)
.commit();
- mBrowseController = BrowseViewController.newInstance(this,
+ mMediaActivityController = new MediaActivityController(this, getMediaItemsRepository(),
mCarPackageManager, mBrowseContainer);
- mSearchController = BrowseViewController.newSearchInstance(this,
- mCarPackageManager, mSearchContainer);
playbackViewModel.getPlaybackController().observe(this,
playbackController -> {
@@ -227,17 +192,13 @@
mCarUxRestrictionsUtil.register(mListener);
mPlaybackContainer.setOnTouchListener(new ClosePlaybackDetector(this));
-
- localViewModel.getMiniControlsVisible().observe(this, visible -> {
- mBrowseController.onPlaybackControlsChanged(visible);
- mSearchController.onPlaybackControlsChanged(visible);
- });
}
@Override
protected void onDestroy() {
mCarUxRestrictionsUtil.unregister(mListener);
mCar.disconnect();
+ mMediaActivityController.onDestroy();
super.onDestroy();
}
@@ -247,97 +208,62 @@
private void handlePlaybackState(PlaybackViewModel.PlaybackStateWrapper state,
boolean ignoreSameState) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG,
- "handlePlaybackState(); state change: " + (mCurrentPlaybackStateWrapper != null
- ? mCurrentPlaybackStateWrapper.getState() : null) + " -> " + (
- state != null ? state.getState() : null));
-
- }
-
- // TODO(arnaudberry) rethink interactions between customized layouts and dynamic visibility.
- mCanShowMiniPlaybackControls = (state != null) && state.shouldDisplay();
- updateMiniPlaybackControls(true);
-
- if (state == null) {
- mCurrentPlaybackStateWrapper = null;
- return;
- }
-
- String displayedMessage = getDisplayedMessage(state);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Displayed error message: [" + displayedMessage + "]");
- }
- if (ignoreSameState && mCurrentPlaybackStateWrapper != null
- && mCurrentPlaybackStateWrapper.getState() == state.getState()
- && TextUtils.equals(displayedMessage,
- getDisplayedMessage(mCurrentPlaybackStateWrapper))) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Ignore same playback state.");
- }
- return;
- }
-
- mCurrentPlaybackStateWrapper = state;
-
- maybeCancelToast();
- maybeCancelDialog();
-
- Bundle extras = state.getExtras();
- PendingIntent intent = extras == null ? null : extras.getParcelable(
- MediaConstants.ERROR_RESOLUTION_ACTION_INTENT);
- String label = extras == null ? null : extras.getString(
- MediaConstants.ERROR_RESOLUTION_ACTION_LABEL);
-
- boolean isFatalError = false;
- if (!TextUtils.isEmpty(displayedMessage)) {
- if (mBrowseController.browseTreeHasChildren()) {
- if (intent != null && !isUxRestricted()) {
- showDialog(intent, displayedMessage, label, getString(android.R.string.cancel));
- } else {
- showToast(displayedMessage);
- }
- } else {
- getErrorController().setError(displayedMessage, label, intent,
- CarPackageManagerUtils.isDistractionOptimized(mCarPackageManager, intent));
- isFatalError = true;
- }
- }
- if (isFatalError) {
- changeMode(Mode.FATAL_ERROR);
- } else if (mMode == Mode.FATAL_ERROR) {
- changeMode(Mode.BROWSING);
- }
+ mErrorsHelper.handlePlaybackState(TAG, state, ignoreSameState);
}
- private ErrorViewController getErrorController() {
+ private final PlaybackErrorsHelper mErrorsHelper = new PlaybackErrorsHelper(this) {
+
+ @Override
+ public void handlePlaybackState(@NonNull String tag,
+ PlaybackViewModel.PlaybackStateWrapper state, boolean ignoreSameState) {
+
+ // TODO rethink interactions between customized layouts and dynamic visibility.
+ mCanShowMiniPlaybackControls = (state != null) && state.shouldDisplay();
+ updateMiniPlaybackControls(true);
+ super.handlePlaybackState(tag, state, ignoreSameState);
+ }
+
+ @Override
+ public void handleNewPlaybackState(String displayedMessage, PendingIntent intent,
+ String label) {
+ maybeCancelToast();
+ maybeCancelDialog();
+
+ boolean isFatalError = false;
+ if (!TextUtils.isEmpty(displayedMessage)) {
+ if (mMediaActivityController.browseTreeHasChildren()) {
+ if (intent != null && !isUxRestricted()) {
+ showDialog(intent, displayedMessage, label,
+ getString(android.R.string.cancel));
+ } else {
+ showToast(displayedMessage);
+ }
+ } else {
+ boolean isDistractionOptimized =
+ intent != null && CarPackageManagerUtils.isDistractionOptimized(
+ mCarPackageManager, intent);
+ getErrorController().setError(displayedMessage, label, intent,
+ isDistractionOptimized);
+ isFatalError = true;
+ }
+ }
+ if (isFatalError) {
+ changeMode(MediaActivity.Mode.FATAL_ERROR);
+ } else if (mMode == MediaActivity.Mode.FATAL_ERROR) {
+ changeMode(MediaActivity.Mode.BROWSING);
+ }
+ }
+ };
+
+ private ErrorScreenController getErrorController() {
if (mErrorController == null) {
- mErrorController = new ErrorViewController(this, mCarPackageManager, mErrorContainer);
- MediaSource mediaSource = getMediaSourceViewModel().getPrimaryMediaSource().getValue();
+ mErrorController = new ErrorScreenController(this, mCarPackageManager, mErrorContainer);
+ MediaSource mediaSource = getInnerViewModel().getMediaSourceValue();
mErrorController.onMediaSourceChanged(mediaSource);
}
return mErrorController;
}
- private String getDisplayedMessage(@Nullable PlaybackViewModel.PlaybackStateWrapper state) {
- if (state == null) {
- return null;
- }
- if (!TextUtils.isEmpty(state.getErrorMessage())) {
- return state.getErrorMessage().toString();
- }
- // ERROR_CODE_UNKNOWN_ERROR means there is no error in PlaybackState.
- if (state.getErrorCode() != PlaybackStateCompat.ERROR_CODE_UNKNOWN_ERROR) {
- Integer messageId = ERROR_CODE_MESSAGES_MAP.get(state.getErrorCode());
- return messageId != null ? getString(messageId) : getString(
- R.string.default_error_message);
- }
- if (state.getState() == PlaybackStateCompat.STATE_ERROR) {
- return getString(R.string.default_error_message);
- }
- return null;
- }
-
private void showDialog(PendingIntent intent, String message, String positiveBtnText,
String negativeButtonText) {
AlertDialogBuilder dialog = new AlertDialogBuilder(this);
@@ -380,11 +306,8 @@
case PLAYBACK:
changeMode(Mode.BROWSING);
break;
- case SEARCHING:
- mSearchController.onBackPressed();
- break;
case BROWSING:
- boolean handled = mBrowseController.onBackPressed();
+ boolean handled = mMediaActivityController.onBackPressed();
if (handled) return;
// Fall through.
case FATAL_ERROR:
@@ -396,41 +319,46 @@
/**
* Sets the media source being browsed.
*
- * @param mediaSource the new media source we are going to try to browse
+ * @param futureSource contains the new media source we are going to try to browse, as well as
+ * the old one (either could be null).
*/
- private void onMediaSourceChanged(@Nullable MediaSource mediaSource) {
- ComponentName savedMediaSource = getInnerViewModel().getSavedMediaSource();
- if (Log.isLoggable(TAG, Log.INFO)) {
- Log.i(TAG, "MediaSource changed from " + savedMediaSource + " to " + mediaSource);
- }
+ private void onMediaSourceChanged(FutureData<MediaSource> futureSource) {
- savedMediaSource = mediaSource != null ? mediaSource.getBrowseServiceComponentName() : null;
- getInnerViewModel().saveMediaSource(savedMediaSource);
+ MediaSource newMediaSource = FutureData.getData(futureSource);
+ MediaSource oldMediaSource = FutureData.getPastData(futureSource);
- mBrowseController.onMediaSourceChanged(mediaSource);
- mSearchController.onMediaSourceChanged(mediaSource);
if (mErrorController != null) {
- mErrorController.onMediaSourceChanged(mediaSource);
+ mErrorController.onMediaSourceChanged(newMediaSource);
}
mCurrentPlaybackStateWrapper = null;
maybeCancelToast();
maybeCancelDialog();
- if (mediaSource != null) {
+ if (newMediaSource != null) {
if (Log.isLoggable(TAG, Log.INFO)) {
- Log.i(TAG, "Browsing: " + mediaSource.getDisplayName());
+ Log.i(TAG, "Browsing: " + newMediaSource.getDisplayName());
}
- Mode mediaSourceMode = getInnerViewModel().getSavedMode();
- // Changes the mode regardless of its previous value so that the views can be updated.
- changeModeInternal(mediaSourceMode, false);
- // Always go through the trampoline activity to keep all the dispatching logic there.
+ if (Objects.equals(oldMediaSource, newMediaSource)) {
+ // The UI is being restored (eg: after a config change) => restore the mode.
+ Mode mediaSourceMode = getInnerViewModel().getSavedMode();
+ changeModeInternal(mediaSourceMode, false);
+ } else {
+ // Change the mode regardless of its previous value to update the views.
+ // The saved mode is ignored as the media apps don't always recreate a playback
+ // state that can be displayed (and some send a displayable state after sending a
+ // non displayable one...).
+ changeModeInternal(Mode.BROWSING, false);
+
+ // Always go through the trampoline activity to keep the dispatching logic there.
+ startActivity(new Intent(Car.CAR_INTENT_ACTION_MEDIA_TEMPLATE));
+ }
+ } else {
startActivity(new Intent(Car.CAR_INTENT_ACTION_MEDIA_TEMPLATE));
}
}
- @Override
- public void changeMode(Mode mode) {
+ private void changeMode(Mode mode) {
if (mMode == mode) {
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Mode " + mMode + " change is ignored");
@@ -458,7 +386,6 @@
ViewUtils.showViewAnimated(mErrorContainer, mFadeDuration);
ViewUtils.hideViewAnimated(mPlaybackContainer, fadeOutDuration);
ViewUtils.hideViewAnimated(mBrowseContainer, fadeOutDuration);
- ViewUtils.hideViewAnimated(mSearchContainer, fadeOutDuration);
break;
case PLAYBACK:
mPlaybackContainer.setX(0);
@@ -467,27 +394,22 @@
ViewUtils.hideViewAnimated(mErrorContainer, fadeOutDuration);
ViewUtils.showViewAnimated(mPlaybackContainer, mFadeDuration);
ViewUtils.hideViewAnimated(mBrowseContainer, fadeOutDuration);
- ViewUtils.hideViewAnimated(mSearchContainer, fadeOutDuration);
break;
case BROWSING:
if (oldMode == Mode.PLAYBACK) {
+ // When switching from PLAYBACK mode to BROWSING mode, if a CarUiRecyclerView
+ // shows up and it's in rotary mode, restore focus in the CarUiRecyclerView.
+ mMediaActivityController.restoreFocusInCurrentNode();
+
ViewUtils.hideViewAnimated(mErrorContainer, 0);
ViewUtils.showViewAnimated(mBrowseContainer, 0);
- ViewUtils.hideViewAnimated(mSearchContainer, 0);
animateOutPlaybackContainer(fadeOutDuration);
} else {
ViewUtils.hideViewAnimated(mErrorContainer, fadeOutDuration);
ViewUtils.hideViewAnimated(mPlaybackContainer, fadeOutDuration);
ViewUtils.showViewAnimated(mBrowseContainer, mFadeDuration);
- ViewUtils.hideViewAnimated(mSearchContainer, fadeOutDuration);
}
break;
- case SEARCHING:
- ViewUtils.hideViewAnimated(mErrorContainer, fadeOutDuration);
- ViewUtils.hideViewAnimated(mPlaybackContainer, fadeOutDuration);
- ViewUtils.hideViewAnimated(mBrowseContainer, fadeOutDuration);
- ViewUtils.showViewAnimated(mSearchContainer, mFadeDuration);
- break;
}
}
@@ -535,9 +457,14 @@
int fadeOutDuration = hideViewAnimated ? mFadeDuration : 0;
// Minimized control bar should be hidden in playback view.
final boolean shouldShowMiniPlaybackControls =
- mCanShowMiniPlaybackControls && mMode != Mode.PLAYBACK;
+ getResources().getBoolean(R.bool.show_mini_playback_controls)
+ && mCanShowMiniPlaybackControls
+ && mMode != Mode.PLAYBACK;
if (shouldShowMiniPlaybackControls) {
- ViewUtils.showViewAnimated(mMiniPlaybackControls, mFadeDuration);
+ Boolean visible = getInnerViewModel().getMiniControlsVisible().getValue();
+ if (visible != Boolean.TRUE) {
+ ViewUtils.showViewAnimated(mMiniPlaybackControls, mFadeDuration);
+ }
} else {
ViewUtils.hideViewAnimated(mMiniPlaybackControls, fadeOutDuration);
}
@@ -545,14 +472,12 @@
}
@Override
- public void onPlayableItemClicked(MediaItemMetadata item) {
+ public void onPlayableItemClicked(@NonNull MediaItemMetadata item) {
mPlaybackController.playItem(item);
boolean switchToPlayback = getResources().getBoolean(
R.bool.switch_to_playback_view_when_playable_item_is_clicked);
if (switchToPlayback) {
changeMode(Mode.PLAYBACK);
- } else if (mMode == Mode.SEARCHING) {
- changeMode(Mode.BROWSING);
}
setIntent(null);
}
@@ -568,8 +493,8 @@
return this;
}
- private MediaSourceViewModel getMediaSourceViewModel() {
- return MediaSourceViewModel.get(getApplication(), MEDIA_SOURCE_MODE_BROWSE);
+ private MediaItemsRepository getMediaItemsRepository() {
+ return MediaItemsRepository.get(getApplication(), MEDIA_SOURCE_MODE_BROWSE);
}
private PlaybackViewModel getPlaybackViewModel() {
@@ -586,14 +511,19 @@
Mode mMode = Mode.BROWSING;
Stack<MediaItemMetadata> mBrowseStack = new Stack<>();
Stack<MediaItemMetadata> mSearchStack = new Stack<>();
+ /** True when the search bar has been opened or when the search results are browsed. */
+ boolean mSearching;
+ /** True iif the list of search results is being shown (implies mIsSearching). */
+ boolean mShowingSearchResults;
String mSearchQuery;
boolean mQueueVisible = false;
}
private boolean mNeedsInitialization = true;
private PlaybackViewModel mPlaybackViewModel;
- private ComponentName mMediaSource;
- private final Map<ComponentName, MediaServiceState> mStates = new HashMap<>();
+ private final MutableLiveData<FutureData<MediaSource>> mBrowsedMediaSource =
+ dataOf(FutureData.newLoadingData());
+ private final Map<MediaSource, MediaServiceState> mStates = new HashMap<>();
private MutableLiveData<Boolean> mIsMiniControlsVisible = new MutableLiveData<>();
public ViewModel(@NonNull Application application) {
@@ -620,11 +550,17 @@
return mIsMiniControlsVisible;
}
+ @Nullable
+ MediaSource getMediaSourceValue() {
+ return FutureData.getData(mBrowsedMediaSource.getValue());
+ }
+
MediaServiceState getSavedState() {
- MediaServiceState state = mStates.get(mMediaSource);
+ MediaSource source = getMediaSourceValue();
+ MediaServiceState state = mStates.get(source);
if (state == null) {
state = new MediaServiceState();
- mStates.put(mMediaSource, state);
+ mStates.put(source, state);
}
return state;
}
@@ -651,26 +587,47 @@
return getSavedState().mQueueVisible;
}
- void saveMediaSource(ComponentName mediaSource) {
- mMediaSource = mediaSource;
+ void saveBrowsedMediaSource(MediaSource mediaSource) {
+ MediaSource oldSource = getMediaSourceValue();
+ if (Log.isLoggable(TAG, Log.INFO)) {
+ Log.i(TAG, "MediaSource changed from " + oldSource + " to " + mediaSource);
+ }
+ mBrowsedMediaSource.setValue(FutureData.newLoadedData(oldSource, mediaSource));
}
- ComponentName getSavedMediaSource() {
- return mMediaSource;
+ LiveData<FutureData<MediaSource>> getBrowsedMediaSource() {
+ return mBrowsedMediaSource;
}
- Stack<MediaItemMetadata> getBrowseStack() {
+ @NonNull Stack<MediaItemMetadata> getBrowseStack() {
return getSavedState().mBrowseStack;
}
- Stack<MediaItemMetadata> getSearchStack() {
+ @NonNull Stack<MediaItemMetadata> getSearchStack() {
return getSavedState().mSearchStack;
}
+ /** Returns whether search mode is on (showing search results or browsing them). */
+ boolean isSearching() {
+ return getSavedState().mSearching;
+ }
+
+ boolean isShowingSearchResults() {
+ return getSavedState().mShowingSearchResults;
+ }
+
String getSearchQuery() {
return getSavedState().mSearchQuery;
}
+ void setSearching(boolean isSearching) {
+ getSavedState().mSearching = isSearching;
+ }
+
+ void setShowingSearchResults(boolean isShowing) {
+ getSavedState().mShowingSearchResults = isShowing;
+ }
+
void setSearchQuery(String searchQuery) {
getSavedState().mSearchQuery = searchQuery;
}
diff --git a/src/com/android/car/media/MediaActivityController.java b/src/com/android/car/media/MediaActivityController.java
new file mode 100644
index 0000000..9a7d39b
--- /dev/null
+++ b/src/com/android/car/media/MediaActivityController.java
@@ -0,0 +1,679 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.media;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+
+import static com.android.car.apps.common.util.ViewUtils.showHideViewAnimated;
+import static com.android.car.ui.utils.ViewUtils.LazyLayoutView;
+
+import android.car.content.pm.CarPackageManager;
+import android.content.Context;
+import android.support.v4.media.MediaBrowserCompat;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+import androidx.lifecycle.Observer;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.apps.common.util.ViewUtils;
+import com.android.car.apps.common.util.ViewUtils.ViewAnimEndListener;
+import com.android.car.arch.common.FutureData;
+import com.android.car.media.common.MediaItemMetadata;
+import com.android.car.media.common.browse.MediaBrowserViewModelImpl;
+import com.android.car.media.common.browse.MediaItemsRepository;
+import com.android.car.media.common.browse.MediaItemsRepository.MediaItemsLiveData;
+import com.android.car.media.common.source.MediaBrowserConnector.BrowsingState;
+import com.android.car.media.common.source.MediaSource;
+import com.android.car.media.widgets.AppBarController;
+import com.android.car.ui.FocusParkingView;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.Toolbar;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Stack;
+
+/**
+ * Controls the views of the {@link MediaActivity}.
+ * TODO: finish moving control code out of MediaActivity (b/179292809).
+ */
+public class MediaActivityController extends ViewControllerBase {
+
+ private static final String TAG = "MediaActivityCtr";
+
+ private final MediaItemsRepository mMediaItemsRepository;
+ private final Callbacks mCallbacks;
+ private final ViewGroup mBrowseArea;
+ private final FocusParkingView mFpv;
+ private Insets mCarUiInsets;
+ private boolean mPlaybackControlsVisible;
+
+ private final Map<MediaItemMetadata, BrowseViewController> mBrowseViewControllersByNode =
+ new HashMap<>();
+
+ // Controllers that should be destroyed once their view is hidden.
+ private final Map<View, BrowseViewController> mBrowseViewControllersToDestroy = new HashMap<>();
+
+ private final BrowseViewController mRootLoadingController;
+ private final BrowseViewController mSearchResultsController;
+
+ /**
+ * Stores the reference to {@link MediaActivity.ViewModel#getBrowseStack}.
+ * Updated in {@link #onMediaSourceChanged}.
+ */
+ private Stack<MediaItemMetadata> mBrowseStack;
+ /**
+ * Stores the reference to {@link MediaActivity.ViewModel#getSearchStack}.
+ * Updated in {@link #onMediaSourceChanged}.
+ */
+ private Stack<MediaItemMetadata> mSearchStack;
+ private final MediaActivity.ViewModel mViewModel;
+
+ private int mRootBrowsableHint;
+ private int mRootPlayableHint;
+ private boolean mBrowseTreeHasChildren;
+ private boolean mAcceptTabSelection = true;
+
+ /**
+ * Media items to display as tabs. If null, it means we haven't finished loading them yet. If
+ * empty, it means there are no tabs to show
+ */
+ @Nullable
+ private List<MediaItemMetadata> mTopItems;
+
+ private final Observer<BrowsingState> mMediaBrowsingObserver =
+ this::onMediaBrowsingStateChanged;
+
+ /**
+ * Callbacks (implemented by the hosting Activity)
+ */
+ public interface Callbacks {
+
+ /** Invoked when the user clicks on a browsable item. */
+ void onPlayableItemClicked(@NonNull MediaItemMetadata item);
+
+ /** Called once the list of the root node's children has been loaded. */
+ void onRootLoaded();
+
+ /** Returns the activity. */
+ FragmentActivity getActivity();
+ }
+
+ /**
+ * Moves the user one level up in the browse/search tree. Returns whether that was possible.
+ */
+ private boolean navigateBack() {
+ boolean result = false;
+ if (!isAtTopStack()) {
+ hideAndDestroyControllerForItem(getStack().pop());
+
+ // Show the parent (if any)
+ showCurrentNode(true);
+
+ if (isAtTopStack() && mViewModel.isSearching()) {
+ showSearchResults(true);
+ }
+
+ updateAppBar();
+ result = true;
+ }
+ return result;
+ }
+
+ private void reopenSearch() {
+ clearStack(mSearchStack);
+ showSearchResults(true);
+ updateAppBar();
+ }
+
+ private FragmentActivity getActivity() {
+ return mCallbacks.getActivity();
+ }
+
+ /** Returns the browse or search stack. */
+ private Stack<MediaItemMetadata> getStack() {
+ return mViewModel.isSearching() ? mSearchStack : mBrowseStack;
+ }
+
+ /**
+ * @return whether the user is at the top of the browsing stack.
+ */
+ private boolean isAtTopStack() {
+ if (mViewModel.isSearching()) {
+ return mSearchStack.isEmpty();
+ } else {
+ // The mBrowseStack stack includes the tab...
+ return mBrowseStack.size() <= 1;
+ }
+ }
+
+ private void clearMediaSource() {
+ showSearchMode(false);
+ for (BrowseViewController controller : mBrowseViewControllersByNode.values()) {
+ controller.destroy();
+ }
+ mBrowseViewControllersByNode.clear();
+ mBrowseTreeHasChildren = false;
+ }
+
+ private void updateSearchQuery(@Nullable String query) {
+ mMediaItemsRepository.setSearchQuery(query);
+ }
+
+ /**
+ * Clears search state, removes any UI elements from previous results.
+ */
+ @Override
+ void onMediaSourceChanged(@Nullable MediaSource mediaSource) {
+ super.onMediaSourceChanged(mediaSource);
+
+ updateTabs((mediaSource != null) ? null : new ArrayList<>());
+
+ mSearchStack = mViewModel.getSearchStack();
+ mBrowseStack = mViewModel.getBrowseStack();
+
+ updateAppBar();
+ }
+
+ private void onMediaBrowsingStateChanged(BrowsingState newBrowsingState) {
+ switch (newBrowsingState.mConnectionStatus) {
+ case CONNECTING:
+ break;
+ case CONNECTED:
+ MediaBrowserCompat browser = newBrowsingState.mBrowser;
+ mRootBrowsableHint = MediaBrowserViewModelImpl.getRootBrowsableHint(browser);
+ mRootPlayableHint = MediaBrowserViewModelImpl.getRootPlayableHint(browser);
+
+ boolean canSearch = MediaBrowserViewModelImpl.getSupportsSearch(browser);
+ mAppBarController.setSearchSupported(canSearch);
+ break;
+
+ case DISCONNECTING:
+ case REJECTED:
+ case SUSPENDED:
+ clearMediaSource();
+ break;
+ }
+
+ mViewModel.saveBrowsedMediaSource(newBrowsingState.mMediaSource);
+ }
+
+
+ MediaActivityController(Callbacks callbacks, MediaItemsRepository mediaItemsRepo,
+ CarPackageManager carPackageManager, ViewGroup container) {
+ super(callbacks.getActivity(), carPackageManager, container, R.layout.fragment_browse);
+
+ FragmentActivity activity = callbacks.getActivity();
+ mCallbacks = callbacks;
+ mMediaItemsRepository = mediaItemsRepo;
+ mViewModel = ViewModelProviders.of(activity).get(MediaActivity.ViewModel.class);
+ mSearchStack = mViewModel.getSearchStack();
+ mBrowseStack = mViewModel.getBrowseStack();
+ mBrowseArea = mContent.requireViewById(R.id.browse_content_area);
+ mFpv = activity.requireViewById(R.id.fpv);
+
+ MediaItemsLiveData rootMediaItems = mediaItemsRepo.getRootMediaItems();
+ mRootLoadingController = BrowseViewController.newRootController(
+ mBrowseCallbacks, mBrowseArea, rootMediaItems);
+ mRootLoadingController.getContent().setAlpha(1f);
+
+ mSearchResultsController = BrowseViewController.newSearchResultsController(
+ mBrowseCallbacks, mBrowseArea, mMediaItemsRepository.getSearchMediaItems());
+
+ boolean showingSearch = mViewModel.isShowingSearchResults();
+ ViewUtils.setVisible(mSearchResultsController.getContent(), showingSearch);
+ if (showingSearch) {
+ mSearchResultsController.getContent().setAlpha(1f);
+ }
+
+ mAppBarController.setListener(mAppBarListener);
+ mAppBarController.setSearchQuery(mViewModel.getSearchQuery());
+ if (mAppBarController.canShowSearchResultsView()) {
+ // TODO(b/180441965) eliminate the need to create a different view and use
+ // mSearchResultsController.getContent() instead.
+ RecyclerView toolbarSearchResultsView = new RecyclerView(activity);
+ mSearchResultsController.shareBrowseAdapterWith(toolbarSearchResultsView);
+
+ ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ toolbarSearchResultsView.setLayoutParams(params);
+ toolbarSearchResultsView.setLayoutManager(new LinearLayoutManager(activity));
+ toolbarSearchResultsView.setBackground(
+ activity.getDrawable(R.drawable.car_ui_ime_wide_screen_background));
+
+ mAppBarController.setSearchResultsView(toolbarSearchResultsView);
+ }
+
+ updateAppBar();
+
+ // Observe forever ensures the caches are destroyed even while the activity isn't resumed.
+ mediaItemsRepo.getBrowsingState().observeForever(mMediaBrowsingObserver);
+
+ mViewModel.getBrowsedMediaSource().observeForever(future -> {
+ onMediaSourceChanged(future.isLoading() ? null : future.getData());
+ });
+
+ rootMediaItems.observe(activity, this::onRootMediaItemsUpdate);
+ mViewModel.getMiniControlsVisible().observe(activity, this::onPlaybackControlsChanged);
+ }
+
+ void onDestroy() {
+ mMediaItemsRepository.getBrowsingState().removeObserver(mMediaBrowsingObserver);
+ }
+
+ private AppBarController.AppBarListener mAppBarListener = new BasicAppBarListener() {
+ @Override
+ public void onTabSelected(MediaItemMetadata item) {
+ if (mAcceptTabSelection && (item != null) && (item != mViewModel.getSelectedTab())) {
+ clearStack(mBrowseStack);
+ mBrowseStack.push(item);
+ showCurrentNode(true);
+ }
+ }
+
+ @Override
+ public void onSearchSelection() {
+ if (mViewModel.isSearching()) {
+ reopenSearch();
+ } else {
+ showSearchMode(true);
+ updateAppBar();
+ }
+ }
+
+ @Override
+ public void onSearch(String query) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onSearch: " + query);
+ }
+ mViewModel.setSearchQuery(query);
+ updateSearchQuery(query);
+ }
+ };
+
+ private final BrowseViewController.Callbacks mBrowseCallbacks =
+ new BrowseViewController.Callbacks() {
+ @Override
+ public void onPlayableItemClicked(@NonNull MediaItemMetadata item) {
+ hideKeyboard();
+ mCallbacks.onPlayableItemClicked(item);
+ }
+
+ @Override
+ public void onBrowsableItemClicked(@NonNull MediaItemMetadata item) {
+ hideKeyboard();
+ navigateInto(item);
+ }
+
+ @Override
+ public void onChildrenNodesRemoved(@NonNull BrowseViewController controller,
+ @NonNull Collection<MediaItemMetadata> removedNodes) {
+
+ if (mBrowseStack.contains(controller.getParentItem())) {
+ for (MediaItemMetadata node : removedNodes) {
+ int indexOfNode = mBrowseStack.indexOf(node);
+ if (indexOfNode >= 0) {
+ clearStack(mBrowseStack.subList(indexOfNode, mBrowseStack.size()));
+ if (!mViewModel.isShowingSearchResults()) {
+ showCurrentNode(true);
+ updateAppBar();
+ }
+ break; // The stack contains at most one of the removed nodes.
+ }
+ }
+ }
+ }
+
+ @Override
+ public FragmentActivity getActivity() {
+ return mCallbacks.getActivity();
+ }
+ };
+
+ private final ViewAnimEndListener mViewAnimEndListener = view -> {
+ BrowseViewController toDestroy = mBrowseViewControllersToDestroy.remove(view);
+ if (toDestroy != null) {
+ toDestroy.destroy();
+ }
+ };
+
+ boolean onBackPressed() {
+ boolean success = navigateBack();
+ if (!success && mViewModel.isSearching()) {
+ showSearchMode(false);
+ updateAppBar();
+ success = true;
+ }
+ if (success) {
+ // When the back button is pressed, if a CarUiRecyclerView shows up and it's in rotary
+ // mode, restore focus in the CarUiRecyclerView.
+ restoreFocusInCurrentNode();
+ }
+ return success;
+ }
+
+ boolean browseTreeHasChildren() {
+ return mBrowseTreeHasChildren;
+ }
+
+ private void navigateInto(@NonNull MediaItemMetadata item) {
+ showSearchResults(false);
+
+ // Hide the current node (parent)
+ showCurrentNode(false);
+
+ // Make item the current node
+ getStack().push(item);
+
+ // Show the current node (item)
+ showCurrentNode(true);
+
+ updateAppBar();
+ }
+
+ private BrowseViewController getControllerForItem(@NonNull MediaItemMetadata item) {
+ BrowseViewController controller = mBrowseViewControllersByNode.get(item);
+ if (controller == null) {
+ controller = BrowseViewController.newBrowseController(mBrowseCallbacks, mBrowseArea,
+ item, mMediaItemsRepository.getMediaChildren(item.getId()), mRootBrowsableHint,
+ mRootPlayableHint);
+
+ if (mCarUiInsets != null) {
+ controller.onCarUiInsetsChanged(mCarUiInsets);
+ }
+ controller.onPlaybackControlsChanged(mPlaybackControlsVisible);
+
+ mBrowseViewControllersByNode.put(item, controller);
+ }
+ return controller;
+ }
+
+ private void showCurrentNode(boolean show) {
+ MediaItemMetadata currentNode = getCurrentMediaItem();
+ if (currentNode == null) {
+ return;
+ }
+ // Only create a controller to show it.
+ BrowseViewController controller = show ? getControllerForItem(currentNode) :
+ mBrowseViewControllersByNode.get(currentNode);
+
+ if (controller != null) {
+ showHideContentAnimated(show, controller.getContent(), mViewAnimEndListener);
+ }
+ }
+
+ // If the current node has a CarUiRecyclerView and it's in rotary mode, restore focus in it.
+ void restoreFocusInCurrentNode() {
+ MediaItemMetadata currentNode = getCurrentMediaItem();
+ if (currentNode == null) {
+ return;
+ }
+ BrowseViewController controller = getControllerForItem(currentNode);
+ if (controller == null) {
+ return;
+ }
+ CarUiRecyclerView carUiRecyclerView =
+ controller.getContent().findViewById(R.id.browse_list);
+ if (carUiRecyclerView != null && carUiRecyclerView instanceof LazyLayoutView
+ && !carUiRecyclerView.hasFocus() && !carUiRecyclerView.isInTouchMode()) {
+ LazyLayoutView lazyLayoutView = (LazyLayoutView) carUiRecyclerView;
+ com.android.car.ui.utils.ViewUtils.initFocus(lazyLayoutView);
+ }
+ }
+
+ private void showHideContentAnimated(boolean show, @NonNull View content,
+ @Nullable ViewAnimEndListener listener) {
+ CarUiRecyclerView carUiRecyclerView = content.findViewById(R.id.browse_list);
+ if (carUiRecyclerView != null && carUiRecyclerView instanceof LazyLayoutView
+ && !carUiRecyclerView.isInTouchMode()) {
+ // If a CarUiRecyclerView is about to hide and it has focus, park the focus on the
+ // FocusParkingView before hiding the CarUiRecyclerView. Otherwise hiding the focused
+ // view will cause the Android framework to move focus to another view, causing visual
+ // jank.
+ if (!show && carUiRecyclerView.hasFocus()) {
+ mFpv.performAccessibilityAction(ACTION_FOCUS, null);
+ }
+ // If a new CarUiRecyclerView is about to show and there is no view focused or the
+ // FocusParkingView is focused, restore focus in the new CarUiRecyclerView.
+ if (show) {
+ View focusedView = carUiRecyclerView.getRootView().findFocus();
+ if (focusedView == null || focusedView instanceof FocusParkingView) {
+ LazyLayoutView lazyLayoutView = (LazyLayoutView) carUiRecyclerView;
+ com.android.car.ui.utils.ViewUtils.initFocus(lazyLayoutView);
+ }
+ }
+ }
+
+ showHideViewAnimated(show, content, mFadeDuration, listener);
+ }
+
+
+
+ private void showSearchResults(boolean show) {
+ if (mViewModel.isShowingSearchResults() != show) {
+ mViewModel.setShowingSearchResults(show);
+ showHideContentAnimated(show, mSearchResultsController.getContent(), null);
+ }
+ }
+
+ private void showSearchMode(boolean show) {
+ if (mViewModel.isSearching() != show) {
+ if (show) {
+ showCurrentNode(false);
+ }
+
+ mViewModel.setSearching(show);
+ showSearchResults(show);
+
+ if (!show) {
+ showCurrentNode(true);
+ }
+ }
+ }
+
+ /**
+ * @return the current item being displayed
+ */
+ @Nullable
+ private MediaItemMetadata getCurrentMediaItem() {
+ Stack<MediaItemMetadata> stack = getStack();
+ return stack.isEmpty() ? null : stack.lastElement();
+ }
+
+ @Override
+ public void onCarUiInsetsChanged(@NonNull Insets insets) {
+ mCarUiInsets = insets;
+ for (BrowseViewController controller : mBrowseViewControllersByNode.values()) {
+ controller.onCarUiInsetsChanged(mCarUiInsets);
+ }
+ mRootLoadingController.onCarUiInsetsChanged(mCarUiInsets);
+ mSearchResultsController.onCarUiInsetsChanged(mCarUiInsets);
+ }
+
+ void onPlaybackControlsChanged(boolean visible) {
+ mPlaybackControlsVisible = visible;
+ for (BrowseViewController controller : mBrowseViewControllersByNode.values()) {
+ controller.onPlaybackControlsChanged(mPlaybackControlsVisible);
+ }
+ mRootLoadingController.onPlaybackControlsChanged(mPlaybackControlsVisible);
+ mSearchResultsController.onPlaybackControlsChanged(mPlaybackControlsVisible);
+ }
+
+ private void hideKeyboard() {
+ InputMethodManager in =
+ (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ in.hideSoftInputFromWindow(mContent.getWindowToken(), 0);
+ }
+
+ private void hideAndDestroyControllerForItem(@Nullable MediaItemMetadata item) {
+ if (item == null) {
+ return;
+ }
+ BrowseViewController controller = mBrowseViewControllersByNode.get(item);
+ if (controller == null) {
+ return;
+ }
+
+ if (controller.getContent().getVisibility() == View.VISIBLE) {
+ View view = controller.getContent();
+ mBrowseViewControllersToDestroy.put(view, controller);
+ showHideContentAnimated(false, view, mViewAnimEndListener);
+ } else {
+ controller.destroy();
+ }
+ mBrowseViewControllersByNode.remove(item);
+ }
+
+ /**
+ * Clears the given stack (or a portion of a stack) and destroys the old controllers (after
+ * their view is hidden).
+ */
+ private void clearStack(List<MediaItemMetadata> stack) {
+ for (MediaItemMetadata item : stack) {
+ hideAndDestroyControllerForItem(item);
+ }
+ stack.clear();
+ }
+
+ /**
+ * Updates the tabs displayed on the app bar, based on the top level items on the browse tree.
+ * If there is at least one browsable item, we show the browse content of that node. If there
+ * are only playable items, then we show those items. If there are not items at all, we show the
+ * empty message. If we receive null, we show the error message.
+ *
+ * @param items top level items, null if the items are still being loaded, or empty list if
+ * items couldn't be loaded.
+ */
+ private void updateTabs(@Nullable List<MediaItemMetadata> items) {
+ if (Objects.equals(mTopItems, items)) {
+ // When coming back to the app, the live data sends an update even if the list hasn't
+ // changed. Updating the tabs then recreates the browse view, which produces jank
+ // (b/131830876), and also resets the navigation to the top of the first tab...
+ return;
+ }
+ mTopItems = items;
+
+ if (mTopItems == null || mTopItems.isEmpty()) {
+ mAppBarController.setItems(null);
+ mAppBarController.setActiveItem(null);
+ if (items != null) {
+ // Only do this when not loading the tabs or we loose the saved one.
+ clearStack(mBrowseStack);
+ }
+ updateAppBar();
+ return;
+ }
+
+ MediaItemMetadata oldTab = mViewModel.getSelectedTab();
+ MediaItemMetadata newTab = items.contains(oldTab) ? oldTab : items.get(0);
+
+ try {
+ mAcceptTabSelection = false;
+ mAppBarController.setItems(mTopItems.size() == 1 ? null : mTopItems);
+ mAppBarController.setActiveItem(newTab);
+
+ if (oldTab != newTab) {
+ // Tabs belong to the browse stack.
+ clearStack(mBrowseStack);
+ mBrowseStack.push(newTab);
+ }
+
+ if (!mViewModel.isShowingSearchResults()) {
+ // Needed when coming back to an app after a config change or from another app,
+ // or when the tab actually changes.
+ showCurrentNode(true);
+ }
+ } finally {
+ mAcceptTabSelection = true;
+ }
+ updateAppBar();
+ }
+
+ private void updateAppBarTitle() {
+ boolean isStacked = !isAtTopStack();
+
+ final CharSequence title;
+ if (isStacked) {
+ // If not at top level, show the current item as title
+ title = getCurrentMediaItem().getTitle();
+ } else if (mTopItems == null) {
+ // If still loading the tabs, force to show an empty bar.
+ title = "";
+ } else if (mTopItems.size() == 1) {
+ // If we finished loading tabs and there is only one, use that as title.
+ title = mTopItems.get(0).getTitle();
+ } else {
+ // Otherwise (no tabs or more than 1 tabs), show the current media source title.
+ MediaSource mediaSource = mMediaSourceVM.getPrimaryMediaSource().getValue();
+ title = getAppBarDefaultTitle(mediaSource);
+ }
+
+ mAppBarController.setTitle(title);
+ }
+
+ /**
+ * Update elements of the appbar that change depending on where we are in the browse.
+ */
+ private void updateAppBar() {
+ boolean isSearching = mViewModel.isSearching();
+ boolean isStacked = !isAtTopStack();
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "App bar is in stacked state: " + isStacked);
+ }
+ Toolbar.State unstackedState = isSearching ? Toolbar.State.SEARCH : Toolbar.State.HOME;
+ updateAppBarTitle();
+ mAppBarController.setState(isStacked ? Toolbar.State.SUBPAGE : unstackedState);
+ mAppBarController.showSearchIfSupported(!isSearching || isStacked);
+ }
+
+ private void onRootMediaItemsUpdate(FutureData<List<MediaItemMetadata>> data) {
+ if (data.isLoading()) {
+ if (Log.isLoggable(TAG, Log.INFO)) {
+ Log.i(TAG, "Loading browse tree...");
+ }
+ mBrowseTreeHasChildren = false;
+ updateTabs(null);
+ return;
+ }
+
+ List<MediaItemMetadata> items =
+ MediaBrowserViewModelImpl.filterItems(/*forRoot*/ true, data.getData());
+
+ boolean browseTreeHasChildren = items != null && !items.isEmpty();
+ if (Log.isLoggable(TAG, Log.INFO)) {
+ Log.i(TAG, "Browse tree loaded, status (has children or not) changed: "
+ + mBrowseTreeHasChildren + " -> " + browseTreeHasChildren);
+ }
+ mBrowseTreeHasChildren = browseTreeHasChildren;
+ mCallbacks.onRootLoaded();
+ updateTabs(items != null ? items : new ArrayList<>());
+ }
+
+}
diff --git a/src/com/android/car/media/MediaDispatcherActivity.java b/src/com/android/car/media/MediaDispatcherActivity.java
index b44feb9..973937b 100644
--- a/src/com/android/car/media/MediaDispatcherActivity.java
+++ b/src/com/android/car/media/MediaDispatcherActivity.java
@@ -67,6 +67,8 @@
// Launch custom app (e.g. Radio)
String srcPackage = mediaSrc.getPackageName();
newIntent = getPackageManager().getLaunchIntentForPackage(srcPackage);
+ newIntent.putExtra(Car.CAR_EXTRA_MEDIA_COMPONENT,
+ mediaSrc.getBrowseServiceComponentName().flattenToString());
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Getting launch intent for package : " + srcPackage + (newIntent != null
? " succeeded" : " failed"));
diff --git a/src/com/android/car/media/PlaybackFragment.java b/src/com/android/car/media/PlaybackFragment.java
index dcaf7dc..cbf1ade 100644
--- a/src/com/android/car/media/PlaybackFragment.java
+++ b/src/com/android/car/media/PlaybackFragment.java
@@ -21,9 +21,11 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
-import android.graphics.Bitmap;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.util.Log;
import android.util.Size;
@@ -51,8 +53,16 @@
import com.android.car.media.common.PlaybackControlsActionBar;
import com.android.car.media.common.playback.PlaybackViewModel;
import com.android.car.media.common.source.MediaSourceViewModel;
+import com.android.car.media.widgets.AppBarController;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.recyclerview.ContentLimiting;
+import com.android.car.ui.recyclerview.ScrollingLimitedViewHolder;
import com.android.car.ui.toolbar.MenuItem;
import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+import com.android.car.ui.utils.DirectManipulationHelper;
+import com.android.car.uxr.LifeCycleObserverUxrContentLimiter;
+import com.android.car.uxr.UxrContentLimiterImpl;
import java.util.ArrayList;
import java.util.Collections;
@@ -68,7 +78,9 @@
public class PlaybackFragment extends Fragment {
private static final String TAG = "PlaybackFragment";
+ private LifeCycleObserverUxrContentLimiter mUxrContentLimiter;
private ImageBinder<MediaItemMetadata.ArtworkRef> mAlbumArtBinder;
+ private AppBarController mAppBarController;
private BackgroundImageView mAlbumBackground;
private View mBackgroundScrim;
private View mControlBarScrim;
@@ -77,7 +89,6 @@
private RecyclerView mQueue;
private ViewGroup mSeekBarContainer;
private SeekBar mSeekBar;
- private Toolbar mToolbar;
private List<View> mViewsToHideForCustomActions;
private List<View> mViewsToHideWhenQueueIsVisible;
private List<View> mViewsToShowWhenQueueIsVisible;
@@ -106,6 +117,8 @@
private MediaActivity.ViewModel mViewModel;
+ private MenuItem mQueueMenuItem;
+
/**
* PlaybackFragment listener
*/
@@ -199,13 +212,47 @@
}
- private class QueueItemsAdapter extends RecyclerView.Adapter<QueueViewHolder> {
+ private class QueueItemsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
+ implements ContentLimiting {
+ private static final int CLAMPED_MESSAGE_VIEW_TYPE = -1;
+ private static final int QUEUE_ITEM_VIEW_TYPE = 0;
+
+ private UxrPivotFilter mUxrPivotFilter;
private List<MediaItemMetadata> mQueueItems = Collections.emptyList();
private String mCurrentTimeText = "";
private String mMaxTimeText = "";
- private Integer mActiveItemPos;
+ /** Index in {@link #mQueueItems}. */
+ private Integer mActiveItemIndex;
private boolean mTimeVisible;
+ private Integer mScrollingLimitedMessageResId;
+
+ QueueItemsAdapter() {
+ mUxrPivotFilter = UxrPivotFilter.PASS_THROUGH;
+ }
+
+ @Override
+ public void setMaxItems(int maxItems) {
+ if (maxItems >= 0) {
+ mUxrPivotFilter = new UxrPivotFilterImpl(this, maxItems);
+ } else {
+ mUxrPivotFilter = UxrPivotFilter.PASS_THROUGH;
+ }
+ applyFilterToQueue();
+ }
+
+ @Override
+ public void setScrollingLimitedMessageResId(int resId) {
+ if (mScrollingLimitedMessageResId == null || mScrollingLimitedMessageResId != resId) {
+ mScrollingLimitedMessageResId = resId;
+ mUxrPivotFilter.invalidateMessagePositions();
+ }
+ }
+
+ @Override
+ public int getConfigurationId() {
+ return R.id.playback_fragment_now_playing_list_uxr_config;
+ }
void setItems(@Nullable List<MediaItemMetadata> items) {
List<MediaItemMetadata> newQueueItems =
@@ -214,62 +261,97 @@
return;
}
mQueueItems = newQueueItems;
- updateActiveItem();
+ updateActiveItem(/* listIsNew */ true);
+ }
+
+ private int getActiveItemIndex() {
+ return mActiveItemIndex != null ? mActiveItemIndex : 0;
+ }
+
+ private int getQueueSize() {
+ return (mQueueItems != null) ? mQueueItems.size() : 0;
+ }
+
+
+ /**
+ * Returns the position of the active item if there is one, otherwise returns
+ * @link UxrPivotFilter#INVALID_POSITION}.
+ */
+ private int getActiveItemPosition() {
+ if (mActiveItemIndex == null) {
+ return UxrPivotFilter.INVALID_POSITION;
+ }
+ return mUxrPivotFilter.indexToPosition(mActiveItemIndex);
+ }
+
+ private void invalidateActiveItemPosition() {
+ int position = getActiveItemPosition();
+ if (position != UxrPivotFilterImpl.INVALID_POSITION) {
+ notifyItemChanged(position);
+ }
+ }
+
+ private void scrollToActiveItemPosition() {
+ int position = getActiveItemPosition();
+ if (position != UxrPivotFilterImpl.INVALID_POSITION) {
+ mQueue.scrollToPosition(position);
+ }
+ }
+
+ private void applyFilterToQueue() {
+ mUxrPivotFilter.recompute(getQueueSize(), getActiveItemIndex());
notifyDataSetChanged();
}
// Updates mActiveItemPos, then scrolls the queue to mActiveItemPos.
// It should be called when the active item (mActiveQueueItemId) changed or
// the queue items (mQueueItems) changed.
- void updateActiveItem() {
+ void updateActiveItem(boolean listIsNew) {
if (mQueueItems == null || mActiveQueueItemId == null) {
- mActiveItemPos = null;
+ mActiveItemIndex = null;
+ applyFilterToQueue();
return;
}
Integer activeItemPos = null;
for (int i = 0; i < mQueueItems.size(); i++) {
- if (mQueueItems.get(i).getQueueId() == mActiveQueueItemId) {
+ if (Objects.equals(mQueueItems.get(i).getQueueId(), mActiveQueueItemId)) {
activeItemPos = i;
break;
}
}
- if (mActiveItemPos != activeItemPos) {
- if (mActiveItemPos != null) {
- notifyItemChanged(mActiveItemPos.intValue());
- }
- mActiveItemPos = activeItemPos;
- if (mActiveItemPos != null) {
- mQueue.scrollToPosition(mActiveItemPos.intValue());
- notifyItemChanged(mActiveItemPos.intValue());
- }
+ // Invalidate the previous active item so it gets redrawn as a normal one.
+ invalidateActiveItemPosition();
+
+ mActiveItemIndex = activeItemPos;
+ if (listIsNew) {
+ applyFilterToQueue();
+ } else {
+ mUxrPivotFilter.updatePivotIndex(getActiveItemIndex());
}
+
+ scrollToActiveItemPosition();
+ invalidateActiveItemPosition();
}
void setCurrentTime(String currentTime) {
if (!mCurrentTimeText.equals(currentTime)) {
mCurrentTimeText = currentTime;
- if (mActiveItemPos != null) {
- notifyItemChanged(mActiveItemPos.intValue());
- }
+ invalidateActiveItemPosition();
}
}
void setMaxTime(String maxTime) {
if (!mMaxTimeText.equals(maxTime)) {
mMaxTimeText = maxTime;
- if (mActiveItemPos != null) {
- notifyItemChanged(mActiveItemPos.intValue());
- }
+ invalidateActiveItemPosition();
}
}
void setTimeVisible(boolean visible) {
if (mTimeVisible != visible) {
mTimeVisible = visible;
- if (mActiveItemPos != null) {
- notifyItemChanged(mActiveItemPos.intValue());
- }
+ invalidateActiveItemPosition();
}
}
@@ -286,51 +368,83 @@
}
@Override
- public QueueViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ public final int getItemViewType(int position) {
+ if (mUxrPivotFilter.positionToIndex(position) == UxrPivotFilterImpl.INVALID_INDEX) {
+ return CLAMPED_MESSAGE_VIEW_TYPE;
+ } else {
+ return QUEUE_ITEM_VIEW_TYPE;
+ }
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ if (viewType == CLAMPED_MESSAGE_VIEW_TYPE) {
+ return ScrollingLimitedViewHolder.create(parent);
+ }
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new QueueViewHolder(inflater.inflate(R.layout.queue_list_item, parent, false));
}
@Override
- public void onBindViewHolder(QueueViewHolder holder, int position) {
- int size = mQueueItems.size();
- if (0 <= position && position < size) {
- holder.bind(mQueueItems.get(position));
+ public void onBindViewHolder(RecyclerView.ViewHolder vh, int position) {
+ if (vh instanceof QueueViewHolder) {
+ int index = mUxrPivotFilter.positionToIndex(position);
+ if (index != UxrPivotFilterImpl.INVALID_INDEX) {
+ int size = mQueueItems.size();
+ if (0 <= index && index < size) {
+ QueueViewHolder holder = (QueueViewHolder) vh;
+ holder.bind(mQueueItems.get(index));
+ } else {
+ Log.e(TAG, "onBindViewHolder pos: " + position + " gave index: " + index +
+ " out of bounds size: " + size + " " + mUxrPivotFilter.toString());
+ }
+ } else {
+ Log.e(TAG, "onBindViewHolder invalid position " + position + " " +
+ mUxrPivotFilter.toString());
+ }
+ } else if (vh instanceof ScrollingLimitedViewHolder) {
+ ScrollingLimitedViewHolder holder = (ScrollingLimitedViewHolder) vh;
+ holder.bind(mScrollingLimitedMessageResId);
} else {
- Log.e(TAG, "onBindViewHolder invalid position " + position + " of " + size);
+ throw new IllegalArgumentException("unknown holder class " + vh.getClass());
}
}
@Override
- public void onViewAttachedToWindow(@NonNull QueueViewHolder holder) {
- super.onViewAttachedToWindow(holder);
- holder.onViewAttachedToWindow();
+ public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder vh) {
+ super.onViewAttachedToWindow(vh);
+ if (vh instanceof QueueViewHolder) {
+ QueueViewHolder holder = (QueueViewHolder) vh;
+ holder.onViewAttachedToWindow();
+ }
}
@Override
- public void onViewDetachedFromWindow(@NonNull QueueViewHolder holder) {
- super.onViewDetachedFromWindow(holder);
- holder.onViewDetachedFromWindow();
+ public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder vh) {
+ super.onViewDetachedFromWindow(vh);
+ if (vh instanceof QueueViewHolder) {
+ QueueViewHolder holder = (QueueViewHolder) vh;
+ holder.onViewDetachedFromWindow();
+ }
}
@Override
public int getItemCount() {
- return mQueueItems.size();
- }
-
- void refresh() {
- // TODO: Perform a diff between current and new content and trigger the proper
- // RecyclerView updates.
- this.notifyDataSetChanged();
+ return mUxrPivotFilter.getFilteredCount();
}
@Override
public long getItemId(int position) {
- return mQueueItems.get(position).getQueueId();
+ int index = mUxrPivotFilter.positionToIndex(position);
+ if (index != UxrPivotFilterImpl.INVALID_INDEX) {
+ return mQueueItems.get(position).getQueueId();
+ } else {
+ return RecyclerView.NO_ID;
+ }
}
}
- private class QueueTopItemDecoration extends RecyclerView.ItemDecoration {
+ private static class QueueTopItemDecoration extends RecyclerView.ItemDecoration {
int mHeight;
int mDecorationPosition;
@@ -352,31 +466,33 @@
@Override
public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.fragment_playback, container, false);
+ return inflater.inflate(R.layout.fragment_playback, container, false);
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
mAlbumBackground = view.findViewById(R.id.playback_background);
mQueue = view.findViewById(R.id.queue_list);
- mSeekBarContainer = view.findViewById(R.id.seek_bar_container);
- mSeekBar = view.findViewById(R.id.seek_bar);
- mToolbar = view.findViewById(R.id.toolbar);
- if (mToolbar != null) {
- mToolbar.setBackgroundShown(false);
- mToolbar.setNavButtonMode(Toolbar.NavButtonMode.DOWN);
+ mSeekBarContainer = view.findViewById(R.id.playback_seek_bar_container);
+ mSeekBar = view.findViewById(R.id.playback_seek_bar);
+ DirectManipulationHelper.setSupportsRotateDirectly(mSeekBar, true);
- // Notify listeners when toolbar's down button is pressed.
- mToolbar.registerOnBackListener(() -> {
- if (mListener != null) {
- mListener.onCollapse();
- }
- return true;
- });
+ GuidelinesUpdater updater = new GuidelinesUpdater(view);
+ ToolbarController toolbarController = CarUi.installBaseLayoutAround(view, updater, true);
+ mAppBarController = new AppBarController(view.getContext(), toolbarController);
- // Update toolbar's logo
- MediaSourceViewModel mediaSourceViewModel = getMediaSourceViewModel();
- mediaSourceViewModel.getPrimaryMediaSource().observe(this, mediaSource ->
- mToolbar.setLogo(mediaSource != null
- ? new BitmapDrawable(getResources(), mediaSource.getCroppedPackageIcon())
- : null));
- }
+ mAppBarController.setTitle(R.string.fragment_playback_title);
+ mAppBarController.setBackgroundShown(false);
+ mAppBarController.setNavButtonMode(Toolbar.NavButtonMode.DOWN);
+ mAppBarController.setState(Toolbar.State.SUBPAGE);
+
+ // Update toolbar's logo
+ MediaSourceViewModel mediaSourceViewModel = getMediaSourceViewModel();
+ mediaSourceViewModel.getPrimaryMediaSource().observe(this, mediaSource ->
+ mAppBarController.setLogo(mediaSource != null
+ ? new BitmapDrawable(getResources(), mediaSource.getCroppedPackageIcon())
+ : null));
+
mBackgroundScrim = view.findViewById(R.id.background_scrim);
ViewUtils.setVisible(mBackgroundScrim, false);
mControlBarScrim = view.findViewById(R.id.control_bar_scrim);
@@ -406,15 +522,13 @@
if (useMediaSourceColor) {
getPlaybackViewModel().getMediaSourceColors().observe(getViewLifecycleOwner(),
sourceColors -> {
- int color = sourceColors != null ? sourceColors.getAccentColor(
- defaultColor)
+ int color = sourceColors != null
+ ? sourceColors.getAccentColor(defaultColor)
: defaultColor;
- mSeekBar.setThumbTintList(ColorStateList.valueOf(color));
- mSeekBar.setProgressTintList(ColorStateList.valueOf(color));
+ setSeekBarColor(color);
});
} else {
- mSeekBar.setThumbTintList(ColorStateList.valueOf(defaultColor));
- mSeekBar.setProgressTintList(ColorStateList.valueOf(defaultColor));
+ setSeekBarColor(defaultColor);
}
} else {
mSeekBar.setVisibility(View.GONE);
@@ -453,7 +567,10 @@
item -> mAlbumArtBinder.setImage(PlaybackFragment.this.getContext(),
item != null ? item.getArtworkKey() : null));
- return view;
+ mUxrContentLimiter = new LifeCycleObserverUxrContentLimiter(
+ new UxrContentLimiterImpl(getContext(), R.xml.uxr_config));
+ mUxrContentLimiter.setAdapter(mQueueAdapter);
+ getLifecycle().addObserver(mUxrContentLimiter);
}
@Override
@@ -519,7 +636,7 @@
Long itemId = (state != null) ? state.getActiveQueueItemId() : null;
if (!Objects.equals(mActiveQueueItemId, itemId)) {
mActiveQueueItemId = itemId;
- mQueueAdapter.updateActiveItem();
+ mQueueAdapter.updateActiveItem(/* listIsNew */ false);
}
});
mQueue.setAdapter(mQueueAdapter);
@@ -529,12 +646,19 @@
mItemAnimator.setSupportsChangeAnimations(false);
mQueue.setItemAnimator(mItemAnimator);
+ // Make sure the AppBar menu reflects the initial state of playback fragment.
+ updateAppBarMenu(mHasQueue);
+ if (mQueueMenuItem != null) {
+ mQueueMenuItem.setActivated(mQueueIsVisible);
+ }
+
getPlaybackViewModel().getQueue().observe(this, this::setQueue);
getPlaybackViewModel().hasQueue().observe(getViewLifecycleOwner(), hasQueue -> {
boolean enableQueue = (hasQueue != null) && hasQueue;
- mQueueIsVisible = mViewModel.getQueueVisible();
- setHasQueue(enableQueue);
+ boolean isQueueVisible = enableQueue && mViewModel.getQueueVisible();
+
+ setQueueState(enableQueue, isQueueVisible);
});
getPlaybackViewModel().getProgress().observe(getViewLifecycleOwner(),
playbackProgress ->
@@ -571,7 +695,7 @@
*/
private void toggleQueueVisibility() {
boolean updatedQueueVisibility = !mQueueIsVisible;
- setQueueVisible(updatedQueueVisibility);
+ setQueueState(mHasQueue, updatedQueueVisibility);
// When the visibility of queue is changed by the user, save the visibility into ViewModel
// so that we can restore PlaybackFragment properly when needed. If it's changed by media
@@ -580,39 +704,39 @@
mViewModel.setQueueVisible(updatedQueueVisibility);
}
- private void setQueueVisible(boolean visible) {
- mQueueIsVisible = visible;
-
- if (mToolbar != null) {
- if (mHasQueue) {
- MenuItem queueMenuItem = MenuItem.builder(getContext())
- .setIcon(R.drawable.ic_queue_button)
- .setActivated(mQueueIsVisible)
- .setOnClickListener(button -> toggleQueueVisibility())
- .build();
- mToolbar.setMenuItems(Collections.singletonList(queueMenuItem));
- } else {
- mToolbar.setMenuItems(Collections.emptyList());
- }
+ private void updateAppBarMenu(boolean hasQueue) {
+ if (hasQueue && mQueueMenuItem == null) {
+ mQueueMenuItem = MenuItem.builder(getContext())
+ .setIcon(R.drawable.ic_queue_button)
+ .setActivatable()
+ .setOnClickListener(button -> toggleQueueVisibility())
+ .build();
}
-
- if (mQueueIsVisible) {
- ViewUtils.showViewsAnimated(mViewsToShowWhenQueueIsVisible, mFadeDuration);
- ViewUtils.hideViewsAnimated(mViewsToHideWhenQueueIsVisible, mFadeDuration);
- ViewUtils.setVisible(mViewsToShowImmediatelyWhenQueueIsVisible, true);
- ViewUtils.setVisible(mViewsToHideImmediatelyWhenQueueIsVisible, false);
- } else {
- ViewUtils.hideViewsAnimated(mViewsToShowWhenQueueIsVisible, mFadeDuration);
- ViewUtils.showViewsAnimated(mViewsToHideWhenQueueIsVisible, mFadeDuration);
- ViewUtils.setVisible(mViewsToShowImmediatelyWhenQueueIsVisible, false);
- ViewUtils.setVisible(mViewsToHideImmediatelyWhenQueueIsVisible, true);
- }
+ mAppBarController.setMenuItems(
+ hasQueue ? Collections.singletonList(mQueueMenuItem) : Collections.emptyList());
}
- /** Sets whether the source has a queue. */
- private void setHasQueue(boolean hasQueue) {
- mHasQueue = hasQueue;
- setQueueVisible(hasQueue && mQueueIsVisible);
+ private void setQueueState(boolean hasQueue, boolean visible) {
+ if (mHasQueue != hasQueue) {
+ mHasQueue = hasQueue;
+ updateAppBarMenu(hasQueue);
+ }
+ if (mQueueMenuItem != null) {
+ mQueueMenuItem.setActivated(visible);
+ }
+
+ if (mQueueIsVisible != visible) {
+ mQueueIsVisible = visible;
+ if (mQueueIsVisible) {
+ ViewUtils.showViewsAnimated(mViewsToShowWhenQueueIsVisible, mFadeDuration);
+ ViewUtils.hideViewsAnimated(mViewsToHideWhenQueueIsVisible, mFadeDuration);
+ } else {
+ ViewUtils.hideViewsAnimated(mViewsToShowWhenQueueIsVisible, mFadeDuration);
+ ViewUtils.showViewsAnimated(mViewsToHideWhenQueueIsVisible, mFadeDuration);
+ }
+ ViewUtils.setVisible(mViewsToShowImmediatelyWhenQueueIsVisible, mQueueIsVisible);
+ ViewUtils.setVisible(mViewsToHideImmediatelyWhenQueueIsVisible, !mQueueIsVisible);
+ }
}
private void onQueueItemClicked(MediaItemMetadata item) {
@@ -642,6 +766,24 @@
return MediaSourceViewModel.get(getActivity().getApplication(), MEDIA_SOURCE_MODE_BROWSE);
}
+ private void setSeekBarColor(int color) {
+ mSeekBar.setProgressTintList(ColorStateList.valueOf(color));
+
+ // If the thumb drawable consists of a center drawable, only change the color of the center
+ // drawable. Otherwise change the color of the entire thumb drawable.
+ Drawable thumb = mSeekBar.getThumb();
+ if (thumb instanceof LayerDrawable) {
+ LayerDrawable thumbDrawable = (LayerDrawable) thumb;
+ Drawable thumbCenter = thumbDrawable.findDrawableByLayerId(R.id.thumb_center);
+ if (thumbCenter != null) {
+ thumbCenter.setColorFilter(color, PorterDuff.Mode.SRC);
+ thumbDrawable.setDrawableByLayerId(R.id.thumb_center, thumbCenter);
+ return;
+ }
+ }
+ mSeekBar.setThumbTintList(ColorStateList.valueOf(color));
+ }
+
/**
* Sets a listener of this PlaybackFragment events. In order to avoid memory leaks, consumers
* must reset this reference by setting the listener to null.
diff --git a/src/com/android/car/media/UxrPivotFilter.java b/src/com/android/car/media/UxrPivotFilter.java
new file mode 100644
index 0000000..57b1e52
--- /dev/null
+++ b/src/com/android/car/media/UxrPivotFilter.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.media;
+
+
+/**
+ * Interface for helper objects that hide elements from lists that are too long. The limiting
+ * happens around a pivot element that can be anywhere in the list. Elements near that pivot will
+ * be visible, while elements at the head and / or tail of the list will be replaced by a message
+ * telling the user about the truncation.
+ * When no restrictions are in effect, the {@link #PASS_THROUGH} instance should be used.
+ */
+public interface UxrPivotFilter {
+
+ int INVALID_INDEX = -1;
+ int INVALID_POSITION = -1;
+
+ /**
+ * Computes new restrictions when the list (and optionally) the pivot have changed.
+ * The implementation doesn't send any notification.
+ */
+ void recompute(int newCount, int pivotIndex);
+
+ /**
+ * Computes new restrictions when only the pivot has changed.
+ * The implementation must send notification changes (ideally incremental ones).
+ */
+ void updatePivotIndex(int pivotIndex);
+
+ /** Returns the number of elements in the resulting list, including the message(s). */
+ int getFilteredCount();
+
+ /**
+ * Converts an index in the unfiltered data set to a RV position in the filtered UI in the
+ * 0 .. {@link #getFilteredCount} range which includes the limits message(s).
+ * Returns INVALID_POSITION if that element has been filtered out.
+ */
+ int indexToPosition(int index);
+
+ /**
+ * Converts a RV position in the filtered UI to an index in the unfiltered data set.
+ * Returns INVALID_INDEX if a message is shown at that position.
+ */
+ int positionToIndex(int position);
+
+ /** Send notification changes for the restriction message(s) if there are any. */
+ void invalidateMessagePositions();
+
+
+ /**
+ * A trivial implementation that doesn't do any filtering (simplifies the filter's code).
+ */
+ UxrPivotFilter PASS_THROUGH = new UxrPivotFilter() {
+ private int mCount;
+
+ @Override
+ public void recompute(int newCount, int pivotIndex) {
+ mCount = newCount;
+ }
+
+ @Override
+ public void updatePivotIndex(int pivotIndex) {
+ }
+
+ @Override
+ public int getFilteredCount() {
+ return mCount;
+ }
+
+ @Override
+ public int indexToPosition(int index) {
+ return index;
+ }
+
+ @Override
+ public int positionToIndex(int position) {
+ return position;
+ }
+
+ @Override
+ public void invalidateMessagePositions() {
+ }
+ };
+}
diff --git a/src/com/android/car/media/UxrPivotFilterImpl.java b/src/com/android/car/media/UxrPivotFilterImpl.java
new file mode 100644
index 0000000..29be569
--- /dev/null
+++ b/src/com/android/car/media/UxrPivotFilterImpl.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.car.media;
+
+import android.util.Log;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+
+public class UxrPivotFilterImpl implements UxrPivotFilter {
+
+ private static final String TAG = "UxrPivotFilterImpl";
+
+ private final RecyclerView.Adapter<?> mAdapter;
+ private final int mMaxItems;
+ private final int mMaxItemsDiv2;
+
+ private int mUnlimitedCount;
+ private int mPivotIndex;
+ private final ListRange mRange = new ListRange();
+ private final ListRange mSavedRange = new ListRange();
+
+
+ /**
+ * Constructor
+ * @param adapter the adapter to notify of changes in {@link #updatePivotIndex}.
+ * @param maxItems the maximum number of items to show. When > 0, its value is rounded up to
+ * the nearest greater odd integer in order to show the active element plus or
+ * minus maxItems / 2.
+ */
+ public UxrPivotFilterImpl(RecyclerView.Adapter<?> adapter, int maxItems) {
+ mAdapter = adapter;
+ if (maxItems <= 0) {
+ mMaxItemsDiv2 = 0;
+ mMaxItems = 0;
+ } else {
+ mMaxItemsDiv2 = maxItems / 2;
+ mMaxItems = 1 + (mMaxItemsDiv2 * 2);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "UxrPivotFilterImpl{" +
+ "mMaxItemsDiv2=" + mMaxItemsDiv2 +
+ ", mUnlimitedCount=" + mUnlimitedCount +
+ ", mPivotIndex=" + mPivotIndex +
+ ", mRange=" + mRange.toString() +
+ '}';
+ }
+
+ @Override
+ public int getFilteredCount() {
+ return mRange.mLimitedCount;
+ }
+
+ @Override
+ public void invalidateMessagePositions() {
+ if (mRange.mClampedHead > 0) {
+ mAdapter.notifyItemChanged(0);
+ }
+ if (mRange.mClampedTail > 0) {
+ mAdapter.notifyItemChanged(getFilteredCount() - 1);
+ }
+ }
+
+ @Override
+ public void recompute(int newCount, int pivotIndex) {
+ if (pivotIndex < 0 || newCount <= pivotIndex) {
+ Log.e(TAG, "Invalid pivotIndex: " + pivotIndex + " newCount: " + newCount);
+ pivotIndex = 0;
+ }
+ mUnlimitedCount = newCount;
+ mPivotIndex = pivotIndex;
+ mRange.mClampedHead = 0;
+ mRange.mClampedTail = 0;
+
+ if (newCount <= mMaxItems) {
+ // Under the cap case.
+ mRange.mStartIndex = 0;
+ mRange.mEndIndex = mUnlimitedCount;
+ mRange.mLimitedCount = mUnlimitedCount;
+ } else if (mMaxItems <= 0) {
+ // Zero cap case.
+ mRange.mStartIndex = 0;
+ mRange.mEndIndex = 0;
+ mRange.mLimitedCount = 1; // One limit message
+ mRange.mClampedTail = 1;
+ } else if (mPivotIndex <= mMaxItemsDiv2) {
+ // No need to clamp the head case
+ // For example: P = 2, M/2 = 2 => exactly two items before the pivot.
+ // Tail has to be clamped or we'd be in the "under the cap" case.
+ mRange.mStartIndex = 0;
+ mRange.mEndIndex = mMaxItems;
+ mRange.mLimitedCount = mMaxItems + 1; // One limit message at the end
+ mRange.mClampedTail = 1;
+ } else if ((mUnlimitedCount - 1 - mPivotIndex) <= mMaxItemsDiv2) {
+ // No need to clamp the tail case
+ // For example: C = 5, P = 2 => exactly 2 items after the pivot (count is exclusive).
+ // Head has to be clamped or we'd be in the "under the cap" case.
+ mRange.mEndIndex = mUnlimitedCount;
+ mRange.mStartIndex = mRange.mEndIndex - mMaxItems;
+ mRange.mLimitedCount = mMaxItems + 1; // One limit message at the start
+ mRange.mClampedHead = 1;
+ } else {
+ // Both head and tail need clamping
+ mRange.mStartIndex = mPivotIndex - mMaxItemsDiv2;
+ mRange.mEndIndex = mPivotIndex + mMaxItemsDiv2 + 1;
+ mRange.mLimitedCount = mMaxItems + 2; // One limit message at each end.
+ mRange.mClampedHead = 1;
+ mRange.mClampedTail = 1;
+ }
+ }
+
+ /**
+ * Computes the new restrictions when the pivot changes but the list remains the same.
+ * Notifications are done from the end to the beginning of the list so we don't have to mess
+ * with the indices as we go. Beyond the addition or removal of head and tail messages, the
+ * method boils down to intersecting two segments and determining which elements to remove and
+ * which to add to go from the old one to the new one.<p/>
+ * The diagram below illustrates all the cases with [S1, E1[ the old range and [S2, E2[ the
+ * new one. The =, + and - signs identify identical, inserted and removed elements.<p/>
+ * <pre>
+ * S1 E1
+ * |........................|
+ * | |
+ * S2 | E2 |
+ * +++++++++++++++|======------------------|
+ * | |
+ * | S2 | E2
+ * | ===========|+++++++++++
+ * | |
+ * | S2 E2 |
+ * |-----===========--------|
+ * | |
+ * S2 | | E2
+ * ++++++++++|========================|++++++++++++++++
+ * <pre/>
+ */
+ @Override
+ public void updatePivotIndex(int pivotIndex) {
+ if (mPivotIndex == pivotIndex) return;
+
+ mSavedRange.copyFrom(mRange);
+
+ recompute(mUnlimitedCount, pivotIndex);
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "updatePivotIndex pivot: " + pivotIndex + " saved: " + mSavedRange
+ + " new: " + mRange);
+ }
+
+ if (mSavedRange.intersects(mRange)) {
+ if (mSavedRange.mClampedTail < mRange.mClampedTail) {
+ // Add a tail message, inserting it after the last element of the restricted list.
+ mAdapter.notifyItemInserted(mSavedRange.mLimitedCount);
+ }
+ if (mSavedRange.mClampedTail > mRange.mClampedTail) {
+ // Remove a tail message which was shown as the last element of the restricted list.
+ mAdapter.notifyItemRemoved(mSavedRange.mLimitedCount - 1);
+ }
+
+ // Add or remove items at the end
+ if (mSavedRange.mEndIndex < mRange.mEndIndex) {
+ int insertPos = mSavedRange.indexToPosition(mSavedRange.mEndIndex);
+ int insertCount = mRange.mEndIndex - mSavedRange.mEndIndex;
+ mAdapter.notifyItemRangeInserted(insertPos, insertCount);
+ }
+ if (mSavedRange.mEndIndex > mRange.mEndIndex) {
+ int delPos = mSavedRange.indexToPosition(mRange.mEndIndex);
+ int delCount = mSavedRange.mEndIndex - mRange.mEndIndex;
+ mAdapter.notifyItemRangeRemoved(delPos, delCount);
+ }
+
+ // Add or remove items at the start
+ if (mSavedRange.mStartIndex > mRange.mStartIndex) {
+ int insertPos = mSavedRange.indexToPosition(mSavedRange.mStartIndex);
+ int insertCount = mSavedRange.mStartIndex - mRange.mStartIndex;
+ mAdapter.notifyItemRangeInserted(insertPos, insertCount);
+ }
+ if (mSavedRange.mStartIndex < mRange.mStartIndex) {
+ int delPos = mSavedRange.indexToPosition(mSavedRange.mStartIndex);
+ int delCount = mRange.mStartIndex - mSavedRange.mStartIndex;
+ mAdapter.notifyItemRangeRemoved(delPos, delCount);
+ }
+
+ // Add or remove the head message
+ if (mSavedRange.mClampedHead < mRange.mClampedHead) {
+ mAdapter.notifyItemInserted(0);
+ }
+ if (mSavedRange.mClampedHead > mRange.mClampedHead) {
+ mAdapter.notifyItemRemoved(0);
+ }
+ } else {
+ // No element is the same, invalidate all.
+ mAdapter.notifyDataSetChanged();
+ }
+ }
+
+ @Override
+ public int indexToPosition(int index) {
+ if ((mRange.mStartIndex <= index) && (index < mRange.mEndIndex)) {
+ return mRange.indexToPosition(index);
+ } else {
+ return INVALID_POSITION;
+ }
+ }
+
+ @Override
+ public int positionToIndex(int position) {
+ return mRange.positionToIndex(position);
+ }
+
+
+ /** A portion of the unfiltered list. */
+ private static class ListRange {
+
+ /** In original data, inclusive. */
+ private int mStartIndex;
+ /** In original data, exclusive. */
+ private int mEndIndex;
+
+ /** 1 when clamped, otherwise 0. */
+ private int mClampedHead;
+ /** 1 when clamped, otherwise 0. */
+ private int mClampedTail;
+
+ /** The count of the resulting elements, including the truncation message(s). */
+ private int mLimitedCount;
+
+ public void copyFrom(ListRange range) {
+ mStartIndex = range.mStartIndex;
+ mEndIndex = range.mEndIndex;
+ mClampedHead = range.mClampedHead;
+ mClampedTail = range.mClampedTail;
+ mLimitedCount = range.mLimitedCount;
+ }
+
+ @Override
+ public String toString() {
+ return "ListRange{" +
+ "mStartIndex=" + mStartIndex +
+ ", mEndIndex=" + mEndIndex +
+ ", mClampedHead=" + mClampedHead +
+ ", mClampedTail=" + mClampedTail +
+ ", mLimitedCount=" + mLimitedCount +
+ '}';
+ }
+
+ public boolean intersects(ListRange range) {
+ return ((range.mEndIndex > mStartIndex) && (mEndIndex > range.mStartIndex));
+ }
+
+ /** Unchecked index needed by {@link #updatePivotIndex}. */
+ public int indexToPosition(int index) {
+ return index - mStartIndex + mClampedHead;
+ }
+
+ public int positionToIndex(int position) {
+ int index = position - mClampedHead + mStartIndex;
+ if ((index < mStartIndex) || (mEndIndex <= index)) {
+ return INVALID_INDEX;
+ } else {
+ return index;
+ }
+ }
+ }
+}
diff --git a/src/com/android/car/media/ViewControllerBase.java b/src/com/android/car/media/ViewControllerBase.java
index a4c413d..b27e4bf 100644
--- a/src/com/android/car/media/ViewControllerBase.java
+++ b/src/com/android/car/media/ViewControllerBase.java
@@ -34,19 +34,25 @@
import androidx.annotation.CallSuper;
import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import com.android.car.apps.common.util.CarPackageManagerUtils;
import com.android.car.media.common.source.MediaSource;
import com.android.car.media.common.source.MediaSourceViewModel;
-import com.android.car.media.widgets.AppBarView;
+import com.android.car.media.widgets.AppBarController;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.toolbar.ToolbarController;
/**
* Functionality common to content view controllers. It mainly handles the AppBar view,
- * which is common to all them.
+ * which is common to all of them.
*/
-abstract class ViewControllerBase {
+abstract class ViewControllerBase implements InsetsChangedListener {
private static final String TAG = "ViewControllerBase";
private final boolean mShouldShowSoundSettings;
@@ -55,7 +61,7 @@
final FragmentActivity mActivity;
final int mFadeDuration;
final View mContent;
- final AppBarView mAppBarView;
+ final AppBarController mAppBarController;
final MediaSourceViewModel mMediaSourceVM;
private Intent mCurrentSourcePreferences;
@@ -69,17 +75,26 @@
LayoutInflater inflater = LayoutInflater.from(container.getContext());
mContent = inflater.inflate(resource, container, false);
-
- mAppBarView = mContent.findViewById(R.id.app_bar);
- mAppBarView.setSearchSupported(false);
- mAppBarView.setHasEqualizer(false);
-
container.addView(mContent);
+ GuidelinesUpdater updater = new GuidelinesUpdater(mContent);
+ updater.addListener(this);
+ ToolbarController toolbar = CarUi.installBaseLayoutAround(mContent, updater, true);
+
+ mAppBarController = new AppBarController(activity, toolbar);
+ mAppBarController.setSearchSupported(false);
+ mAppBarController.setHasEqualizer(false);
+
mCarPackageManager = carPackageManager;
mMediaSourceVM = MediaSourceViewModel.get(activity.getApplication(),
MEDIA_SOURCE_MODE_BROWSE);
+
+ }
+
+ @Override
+ public void onCarUiInsetsChanged(@NonNull Insets insets) {
+ // Overridden in subclasses
}
CharSequence getAppBarDefaultTitle(@Nullable MediaSource mediaSource) {
@@ -87,7 +102,7 @@
: mActivity.getResources().getString(R.string.media_app_title);
}
- class BasicAppBarListener extends AppBarView.AppBarListener {
+ class BasicAppBarListener extends AppBarController.AppBarListener {
@Override
protected void onSettingsSelection() {
if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -127,8 +142,8 @@
packageName = mediaSource.getPackageName();
}
- mAppBarView.setLogo(icon);
- mAppBarView.setSearchIcon(searchIcon);
+ mAppBarController.setLogo(icon);
+ mAppBarController.setSearchIcon(searchIcon);
updateSourcePreferences(packageName);
}
@@ -142,13 +157,13 @@
if (info != null && info.activityInfo != null && info.activityInfo.exported) {
mCurrentSourcePreferences = new Intent(prefsIntent.getAction())
.setClassName(info.activityInfo.packageName, info.activityInfo.name);
- mAppBarView.setSettingsDistractionOptimized(
+ mAppBarController.setSettingsDistractionOptimized(
CarPackageManagerUtils.isDistractionOptimized(
mCarPackageManager, info.activityInfo));
}
}
- mAppBarView.setHasSettings(mCurrentSourcePreferences != null);
- mAppBarView.setHasEqualizer(mShouldShowSoundSettings);
+ mAppBarController.setHasSettings(mCurrentSourcePreferences != null);
+ mAppBarController.setHasEqualizer(mShouldShowSoundSettings);
}
diff --git a/src/com/android/car/media/browse/BrowseAdapter.java b/src/com/android/car/media/browse/BrowseAdapter.java
index 9ba3cd1..847d270 100644
--- a/src/com/android/car/media/browse/BrowseAdapter.java
+++ b/src/com/android/car/media/browse/BrowseAdapter.java
@@ -33,7 +33,6 @@
import com.android.car.media.common.MediaItemMetadata;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -51,6 +50,17 @@
*/
public class BrowseAdapter extends ListAdapter<BrowseViewData, BrowseViewHolder> {
private static final String TAG = "BrowseAdapter";
+
+ /**
+ * Listens to the list data changes.
+ */
+ public interface OnListChangedListener {
+ /**
+ * Called when {@link #onCurrentListChanged(List, List)} is called.
+ */
+ void onListChanged(List<BrowseViewData> previousList, List<BrowseViewData> currentList);
+ }
+
@NonNull
private final Context mContext;
@NonNull
@@ -59,11 +69,12 @@
private CharSequence mTitle;
@Nullable
private MediaItemMetadata mParentMediaItem;
- private int mMaxSpanSize = 1;
private BrowseItemViewType mRootBrowsableViewType = BrowseItemViewType.LIST_ITEM;
private BrowseItemViewType mRootPlayableViewType = BrowseItemViewType.LIST_ITEM;
+ private OnListChangedListener mOnListChangedListener;
+
private static final DiffUtil.ItemCallback<BrowseViewData> DIFF_CALLBACK =
new DiffUtil.ItemCallback<BrowseViewData>() {
@Override
@@ -88,13 +99,13 @@
/**
* Callback invoked when a user clicks on a playable item.
*/
- protected void onPlayableItemClicked(MediaItemMetadata item) {
+ protected void onPlayableItemClicked(@NonNull MediaItemMetadata item) {
}
/**
* Callback invoked when a user clicks on a browsable item.
*/
- protected void onBrowsableItemClicked(MediaItemMetadata item) {
+ protected void onBrowsableItemClicked(@NonNull MediaItemMetadata item) {
}
/**
@@ -133,16 +144,6 @@
mObservers.remove(observer);
}
- /**
- * Sets the number of columns that items can take. This method only needs to be used if the
- * attached {@link RecyclerView} is NOT using a {@link GridLayoutManager}. This class will
- * automatically determine this value on {@link #onAttachedToRecyclerView(RecyclerView)}
- * otherwise.
- */
- public void setMaxSpanSize(int maxSpanSize) {
- mMaxSpanSize = maxSpanSize;
- }
-
public void setRootBrowsableViewType(int hintValue) {
mRootBrowsableViewType = fromMediaHint(hintValue);
}
@@ -151,20 +152,16 @@
mRootPlayableViewType = fromMediaHint(hintValue);
}
+ public int getSpanSize(int position, int maxSpanSize) {
+ BrowseItemViewType viewType = getItem(position).mViewType;
+ return viewType.getSpanSize(maxSpanSize);
+ }
+
/**
- * @return a {@link GridLayoutManager.SpanSizeLookup} that can be used to obtain the span size
- * of each item in this adapter. This method is only needed if the {@link RecyclerView} is NOT
- * using a {@link GridLayoutManager}. This class will automatically use it on\ {@link
- * #onAttachedToRecyclerView(RecyclerView)} otherwise.
+ * Sets a listener to listen for the list data changes.
*/
- private GridLayoutManager.SpanSizeLookup getSpanSizeLookup() {
- return new GridLayoutManager.SpanSizeLookup() {
- @Override
- public int getSpanSize(int position) {
- BrowseItemViewType viewType = getItem(position).mViewType;
- return viewType.getSpanSize(mMaxSpanSize);
- }
- };
+ public void setOnListChangedListener(OnListChangedListener onListChangedListener) {
+ mOnListChangedListener = onListChangedListener;
}
@NonNull
@@ -198,6 +195,15 @@
return getItem(position).mViewType.ordinal();
}
+ @Override
+ public void onCurrentListChanged(@NonNull List<BrowseViewData> previousList,
+ @NonNull List<BrowseViewData> currentList) {
+ super.onCurrentListChanged(previousList, currentList);
+ if (mOnListChangedListener != null) {
+ mOnListChangedListener.onListChanged(previousList, currentList);
+ }
+ }
+
public void submitItems(@Nullable MediaItemMetadata parentItem,
@Nullable List<MediaItemMetadata> children) {
mParentMediaItem = parentItem;
@@ -214,15 +220,6 @@
}
}
- @Override
- public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
- if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
- GridLayoutManager manager = (GridLayoutManager) recyclerView.getLayoutManager();
- mMaxSpanSize = manager.getSpanCount();
- manager.setSpanSizeLookup(getSpanSizeLookup());
- }
- }
-
private class ItemsBuilder {
private List<BrowseViewData> result = new ArrayList<>();
diff --git a/src/com/android/car/media/browse/BrowseViewHolder.java b/src/com/android/car/media/browse/BrowseViewHolder.java
index aa4449f..b885a9c 100644
--- a/src/com/android/car/media/browse/BrowseViewHolder.java
+++ b/src/com/android/car/media/browse/BrowseViewHolder.java
@@ -34,7 +34,7 @@
/**
* Generic {@link RecyclerView.ViewHolder} to use for all views in the {@link BrowseAdapter}
*/
-class BrowseViewHolder extends RecyclerView.ViewHolder {
+public class BrowseViewHolder extends RecyclerView.ViewHolder {
private final TextView mTitle;
private final TextView mSubtitle;
private final ImageView mAlbumArt;
@@ -55,7 +55,7 @@
mTitle = itemView.findViewById(com.android.car.media.R.id.title);
mSubtitle = itemView.findViewById(com.android.car.media.R.id.subtitle);
mAlbumArt = itemView.findViewById(com.android.car.media.R.id.thumbnail);
- mContainer = itemView.findViewById(com.android.car.media.R.id.container);
+ mContainer = itemView.findViewById(com.android.car.media.R.id.item_container);
mRightArrow = itemView.findViewById(com.android.car.media.R.id.right_arrow);
mTitleDownloadIcon = itemView.findViewById(
com.android.car.media.R.id.download_icon_with_title);
diff --git a/src/com/android/car/media/browse/LimitedBrowseAdapter.java b/src/com/android/car/media/browse/LimitedBrowseAdapter.java
new file mode 100644
index 0000000..6d3c6a7
--- /dev/null
+++ b/src/com/android/car/media/browse/LimitedBrowseAdapter.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.media.browse;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.media.R;
+import com.android.car.media.common.MediaItemMetadata;
+import com.android.car.ui.recyclerview.DelegatingContentLimitingAdapter;
+
+import java.util.List;
+
+/**
+ * Provides list limiting functionality to {@link BrowseAdapter}.
+ */
+public class LimitedBrowseAdapter extends DelegatingContentLimitingAdapter<BrowseViewHolder> {
+
+ private final BrowseAdapter mBrowseAdapter;
+ private final GridLayoutManager mLayoutManager;
+ private final int mMaxSpanSize;
+
+ @Nullable private String mAnchorId;
+
+ public LimitedBrowseAdapter(BrowseAdapter browseAdapter, GridLayoutManager manager,
+ BrowseAdapter.Observer browseAdapterObserver) {
+ super(browseAdapter, R.id.browse_list_uxr_config);
+
+ mBrowseAdapter = browseAdapter;
+ mLayoutManager = manager;
+ mMaxSpanSize = manager.getSpanCount();
+
+ mLayoutManager.setSpanSizeLookup(mSpanSizeLookup);
+ mBrowseAdapter.registerObserver(browseAdapterObserver);
+ mBrowseAdapter.setOnListChangedListener(((previousList, currentList) -> {
+ updateUnderlyingDataChanged(currentList.size(), validateAnchor());
+ }));
+ }
+
+ private final GridLayoutManager.SpanSizeLookup mSpanSizeLookup =
+ new GridLayoutManager.SpanSizeLookup() {
+ @Override
+ public int getSpanSize(int position) {
+ if (getItemViewType(position) == getScrollingLimitedMessageViewType()) {
+ return mMaxSpanSize;
+ }
+
+ int itemIndex = positionToIndex(position);
+ return mBrowseAdapter.getSpanSize(itemIndex, mMaxSpanSize);
+ }
+ };
+
+ /**
+ * @see BrowseAdapter#submitItems(MediaItemMetadata, List)
+ */
+ public void submitItems(@Nullable MediaItemMetadata parentItem,
+ @Nullable List<MediaItemMetadata> items) {
+ mBrowseAdapter.submitItems(parentItem, items);
+
+ if (items == null) {
+ updateUnderlyingDataChanged(0, 0);
+ return;
+ }
+ // We can't take any action with the new items as they must first go through the
+ // AsyncListDiffer of ListAdapter. This is handled in the OnListChangedListener.
+ }
+
+ private int validateAnchor() {
+ if (mAnchorId == null) {
+ return 0;
+ }
+
+ List<BrowseViewData> items = mBrowseAdapter.getCurrentList();
+ for (int i = 0; i < items.size(); i++) {
+ MediaItemMetadata mediaItem = items.get(i).mMediaItem;
+ if (mediaItem != null && mAnchorId.equals(mediaItem.getId())) {
+ return i;
+ }
+ }
+
+ // The anchor isn't present in the new list, reset it.
+ mAnchorId = null;
+ return 0;
+ }
+
+
+ @Override
+ public int computeAnchorIndexWhenRestricting() {
+ List<BrowseViewData> items = mBrowseAdapter.getCurrentList();
+ if (items.size() <= 0) {
+ mAnchorId = null;
+ return 0;
+ }
+
+ int anchorIndex = (getFirstVisibleItemPosition() + getLastVisibleItemPosition()) / 2;
+ if (0 <= anchorIndex && anchorIndex < items.size()) {
+ MediaItemMetadata mediaItem = items.get(anchorIndex).mMediaItem;
+ mAnchorId = mediaItem != null ? mediaItem.getId() : null;
+ return anchorIndex;
+ } else {
+ mAnchorId = null;
+ return 0;
+ }
+ }
+
+ private int getFirstVisibleItemPosition() {
+ int firstItem = mLayoutManager.findFirstCompletelyVisibleItemPosition();
+ if (firstItem == RecyclerView.NO_POSITION) {
+ firstItem = mLayoutManager.findFirstVisibleItemPosition();
+ }
+ return firstItem;
+ }
+
+ private int getLastVisibleItemPosition() {
+ int lastItem = mLayoutManager.findLastCompletelyVisibleItemPosition();
+ if (lastItem == RecyclerView.NO_POSITION) {
+ lastItem = mLayoutManager.findLastVisibleItemPosition();
+ }
+ return lastItem;
+ }
+}
diff --git a/src/com/android/car/media/widgets/AppBarView.java b/src/com/android/car/media/widgets/AppBarController.java
similarity index 62%
rename from src/com/android/car/media/widgets/AppBarView.java
rename to src/com/android/car/media/widgets/AppBarController.java
index b17a773..962f2ac 100644
--- a/src/com/android/car/media/widgets/AppBarView.java
+++ b/src/com/android/car/media/widgets/AppBarController.java
@@ -3,7 +3,8 @@
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.Intent;
-import android.util.AttributeSet;
+import android.graphics.drawable.Drawable;
+import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -13,6 +14,7 @@
import com.android.car.media.common.source.MediaSource;
import com.android.car.ui.toolbar.MenuItem;
import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
import java.util.Arrays;
import java.util.List;
@@ -24,13 +26,16 @@
* views via {@link #setState}. A detailed explanation of all possible states of this application
* bar can be seen at {@link Toolbar.State}.
*/
-public class AppBarView extends Toolbar {
+public class AppBarController {
private static final int MEDIA_UX_RESTRICTION_DEFAULT =
CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP;
private static final int MEDIA_UX_RESTRICTION_NONE = CarUxRestrictions.UX_RESTRICTIONS_BASELINE;
private int mMaxTabs;
+ private final ToolbarController mToolbarController;
+
+ private final boolean mUseSourceLogoForAppSelector;
@NonNull
private AppBarListener mListener = new AppBarListener();
@@ -41,6 +46,7 @@
private boolean mSearchSupported;
private boolean mShowSearchIfSupported;
+ private String mSearchQuery;
private Intent mAppSelectorIntent;
@@ -54,11 +60,6 @@
protected void onTabSelected(MediaItemMetadata item) {}
/**
- * Invoked when the user clicks on the back button
- */
- protected void onBack() {}
-
- /**
* Invoked when the user clicks on the settings button.
*/
protected void onSettingsSelection() {}
@@ -77,56 +78,48 @@
* Invoked when the user clicks on the search button
*/
protected void onSearchSelection() {}
-
- /**
- * Invoked when the height of the toolbar changes
- */
- protected void onHeightChanged(int height) {}
}
- public AppBarView(Context context) {
- this(context, null);
- }
-
- public AppBarView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AppBarView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context);
- }
-
- private void init(Context context) {
+ public AppBarController(Context context, ToolbarController controller) {
+ mToolbarController = controller;
mMaxTabs = context.getResources().getInteger(R.integer.max_tabs);
+ mUseSourceLogoForAppSelector =
+ context.getResources().getBoolean(R.bool.use_media_source_logo_for_app_selector);
+
mAppSelectorIntent = MediaSource.getSourceSelectorIntent(context, false);
- registerOnTabSelectedListener(tab ->
+ mToolbarController.registerOnTabSelectedListener(tab ->
mListener.onTabSelected(((MediaItemTab) tab).getItem()));
- registerOnBackListener(() -> {
- mListener.onBack();
- return true;
+ mToolbarController.registerOnSearchListener(query -> {
+ mSearchQuery = query;
+ mListener.onSearch(query);
});
- registerOnSearchListener(query -> mListener.onSearch(query));
- registerToolbarHeightChangeListener(height -> mListener.onHeightChanged(height));
- mSearch = MenuItem.Builder.createSearch(context, v -> mListener.onSearchSelection());
- mSettings = new MenuItem.Builder(context)
+ mToolbarController.registerOnSearchCompletedListener(
+ () -> mListener.onSearch(mSearchQuery));
+ mSearch = MenuItem.builder(context)
+ .setToSearch()
+ .setOnClickListener(v -> mListener.onSearchSelection())
+ .build();
+ mSettings = MenuItem.builder(context)
.setToSettings()
.setUxRestrictions(MEDIA_UX_RESTRICTION_DEFAULT)
.setOnClickListener(v -> mListener.onSettingsSelection())
.build();
- mEqualizer = new MenuItem.Builder(context)
+ mEqualizer = MenuItem.builder(context)
.setTitle(R.string.menu_item_sound_settings_title)
.setIcon(R.drawable.ic_equalizer)
.setOnClickListener(v -> mListener.onEqualizerSelection())
.build();
- mAppSelector = new MenuItem.Builder(context)
+ mAppSelector = MenuItem.builder(context)
.setTitle(R.string.menu_item_app_selector_title)
- .setIcon(R.drawable.ic_app_switch)
- .setOnClickListener(m -> getContext().startActivity(mAppSelectorIntent))
+ .setTinted(!mUseSourceLogoForAppSelector)
+ .setIcon(mUseSourceLogoForAppSelector
+ ? null : context.getDrawable(R.drawable.ic_app_switch))
+ .setOnClickListener(m -> context.startActivity(mAppSelectorIntent))
.build();
- setMenuItems(Arrays.asList(mSearch, mEqualizer, mSettings, mAppSelector));
+ mToolbarController.setMenuItems(
+ Arrays.asList(mSearch, mEqualizer, mSettings, mAppSelector));
setAppLauncherSupported(mAppSelectorIntent != null);
}
@@ -145,12 +138,12 @@
* @param items list of tabs to show, or null if no tabs should be shown.
*/
public void setItems(@Nullable List<MediaItemMetadata> items) {
- clearAllTabs();
+ mToolbarController.clearAllTabs();
if (items != null && !items.isEmpty()) {
int count = 0;
for (MediaItemMetadata item : items) {
- addTab(new MediaItemTab(item));
+ mToolbarController.addTab(new MediaItemTab(item));
count++;
if (count >= mMaxTabs) {
@@ -206,15 +199,65 @@
* Updates the currently active item
*/
public void setActiveItem(MediaItemMetadata item) {
- for (int i = 0; i < getTabLayout().getTabCount(); i++) {
- MediaItemTab mediaItemTab = (MediaItemTab) getTabLayout().get(i);
+ for (int i = 0; i < mToolbarController.getTabCount(); i++) {
+ MediaItemTab mediaItemTab = (MediaItemTab) mToolbarController.getTab(i);
boolean match = item != null && Objects.equals(
item.getId(),
mediaItemTab.getItem().getId());
if (match) {
- getTabLayout().selectTab(i);
+ mToolbarController.selectTab(i);
return;
}
}
}
+
+ public void setSearchQuery(String query) {
+ mToolbarController.setSearchQuery(query);
+ }
+
+ public void setLogo(Drawable drawable) {
+ if (mUseSourceLogoForAppSelector) {
+ mAppSelector.setIcon(drawable);
+ } else {
+ mToolbarController.setLogo(drawable);
+ }
+ }
+
+ public void setSearchIcon(Drawable drawable) {
+ mToolbarController.setSearchIcon(drawable);
+ }
+
+ public void setTitle(CharSequence title) {
+ mToolbarController.setTitle(title);
+ }
+
+ public void setTitle(int title) {
+ mToolbarController.setTitle(title);
+ }
+
+ public void setState(Toolbar.State state) {
+ mToolbarController.setState(state);
+ }
+
+ public void setMenuItems(List<MenuItem> items) {
+ mToolbarController.setMenuItems(items);
+ }
+
+ public void setBackgroundShown(boolean shown) {
+ mToolbarController.setBackgroundShown(shown);
+ }
+
+ public void setNavButtonMode(Toolbar.NavButtonMode mode) {
+ mToolbarController.setNavButtonMode(mode);
+ }
+
+ /** See {@link ToolbarController#canShowSearchResultItems}. */
+ public boolean canShowSearchResultsView() {
+ return mToolbarController.canShowSearchResultsView();
+ }
+
+ /** See {@link ToolbarController#setSearchResultsView}. */
+ public void setSearchResultsView(View view) {
+ mToolbarController.setSearchResultsView(view);
+ }
}
diff --git a/tools/generate-overlayable.sh b/tools/generate-overlayable.sh
new file mode 100755
index 0000000..833d9f5
--- /dev/null
+++ b/tools/generate-overlayable.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Run this script to regenerate the overlayable.xml file.
+
+if [[ -z "$ANDROID_BUILD_TOP" ]]; then
+ echo 'ANDROID_BUILD_TOP environment variable is empty; did you forget to run `lunch`?'
+ exit 1
+fi
+
+PROJECT_TOP=$ANDROID_BUILD_TOP/packages/apps/Car/Media
+
+python $ANDROID_BUILD_TOP/packages/apps/Car/tests/tools/rro/generate-overlayable.py \
+ -n CarMediaApp \
+ -r $PROJECT_TOP/res \
+ -e $PROJECT_TOP/res/values/overlayable.xml $PROJECT_TOP/res/xml/automotive_app_desc.xml \
+ -o $PROJECT_TOP/res/values/overlayable.xml
\ No newline at end of file