diff options
author | Roberto Perez <robertoalexis@google.com> | 2018-03-30 15:30:30 -0700 |
---|---|---|
committer | Roberto Perez <robertoalexis@google.com> | 2018-04-03 18:10:16 -0700 |
commit | d646ef36ef6c0c3bf3f0766e3463c2676d8ca823 (patch) | |
tree | 415ef8670e925f7dd30779cc79876c366232d3b2 | |
parent | 8189d452317e04e1c1852d2d3a2e9da3e0295147 (diff) | |
download | Media-d646ef36ef6c0c3bf3f0766e3463c2676d8ca823.tar.gz |
Using new album art methods from car-media-common. Implementing
background blurring. Adding time progress and duration.
Bug: 76099191
Test: To be added on b/77243935
Change-Id: I59735751b3a1e3aa2822b44e942575f721bce899
-rw-r--r-- | res/layout/fragment_playback.xml | 42 | ||||
-rw-r--r-- | res/layout/view_metadata.xml | 33 | ||||
-rw-r--r-- | res/values/dimens.xml | 13 | ||||
-rw-r--r-- | src/com/android/car/media/MediaActivity.java | 10 | ||||
-rw-r--r-- | src/com/android/car/media/MediaPlaybackModel.java | 53 | ||||
-rw-r--r-- | src/com/android/car/media/PlaybackFragment.java | 77 |
6 files changed, 142 insertions, 86 deletions
diff --git a/res/layout/fragment_playback.xml b/res/layout/fragment_playback.xml index 09ce12d..e37a712 100644 --- a/res/layout/fragment_playback.xml +++ b/res/layout/fragment_playback.xml @@ -8,10 +8,14 @@ <com.android.car.media.CrossfadeImageView android:id="@+id/album_background" + android:layout_width="0dp" + android:layout_height="0dp" android:background="@color/car_dark_blue_grey_800" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scaleType="centerCrop" /> + android:scaleType="centerCrop" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="@+id/playback_scrim_bottom"/> <View android:id="@+id/playback_scrim" @@ -23,17 +27,15 @@ <View android:id="@+id/playback_scrim_bottom" android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" + android:layout_height="@dimen/playback_scrim_transition_height" android:background="@drawable/car_playback_bottom_scrim" - app:layout_constraintTop_toTopOf="@+id/playback_controls" - app:layout_constraintBottom_toBottomOf="@+id/playback_controls"/> + app:layout_constraintTop_toBottomOf="@+id/metadata_container"/> <View android:layout_width="match_parent" android:layout_height="0dp" android:background="@android:color/black" - app:layout_constraintTop_toBottomOf="@+id/playback_controls" + app:layout_constraintTop_toBottomOf="@+id/playback_scrim_bottom" app:layout_constraintBottom_toBottomOf="parent"/> <FrameLayout @@ -50,17 +52,6 @@ </FrameLayout> - <com.android.car.media.common.PlaybackControls - android:id="@+id/playback_controls" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="@dimen/playback_controls_margin" - android:paddingBottom="@dimen/playback_controls_margin" - android:layout_marginLeft="@dimen/car_margin" - android:layout_marginRight="@dimen/car_margin" - app:columns="5" - app:layout_constraintTop_toBottomOf="@+id/metadata_container"/> - <androidx.car.widget.PagedListView android:id="@+id/browse_list" android:layout_width="match_parent" @@ -71,7 +62,18 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior" app:dividerStartMargin="@dimen/car_keyline_1" app:dividerEndMargin="@dimen/car_keyline_1" - app:layout_constraintTop_toBottomOf="@+id/playback_controls" + app:layout_constraintTop_toBottomOf="@+id/metadata_container" + app:layout_constraintBottom_toTopOf="@+id/playback_controls"/> + + <com.android.car.media.common.PlaybackControls + android:id="@+id/playback_controls" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/car_margin" + android:layout_marginRight="@dimen/car_margin" + android:layout_marginTop="@dimen/car_padding_1" + android:layout_marginBottom="@dimen/car_padding_1" + app:columns="5" app:layout_constraintBottom_toBottomOf="parent"/> </android.support.constraint.ConstraintLayout> diff --git a/res/layout/view_metadata.xml b/res/layout/view_metadata.xml index 17bb7aa..c503903 100644 --- a/res/layout/view_metadata.xml +++ b/res/layout/view_metadata.xml @@ -15,13 +15,12 @@ android:contentDescription="@string/album_art" android:layout_marginStart="@dimen/car_keyline_1" android:layout_marginEnd="@dimen/car_keyline_1" - android:layout_width="200dp" - android:layout_height="190dp" + android:layout_width="@dimen/playback_album_art_height" + android:layout_height="@dimen/playback_album_art_width" android:scaleType="centerCrop" android:transitionName="@string/album_art"/> - <LinearLayout - android:orientation="vertical" + <RelativeLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/car_keyline_1" @@ -32,33 +31,43 @@ android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/car_padding_1" android:textAppearance="@style/TextAppearance.Car.Body1.Light" - android:gravity="start" android:maxLines="@integer/playback_title_text_max_lines" android:ellipsize="end" - android:textAlignment="center" android:includeFontPadding="false"/> <TextView android:id="@+id/subtitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/playback_secondary_text_margin_top" + android:layout_below="@+id/title" + android:layout_marginBottom="@dimen/car_padding_2" android:textAppearance="@style/TextAppearance.Car.Body2.Light" - android:gravity="start" android:maxLines="@integer/playback_subtitle_text_max_lines" android:ellipsize="end" - android:textAlignment="center"/> + android:includeFontPadding="false"/> + <TextView + android:id="@+id/time" + android:text="3:27 / 4:03" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_below="@+id/title" + android:textAppearance="@style/TextAppearance.Car.Body2.Light" + android:maxLines="@integer/playback_subtitle_text_max_lines" + android:ellipsize="end" + android:includeFontPadding="false"/> <SeekBar android:id="@+id/seek_bar" android:layout_width="match_parent" android:layout_height="@dimen/playback_seekbar_height" - android:layout_marginTop="@dimen/playback_seekbar_margin_top" - android:visibility="invisible" + android:layout_below="@+id/subtitle" android:paddingStart="0dp" android:paddingEnd="0dp" + android:visibility="invisible" android:progressDrawable="@drawable/seekbar_background" android:background="@color/car_grey_900" android:thumb="@null"/> - </LinearLayout> + </RelativeLayout> </LinearLayout> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index c437ace..79da22b 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -33,5 +33,16 @@ <dimen name="controls_spacing_inner">16dp</dimen> <dimen name="controls_spacing_outer">81dp</dimen> - <dimen name="playback_controls_margin">48dp</dimen> + <!-- Height of the gradient scrim over the background image --> + <dimen name="playback_scrim_transition_height">256dp</dimen> + <!-- Image size used to generate the background --> + <dimen name="playback_background_raw_image_size">300px</dimen> + <!-- Blurring radius used to blur background images --> + <item name="playback_background_blur_radius" format="float" type="dimen">25</item> + <!-- Scale to apply to images before blurring them to create the playback background --> + <item name="playback_background_blur_scale" format="float" type="dimen">1</item> + <!-- Size of the album art thumbnail --> + <dimen name="playback_album_art_height">190dp</dimen> + <dimen name="playback_album_art_width">200dp</dimen> + </resources> diff --git a/src/com/android/car/media/MediaActivity.java b/src/com/android/car/media/MediaActivity.java index 7b774e2..0f0ddbe 100644 --- a/src/com/android/car/media/MediaActivity.java +++ b/src/com/android/car/media/MediaActivity.java @@ -110,13 +110,9 @@ public class MediaActivity extends CarDrawerActivity { ); MediaManager.getInstance(this).setMediaClientComponent(component); } else { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Launching most recent / default component."); - } - - // Set it to the default GPM component. - MediaManager.getInstance(this).connectToMostRecentMediaComponent( - new CarClientServiceAdapter(getPackageManager())); + // TODO (b/77334804): Implement the correct initialization logic when no component is + // given. For example, it should either connect the user to the currently playing + // session, bring the user to the app selector, or open the last known media source. } if (isSearchIntent(intent)) { diff --git a/src/com/android/car/media/MediaPlaybackModel.java b/src/com/android/car/media/MediaPlaybackModel.java index cc39db7..96cfe59 100644 --- a/src/com/android/car/media/MediaPlaybackModel.java +++ b/src/com/android/car/media/MediaPlaybackModel.java @@ -325,45 +325,38 @@ public class MediaPlaybackModel { new MediaBrowser.ConnectionCallback() { @Override public void onConnected() { - mHandler.post(()->{ - // Existing mController has already been disconnected before we call - // MediaBrowser.connect() - // getSessionToken returns a non null token - MediaSession.Token token = mBrowser.getSessionToken(); - if (mController != null) { - mController.unregisterCallback(mMediaControllerCallback); - } - mController = new MediaController(mContext, token); - mController.registerCallback(mMediaControllerCallback); - notifyListeners(Listener::onMediaConnected); - }); + // Existing mController has already been disconnected before we call + // MediaBrowser.connect() + // getSessionToken returns a non null token + MediaSession.Token token = mBrowser.getSessionToken(); + if (mController != null) { + mController.unregisterCallback(mMediaControllerCallback); + } + mController = new MediaController(mContext, token); + mController.registerCallback(mMediaControllerCallback); + notifyListeners(Listener::onMediaConnected); } @Override public void onConnectionSuspended() { - mHandler.post(() -> { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Media browser service connection suspended." - + " Waiting to be reconnected...."); - } - notifyListeners(Listener::onMediaConnectionSuspended); - }); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "Media browser service connection suspended." + + " Waiting to be reconnected...."); + } + notifyListeners(Listener::onMediaConnectionSuspended); } @Override public void onConnectionFailed() { - mHandler.post(() -> { - Log.e(TAG, "Media browser service connection FAILED!"); - // disconnect anyway to make sure we get into a sanity state - mBrowser.disconnect(); - mBrowser = null; - mCurrentComponentName = null; + // disconnect anyway to make sure we get into a sanity state + mBrowser.disconnect(); + mBrowser = null; + mCurrentComponentName = null; - CharSequence failedClientName = MediaManager.getInstance(mContext) - .getMediaClientName(); - notifyListeners( - (listener) -> listener.onMediaConnectionFailed(failedClientName)); - }); + CharSequence failedClientName = MediaManager.getInstance(mContext) + .getMediaClientName(); + notifyListeners( + (listener) -> listener.onMediaConnectionFailed(failedClientName)); } }; diff --git a/src/com/android/car/media/PlaybackFragment.java b/src/com/android/car/media/PlaybackFragment.java index c912b45..a8a6b77 100644 --- a/src/com/android/car/media/PlaybackFragment.java +++ b/src/com/android/car/media/PlaybackFragment.java @@ -1,11 +1,14 @@ package com.android.car.media; +import static java.security.AccessController.getContext; + +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.util.Log; +import android.support.v7.widget.RecyclerView; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -13,13 +16,16 @@ import android.widget.ImageView; import android.widget.SeekBar; import android.widget.TextView; +import com.android.car.apps.common.ImageUtils; import com.android.car.media.common.MediaItemMetadata; import com.android.car.media.common.PlaybackControls; import com.android.car.media.common.PlaybackModel; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.List; - -import android.support.v7.widget.RecyclerView; +import java.util.Locale; import androidx.car.widget.ListItem; import androidx.car.widget.ListItemAdapter; @@ -34,16 +40,21 @@ import androidx.car.widget.TextListItem; */ public class PlaybackFragment extends Fragment { private static final String TAG = "PlaybackFragment"; + private static final DateFormat TIME_FORMAT = new SimpleDateFormat("m:ss", Locale.US); private PlaybackModel mModel; private CrossfadeImageView mAlbumBackground; private PlaybackControls mPlaybackControls; private ImageView mAlbumArt; private TextView mTitle; + private TextView mTime; private TextView mSubtitle; private SeekBar mSeekbar; private PagedListView mBrowseList; private ListItemAdapter mMediaAdapter; + private int mBackgroundRawImageSize; + private float mBackgroundBlurRadius; + private float mBackgroundBlurScale; private PlaybackModel.PlaybackObserver mObserver = new PlaybackModel.PlaybackObserver() { @Override @@ -77,9 +88,9 @@ public class PlaybackFragment extends Fragment { } MediaItemMetadata item = queue.get(position); TextListItem textListItem = new TextListItem(getContext()); - textListItem.setTitle(item.mTitle.toString()); - textListItem.setBody(item.mSubtitle.toString()); - textListItem.setOnClickListener(v -> mModel.onSkipToQueueItem(item.mQueueId)); + textListItem.setTitle(item.getTitle().toString()); + textListItem.setBody(item.getSubtitle().toString()); + textListItem.setOnClickListener(v -> mModel.onSkipToQueueItem(item.getQueueId())); return textListItem; } @@ -107,6 +118,7 @@ public class PlaybackFragment extends Fragment { mTitle = view.findViewById(R.id.title); mSubtitle = view.findViewById(R.id.subtitle); mSeekbar = view.findViewById(R.id.seek_bar); + mTime = view.findViewById(R.id.time); mBrowseList = view.findViewById(R.id.browse_list); mMediaAdapter = new ListItemAdapter(getContext(), mMediaItemsProvider); mBrowseList.setAdapter(mMediaAdapter); @@ -114,6 +126,13 @@ public class PlaybackFragment extends Fragment { recyclerView.setVerticalFadingEdgeEnabled(true); recyclerView.setFadingEdgeLength(getResources() .getDimensionPixelSize(R.dimen.car_padding_3)); + TypedValue outValue = new TypedValue(); + getResources().getValue(R.dimen.playback_background_blur_radius, outValue, true); + mBackgroundBlurRadius = outValue.getFloat(); + getResources().getValue(R.dimen.playback_background_blur_scale, outValue, true); + mBackgroundBlurScale = outValue.getFloat(); + mBackgroundRawImageSize = getContext().getResources().getDimensionPixelSize( + R.dimen.playback_background_raw_image_size); return view; } @@ -132,9 +151,8 @@ public class PlaybackFragment extends Fragment { } private void updateState() { - int maxProgress = mModel.getMaxProgress(); - mSeekbar.setVisibility(maxProgress > 0 ? View.VISIBLE : View.INVISIBLE); - mSeekbar.setMax(maxProgress); + updateProgress(); + if (mModel.isPlaying()) { mSeekbar.post(mSeekBarRunnable); } else { @@ -145,11 +163,26 @@ public class PlaybackFragment extends Fragment { private void updateMetadata() { MediaItemMetadata metadata = mModel.getMetadata(); - mTitle.setText(metadata != null ? metadata.mTitle : null); - mSubtitle.setText(metadata != null ? metadata.mSubtitle : null); - Bitmap art = metadata != null ? metadata.getAlbumArt() : null; - mAlbumArt.setImageBitmap(art); - mAlbumBackground.setImageBitmap(art, true); + mTitle.setText(metadata != null ? metadata.getTitle() : null); + mSubtitle.setText(metadata != null ? metadata.getSubtitle() : null); + MediaItemMetadata.updateImageView(getContext(), metadata, mAlbumArt, 0); + if (metadata != null) { + metadata.getAlbumArt(getContext(), + mBackgroundRawImageSize, + mBackgroundRawImageSize, + false) + .thenAccept(this::setBackgroundImage); + } else { + mAlbumBackground.setImageBitmap(null, true); + } + } + + private void setBackgroundImage(Bitmap bitmap) { + // TODO(b/77551865): Implement image blurring once the following issue is solved: + // b/77551557 + // bitmap = ImageUtils.blur(getContext(), bitmap, mBackgroundBlurScale, + // mBackgroundBlurRadius); + mAlbumBackground.setImageBitmap(bitmap, true); } private void updateAccentColor() { @@ -165,11 +198,23 @@ public class PlaybackFragment extends Fragment { if (!mModel.isPlaying()) { return; } - mSeekbar.setProgress(mModel.getProgress()); + updateProgress(); mSeekbar.postDelayed(this, SEEK_BAR_UPDATE_TIME_INTERVAL_MS); + } }; + private void updateProgress() { + long maxProgress = mModel.getMaxProgress(); + String time = String.format("%s / %s", + TIME_FORMAT.format(new Date(mModel.getProgress())), + TIME_FORMAT.format(new Date(maxProgress))); + mTime.setText(time); + mSeekbar.setVisibility(maxProgress > 0 ? View.VISIBLE : View.INVISIBLE); + mSeekbar.setMax((int) mModel.getMaxProgress()); + mSeekbar.setProgress((int) mModel.getProgress()); + } + /** * Collapses the playback controls. */ |