diff options
19 files changed, 341 insertions, 252 deletions
diff --git a/build/sdk.atree b/build/sdk.atree index 8c678a895..124fc8855 100644 --- a/build/sdk.atree +++ b/build/sdk.atree @@ -328,6 +328,7 @@ developers/build/prebuilts/gradle/SkeletonWearableApp samples/${PLATFO developers/build/prebuilts/gradle/SpeedTracker samples/${PLATFORM_NAME}/wearable/SpeedTracker developers/build/prebuilts/gradle/SynchronizedNotifications samples/${PLATFORM_NAME}/wearable/SynchronizedNotifications developers/build/prebuilts/gradle/Timer samples/${PLATFORM_NAME}/wearable/Timer +developers/build/prebuilts/gradle/WatchFace samples/${PLATFORM_NAME}/wearable/WatchFace developers/build/prebuilts/gradle/WatchViewStub samples/${PLATFORM_NAME}/wearable/WatchViewStub # Old sample tree diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java index b503bcf0e..4c56933e7 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java @@ -124,8 +124,12 @@ public class AnimatedRecyclerView extends Activity { public void itemClicked(View view) { ViewGroup parent = (ViewGroup) view; MyViewHolder holder = (MyViewHolder) mRecyclerView.getChildViewHolder(parent); + final int position = holder.getAdapterPosition(); + if (position == RecyclerView.NO_POSITION) { + return; + } mAdapter.toggleExpanded(holder); - mAdapter.notifyItemChanged(holder.getPosition()); + mAdapter.notifyItemChanged(position); } public void deleteItem(View view) { @@ -240,7 +244,7 @@ public class AnimatedRecyclerView extends Activity { if (lastVisibleView != null) { RecyclerView.LayoutParams lastParams = (RecyclerView.LayoutParams) lastVisibleView.getLayoutParams(); - int lastPosition = lastParams.getViewPosition(); + int lastPosition = lastParams.getViewLayoutPosition(); final List<RecyclerView.ViewHolder> previousViews = recycler.getScrapList(); count = previousViews.size(); for (int i = 0; i < count; ++i) { @@ -250,7 +254,7 @@ public class AnimatedRecyclerView extends Activity { if (params.isItemRemoved()) { continue; } - int position = params.getViewPosition(); + int position = params.getViewLayoutPosition(); int newTop; if (position < mFirstPosition) { newTop = view.getHeight() * (position - mFirstPosition); diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java index 0a6ac6d36..4bb64f4b1 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java @@ -84,11 +84,10 @@ abstract public class BaseLayoutManagerActivity<T extends RecyclerView.LayoutMan vh.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - final int pos = vh.getPosition(); - if (pos + 1 < getItemCount()) { + final int pos = vh.getAdapterPosition(); + if (pos != RecyclerView.NO_POSITION && pos + 1 < getItemCount()) { swap(pos, pos + 1); } - notifyItemChanged(pos); } }); return vh; diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java index 00cfbf86a..ef25c0b0e 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java @@ -119,11 +119,13 @@ public class GridLayoutManagerActivity extends BaseLayoutManagerActivity<GridLay vh.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - final int pos = vh.getPosition(); + final int pos = vh.getAdapterPosition(); + if (pos == RecyclerView.NO_POSITION) { + return; + } if (pos + 1 < getItemCount()) { swap(pos, pos + 1); } - notifyItemChanged(pos); } }); return vh; diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/RecyclerViewActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/RecyclerViewActivity.java index 747992b19..38b50bd3a 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/widget/RecyclerViewActivity.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/RecyclerViewActivity.java @@ -56,7 +56,10 @@ public class RecyclerViewActivity extends Activity { vh.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - final int pos = vh.getPosition(); + final int pos = vh.getAdapterPosition(); + if (pos == RecyclerView.NO_POSITION) { + return; + } if (pos + 1 < getItemCount()) { swap(pos, pos + 1); } diff --git a/samples/SupportLeanbackDemos/AndroidManifest.xml b/samples/SupportLeanbackDemos/AndroidManifest.xml index 68016c52a..e9fc37c63 100644 --- a/samples/SupportLeanbackDemos/AndroidManifest.xml +++ b/samples/SupportLeanbackDemos/AndroidManifest.xml @@ -10,6 +10,7 @@ android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:banner="@drawable/ic_launcher" + android:supportsRtl="true" android:theme="@style/Theme.Example.Leanback"> <activity android:name="MainActivity" diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java index f11c84389..c37ca204e 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java @@ -13,299 +13,395 @@ */ package com.example.android.leanback; -import java.util.ArrayList; - import android.content.Context; -import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.media.session.MediaController; +import android.media.session.MediaSessionManager; +import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.RemoteException; +import android.support.v17.leanback.app.MediaControllerGlue; +import android.support.v17.leanback.app.PlaybackControlGlue; import android.support.v17.leanback.widget.Action; import android.support.v17.leanback.widget.ArrayObjectAdapter; -import android.support.v17.leanback.widget.ClassPresenterSelector; -import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter; import android.support.v17.leanback.widget.PlaybackControlsRow; -import android.support.v17.leanback.widget.PlaybackControlsRow.PlayPauseAction; import android.support.v17.leanback.widget.PlaybackControlsRow.RepeatAction; import android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsUpAction; import android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsDownAction; -import android.support.v17.leanback.widget.PlaybackControlsRow.ShuffleAction; -import android.support.v17.leanback.widget.PlaybackControlsRow.SkipNextAction; -import android.support.v17.leanback.widget.PlaybackControlsRow.SkipPreviousAction; import android.support.v17.leanback.widget.PlaybackControlsRowPresenter; import android.support.v17.leanback.widget.HeaderItem; -import android.support.v17.leanback.widget.VerticalGridView; +import android.support.v17.leanback.widget.PresenterSelector; import android.support.v17.leanback.widget.Row; import android.support.v17.leanback.widget.ListRow; import android.support.v17.leanback.widget.Presenter; import android.support.v17.leanback.widget.RowPresenter; import android.support.v17.leanback.widget.ListRowPresenter; -import android.support.v17.leanback.widget.OnActionClickedListener; import android.support.v17.leanback.widget.OnItemViewSelectedListener; import android.support.v17.leanback.widget.OnItemViewClickedListener; import android.support.v17.leanback.widget.ControlButtonPresenterSelector; +import android.support.v17.leanback.widget.SparseArrayObjectAdapter; +import android.support.v4.media.session.MediaControllerCompat; +import android.support.v4.media.session.MediaSessionCompat; import android.util.Log; import android.widget.Toast; +import java.util.List; + public class PlaybackOverlayFragment extends android.support.v17.leanback.app.PlaybackOverlayFragment { private static final String TAG = "leanback.PlaybackControlsFragment"; - private static final boolean SHOW_DETAIL = true; - private static final boolean HIDE_MORE_ACTIONS = false; - private static final int PRIMARY_CONTROLS = 5; - private static final boolean SHOW_IMAGE = PRIMARY_CONTROLS <= 5; + /** + * Change this to choose a different overlay background. + */ private static final int BACKGROUND_TYPE = PlaybackOverlayFragment.BG_LIGHT; - private static final int MORE_ROWS = 3; - private ArrayObjectAdapter mRowsAdapter; - private ArrayObjectAdapter mPrimaryActionsAdapter; - private ArrayObjectAdapter mSecondaryActionsAdapter; - private PlayPauseAction mPlayPauseAction; + /** + * Change the number of related content rows. + */ + private static final int RELATED_CONTENT_ROWS = 3; + + /** + * Change the location of the thumbs up/down controls + */ + private static final boolean THUMBS_PRIMARY = true; + + /** + * Change this to select hidden + */ + private static final boolean SECONDARY_HIDDEN = false; + + private static final String FAUX_TITLE = "A short song of silence"; + private static final String FAUX_SUBTITLE = "2014"; + private static final int FAUX_DURATION = 33 * 1000; + + private static final int ROW_CONTROLS = 0; + + private PlaybackControlGlue mGlue; + private PlaybackControlsRowPresenter mPlaybackControlsRowPresenter; + private ListRowPresenter mListRowPresenter; + private RepeatAction mRepeatAction; private ThumbsUpAction mThumbsUpAction; private ThumbsDownAction mThumbsDownAction; - private ShuffleAction mShuffleAction; - private SkipNextAction mSkipNextAction; - private SkipPreviousAction mSkipPreviousAction; - private PlaybackControlsRow mPlaybackControlsRow; - private ArrayList<MediaItem> mItems = new ArrayList<MediaItem>(); - private int mCurrentItem; private Handler mHandler; - private Runnable mRunnable; + + // These should match the playback service FF behavior + private int[] mFastForwardSpeeds = { 2, 3, 4, 5 }; + + private OnItemViewClickedListener mOnItemViewClickedListener = new OnItemViewClickedListener() { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + if (item instanceof Action) { + onActionClicked((Action) item); + } + } + }; + + private OnItemViewSelectedListener mOnItemViewSelectedListener = new OnItemViewSelectedListener() { + @Override + public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemSelected: " + item + " row " + row); + } + }; + + final Runnable mUpdateProgressRunnable = new Runnable() { + @Override + public void run() { + mGlue.updateProgress(); + mHandler.postDelayed(this, mGlue.getUpdatePeriod()); + } + }; + + public SparseArrayObjectAdapter getAdapter() { + return (SparseArrayObjectAdapter) super.getAdapter(); + } @Override public void onCreate(Bundle savedInstanceState) { Log.i(TAG, "onCreate"); super.onCreate(savedInstanceState); + setBackgroundType(BACKGROUND_TYPE); + setOnItemViewSelectedListener(mOnItemViewSelectedListener); + + createComponents(getActivity()); + } + + private void createComponents(Context context) { mHandler = new Handler(); + mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context); + mThumbsUpAction.setIndex(ThumbsUpAction.OUTLINE); + mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context); + mThumbsDownAction.setIndex(ThumbsDownAction.OUTLINE); + mRepeatAction = new PlaybackControlsRow.RepeatAction(context); + + mGlue = new PlaybackControlGlue(context, this, mFastForwardSpeeds) { + private boolean mIsPlaying; + private int mSpeed = PlaybackControlGlue.PLAYBACK_SPEED_PAUSED; + private long mStartTime; + private long mStartPosition = 0; - setBackgroundType(BACKGROUND_TYPE); - setFadingEnabled(false); + @Override + protected SparseArrayObjectAdapter createPrimaryActionsAdapter( + PresenterSelector presenterSelector) { + return PlaybackOverlayFragment.this.createPrimaryActionsAdapter( + presenterSelector); + } + + @Override + public boolean hasValidMedia() { + return true; + } - setupRows(); + @Override + public boolean isMediaPlaying() { + return mIsPlaying; + } - setOnItemViewSelectedListener(new OnItemViewSelectedListener() { @Override - public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, - RowPresenter.ViewHolder rowViewHolder, Row row) { - Log.i(TAG, "onItemSelected: " + item + " row " + row); + public CharSequence getMediaTitle() { + return FAUX_TITLE; } - }); - setOnItemViewClickedListener(new OnItemViewClickedListener() { + @Override - public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, - RowPresenter.ViewHolder rowViewHolder, Row row) { - Log.i(TAG, "onItemClicked: " + item + " row " + row); + public CharSequence getMediaSubtitle() { + return FAUX_SUBTITLE; } - }); - } + @Override + public int getMediaDuration() { + return FAUX_DURATION; + } - private void setupRows() { - ClassPresenterSelector ps = new ClassPresenterSelector(); + @Override + public Drawable getMediaArt() { + return null; + } - PlaybackControlsRowPresenter playbackControlsRowPresenter; - if (SHOW_DETAIL) { - playbackControlsRowPresenter = new PlaybackControlsRowPresenter( - new DescriptionPresenter()); - } else { - playbackControlsRowPresenter = new PlaybackControlsRowPresenter(); - } - playbackControlsRowPresenter.setOnActionClickedListener(new OnActionClickedListener() { - public void onActionClicked(Action action) { - if (action.getId() == mPlayPauseAction.getId()) { - if (mPlayPauseAction.getIndex() == PlayPauseAction.PLAY) { - startProgressAutomation(); - setFadingEnabled(true); - } else { - stopProgressAutomation(); - setFadingEnabled(false); + @Override + public long getSupportedActions() { + return PlaybackControlGlue.ACTION_PLAY_PAUSE | + PlaybackControlGlue.ACTION_FAST_FORWARD | + PlaybackControlGlue.ACTION_REWIND; + } + + @Override + public int getCurrentSpeedId() { + return mSpeed; + } + + @Override + public int getCurrentPosition() { + int speed; + if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_PAUSED) { + speed = 0; + } else if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_NORMAL) { + speed = 1; + } else if (mSpeed >= PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0) { + int index = mSpeed - PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0; + speed = getFastForwardSpeeds()[index]; + } else if (mSpeed <= -PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0) { + int index = -mSpeed - PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0; + speed = -getRewindSpeeds()[index]; + } else { + return -1; + } + long position = mStartPosition + + (System.currentTimeMillis() - mStartTime) * speed; + if (position > getMediaDuration()) { + position = getMediaDuration(); + onPlaybackComplete(true); + } else if (position < 0) { + position = 0; + onPlaybackComplete(false); + } + return (int) position; + } + + void onPlaybackComplete(final boolean ended) { + mHandler.post(new Runnable() { + @Override + public void run() { + if (mRepeatAction.getIndex() == RepeatAction.NONE) { + pausePlayback(); + } else { + startPlayback(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL); + } + mStartPosition = 0; + onStateChanged(); } - } else if (action.getId() == mSkipNextAction.getId()) { - next(); - } else if (action.getId() == mSkipPreviousAction.getId()) { - Toast.makeText(getActivity(), "TODO", Toast.LENGTH_SHORT).show(); + }); + } + + @Override + protected void startPlayback(int speed) { + if (speed == mSpeed) { + return; } - if (action instanceof PlaybackControlsRow.MultiAction) { - ((PlaybackControlsRow.MultiAction) action).nextIndex(); - notifyChanged(action); + mStartPosition = getCurrentPosition(); + mSpeed = speed; + mIsPlaying = true; + mStartTime = System.currentTimeMillis(); + } + + @Override + protected void pausePlayback() { + if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_PAUSED) { + return; } + mStartPosition = getCurrentPosition(); + mSpeed = PlaybackControlGlue.PLAYBACK_SPEED_PAUSED; + mIsPlaying = false; } - }); - playbackControlsRowPresenter.setSecondaryActionsHidden(HIDE_MORE_ACTIONS); - ps.addClassPresenter(PlaybackControlsRow.class, playbackControlsRowPresenter); - ps.addClassPresenter(ListRow.class, new ListRowPresenter()); - mRowsAdapter = new ArrayObjectAdapter(ps); + @Override + protected void skipToNext() { + // Not supported + } - addPlaybackControlsRow(); - addOtherRows(); + @Override + protected void skipToPrevious() { + // Not supported + } - setAdapter(mRowsAdapter); - } + @Override + protected void onRowChanged(PlaybackControlsRow row) { + PlaybackOverlayFragment.this.onRowChanged(row); + } - private void addPlaybackControlsRow() { - Context context = getActivity(); + @Override + public void enableProgressUpdating(boolean enable) { + PlaybackOverlayFragment.this.enableProgressUpdating(enable); + } - if (SHOW_DETAIL) { - mPlaybackControlsRow = new PlaybackControlsRow(new MediaItem()); - } else { - mPlaybackControlsRow = new PlaybackControlsRow(); - } - mRowsAdapter.add(mPlaybackControlsRow); - - mItems = new ArrayList<MediaItem>(); - mItems.add(new MediaItem("Awesome Tune", "The More Awesome Band", R.drawable.details_img, 15*1000)); - mItems.add(new MediaItem("Pretty nice Tune", "The Nice Guys", R.drawable.details_img, 10*1000)); - mCurrentItem = 1; - updatePlaybackRow(mCurrentItem); - - ControlButtonPresenterSelector presenterSelector = new ControlButtonPresenterSelector(); - mPrimaryActionsAdapter = new ArrayObjectAdapter(presenterSelector); - mSecondaryActionsAdapter = new ArrayObjectAdapter(presenterSelector); - mPlaybackControlsRow.setPrimaryActionsAdapter(mPrimaryActionsAdapter); - mPlaybackControlsRow.setSecondaryActionsAdapter(mSecondaryActionsAdapter); - - mPlayPauseAction = new PlayPauseAction(context); - mRepeatAction = new RepeatAction(context); - mThumbsUpAction = new ThumbsUpAction(context); - mThumbsDownAction = new ThumbsDownAction(context); - mShuffleAction = new ShuffleAction(context); - mSkipNextAction = new PlaybackControlsRow.SkipNextAction(context); - mSkipPreviousAction = new PlaybackControlsRow.SkipPreviousAction(context); - - if (PRIMARY_CONTROLS > 5) { - mPrimaryActionsAdapter.add(mThumbsUpAction); - } else { - mSecondaryActionsAdapter.add(mThumbsUpAction); - } - mPrimaryActionsAdapter.add(mSkipPreviousAction); - if (PRIMARY_CONTROLS > 3) { - mPrimaryActionsAdapter.add(new PlaybackControlsRow.RewindAction(context)); - } - mPrimaryActionsAdapter.add(mPlayPauseAction); - if (PRIMARY_CONTROLS > 3) { - mPrimaryActionsAdapter.add(new PlaybackControlsRow.FastForwardAction(context)); - } - mPrimaryActionsAdapter.add(mSkipNextAction); + @Override + public int getUpdatePeriod() { + return PlaybackOverlayFragment.this.getUpdatePeriod(); + } + }; - mSecondaryActionsAdapter.add(mRepeatAction); - mSecondaryActionsAdapter.add(mShuffleAction); - if (PRIMARY_CONTROLS > 5) { - mPrimaryActionsAdapter.add(mThumbsDownAction); - } else { - mSecondaryActionsAdapter.add(mThumbsDownAction); - } - mSecondaryActionsAdapter.add(new PlaybackControlsRow.HighQualityAction(context)); - mSecondaryActionsAdapter.add(new PlaybackControlsRow.ClosedCaptioningAction(context)); - } + mGlue.setOnItemViewClickedListener(mOnItemViewClickedListener); - private void notifyChanged(Action action) { - ArrayObjectAdapter adapter = mPrimaryActionsAdapter; - if (adapter.indexOf(action) >= 0) { - adapter.notifyArrayItemRangeChanged(adapter.indexOf(action), 1); - return; - } - adapter = mSecondaryActionsAdapter; - if (adapter.indexOf(action) >= 0) { - adapter.notifyArrayItemRangeChanged(adapter.indexOf(action), 1); - return; - } - } + mPlaybackControlsRowPresenter = mGlue.createControlsRowAndPresenter(); + mPlaybackControlsRowPresenter.setSecondaryActionsHidden(SECONDARY_HIDDEN); + mListRowPresenter = new ListRowPresenter(); - private void updatePlaybackRow(int index) { - if (mPlaybackControlsRow.getItem() != null) { - MediaItem item = (MediaItem) mPlaybackControlsRow.getItem(); - item.title = mItems.get(index).title; - item.subtitle = mItems.get(index).subtitle; + setAdapter(new SparseArrayObjectAdapter(new PresenterSelector() { + @Override + public Presenter getPresenter(Object object) { + if (object instanceof PlaybackControlsRow) { + return mPlaybackControlsRowPresenter; + } else if (object instanceof ListRow) { + return mListRowPresenter; + } + throw new IllegalArgumentException("Unhandled object: " + object); + } + })); + + // Set secondary control actions + PlaybackControlsRow controlsRow = mGlue.getControlsRow(); + ArrayObjectAdapter adapter = new ArrayObjectAdapter(new ControlButtonPresenterSelector()); + controlsRow.setSecondaryActionsAdapter(adapter); + if (!THUMBS_PRIMARY) { + adapter.add(mThumbsDownAction); } - if (SHOW_IMAGE) { - mPlaybackControlsRow.setImageDrawable(getResources().getDrawable( - mItems.get(mCurrentItem).imageResId)); + adapter.add(mRepeatAction); + if (!THUMBS_PRIMARY) { + adapter.add(mThumbsUpAction); } - mRowsAdapter.notifyArrayItemRangeChanged(0, 1); - mPlaybackControlsRow.setTotalTime(mItems.get(mCurrentItem).durationMs); - mPlaybackControlsRow.setCurrentTime(0); - mPlaybackControlsRow.setBufferedProgress(75 * 1000); - } + // Add the controls row + getAdapter().set(ROW_CONTROLS, controlsRow); - private void addOtherRows() { - for (int i = 0; i < MORE_ROWS; ++i) { + // Add related content rows + for (int i = 0; i < RELATED_CONTENT_ROWS; ++i) { ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter()); listRowAdapter.add("Some related content"); listRowAdapter.add("Other related content"); HeaderItem header = new HeaderItem(i, "Row " + i); - mRowsAdapter.add(new ListRow(header, listRowAdapter)); + getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter)); } } - private int getUpdatePeriod() { - if (getView() == null || mPlaybackControlsRow.getTotalTime() <= 0) { - return 1000; + private SparseArrayObjectAdapter createPrimaryActionsAdapter( + PresenterSelector presenterSelector) { + SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(presenterSelector); + if (THUMBS_PRIMARY) { + adapter.set(PlaybackControlGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction); + adapter.set(PlaybackControlGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction); } - return Math.max(16, mPlaybackControlsRow.getTotalTime() / getView().getWidth()); + return adapter; } - private void startProgressAutomation() { - mRunnable = new Runnable() { - @Override - public void run() { - int updatePeriod = getUpdatePeriod(); - int currentTime = mPlaybackControlsRow.getCurrentTime() + updatePeriod; - int totalTime = mPlaybackControlsRow.getTotalTime(); - mPlaybackControlsRow.setCurrentTime(currentTime); - if (totalTime > 0 && totalTime <= currentTime) { - next(); - } - mHandler.postDelayed(this, updatePeriod); - } - }; - mHandler.postDelayed(mRunnable, getUpdatePeriod()); + private void onRowChanged(PlaybackControlsRow row) { + if (getAdapter() == null) { + return; + } + int index = getAdapter().indexOf(row); + if (index >= 0) { + getAdapter().notifyArrayItemRangeChanged(index, 1); + } } - private void next() { - if (++mCurrentItem >= mItems.size()) { - mCurrentItem = 0; + private void enableProgressUpdating(boolean enable) { + Log.v(TAG, "enableProgressUpdating " + enable + " this " + this); + mHandler.removeCallbacks(mUpdateProgressRunnable); + if (enable) { + mUpdateProgressRunnable.run(); } - updatePlaybackRow(mCurrentItem); } - private void stopProgressAutomation() { - if (mHandler != null && mRunnable != null) { - mHandler.removeCallbacks(mRunnable); + private int getUpdatePeriod() { + int totalTime = mGlue.getControlsRow().getTotalTime(); + if (getView() == null || totalTime <= 0) { + return 1000; } + return Math.max(16, totalTime / getView().getWidth()); } - @Override - public void onStop() { - stopProgressAutomation(); - super.onStop(); + private void onActionClicked(Action action) { + Log.v(TAG, "onActionClicked " + action); + Toast.makeText(getActivity(), action.toString(), Toast.LENGTH_SHORT).show(); + if (action instanceof PlaybackControlsRow.MultiAction) { + PlaybackControlsRow.MultiAction multiAction = (PlaybackControlsRow.MultiAction) action; + multiAction.nextIndex(); + notifyActionChanged(multiAction); + } } - static class MediaItem { - String title; - String subtitle; - int imageResId; - int durationMs; + private SparseArrayObjectAdapter getPrimaryActionsAdapter() { + return (SparseArrayObjectAdapter) mGlue.getControlsRow().getPrimaryActionsAdapter(); + } - MediaItem() { - } + private ArrayObjectAdapter getSecondaryActionsAdapter() { + return (ArrayObjectAdapter) mGlue.getControlsRow().getSecondaryActionsAdapter(); + } - MediaItem(String title, String subtitle, int imageResId, int durationMs) { - this.title = title; - this.subtitle = subtitle; - this.imageResId = imageResId; - this.durationMs = durationMs; + private void notifyActionChanged(PlaybackControlsRow.MultiAction action) { + int index; + index = getPrimaryActionsAdapter().indexOf(action); + if (index >= 0) { + getPrimaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); + } else { + index = getSecondaryActionsAdapter().indexOf(action); + if (index >= 0) { + getSecondaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); + } } } - static class DescriptionPresenter extends AbstractDetailsDescriptionPresenter { - @Override - protected void onBindDescription(ViewHolder vh, Object item) { - vh.getTitle().setText(((MediaItem) item).title); - vh.getSubtitle().setText(((MediaItem) item).subtitle); - } + @Override + public void onStart() { + super.onStart(); + mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying()); + } + + @Override + public void onStop() { + mGlue.enableProgressUpdating(false); + super.onStop(); } } diff --git a/samples/browseable/MediaBrowserService/res/drawable-night-xxhdpi/ic_star_off.png b/samples/browseable/MediaBrowserService/res/drawable-night-xxhdpi/ic_star_off.png Binary files differdeleted file mode 100644 index e435d2a9f..000000000 --- a/samples/browseable/MediaBrowserService/res/drawable-night-xxhdpi/ic_star_off.png +++ /dev/null diff --git a/samples/browseable/MediaBrowserService/res/drawable-night-xxhdpi/ic_star_on.png b/samples/browseable/MediaBrowserService/res/drawable-night-xxhdpi/ic_star_on.png Binary files differdeleted file mode 100644 index 0c75bb6da..000000000 --- a/samples/browseable/MediaBrowserService/res/drawable-night-xxhdpi/ic_star_on.png +++ /dev/null diff --git a/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_off.png b/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_off.png Binary files differindex 836085b68..fb7afb0c9 100644 --- a/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_off.png +++ b/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_off.png diff --git a/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_on.png b/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_on.png Binary files differindex 7cd6cfc52..6f7fc75e1 100644 --- a/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_on.png +++ b/samples/browseable/MediaBrowserService/res/drawable-xxhdpi/ic_star_on.png diff --git a/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicPlayerActivity.java b/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicPlayerActivity.java index 648d26896..394b01ad2 100644 --- a/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicPlayerActivity.java +++ b/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicPlayerActivity.java @@ -17,7 +17,6 @@ package com.example.android.mediabrowserservice; import android.app.Activity; import android.media.browse.MediaBrowser; -import android.media.session.MediaController; import android.os.Bundle; /** @@ -28,9 +27,6 @@ public class MusicPlayerActivity extends Activity private static final String TAG = MusicPlayerActivity.class.getSimpleName(); - private MediaBrowser mMediaBrowser; - private MediaController mMediaController; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicService.java b/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicService.java index 1c8744f00..b48242664 100644 --- a/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicService.java +++ b/samples/browseable/MediaBrowserService/src/com.example.android.mediabrowserservice/MusicService.java @@ -39,7 +39,6 @@ import android.os.PowerManager; import android.os.SystemClock; import android.service.media.MediaBrowserService; -import com.example.android.mediabrowserservice.PackageValidator; import com.example.android.mediabrowserservice.model.MusicProvider; import com.example.android.mediabrowserservice.utils.LogHelper; import com.example.android.mediabrowserservice.utils.MediaIDHelper; @@ -379,6 +378,11 @@ public class MusicService extends MediaBrowserService implements OnPreparedListe @Override public void onSkipToQueueItem(long queueId) { LogHelper.d(TAG, "OnSkipToQueueItem:" + queueId); + + if (mState == PlaybackState.STATE_PAUSED) { + mState = PlaybackState.STATE_STOPPED; + } + if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) { // set the current index on queue from the music Id: @@ -393,6 +397,10 @@ public class MusicService extends MediaBrowserService implements OnPreparedListe public void onPlayFromMediaId(String mediaId, Bundle extras) { LogHelper.d(TAG, "playFromMediaId mediaId:", mediaId, " extras=", extras); + if (mState == PlaybackState.STATE_PAUSED) { + mState = PlaybackState.STATE_STOPPED; + } + // The mediaId used here is not the unique musicId. This one comes from the // MediaBrowser, and is actually a "hierarchy-aware mediaID": a concatenation of // the hierarchy in MediaBrowser and the actual unique musicID. This is necessary @@ -406,6 +414,7 @@ public class MusicService extends MediaBrowserService implements OnPreparedListe if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) { String uniqueMusicID = MediaIDHelper.extractMusicIDFromMediaID(mediaId); + // set the current index on queue from the music Id: mCurrentIndexOnQueue = QueueHelper.getMusicIndexOnQueue( mPlayingQueue, uniqueMusicID); @@ -435,7 +444,7 @@ public class MusicService extends MediaBrowserService implements OnPreparedListe mCurrentIndexOnQueue = 0; } if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) { - mState = PlaybackState.STATE_PLAYING; + mState = PlaybackState.STATE_STOPPED; handlePlayRequest(); } else { LogHelper.e(TAG, "skipToNext: cannot skip to next. next Index=" + @@ -448,7 +457,6 @@ public class MusicService extends MediaBrowserService implements OnPreparedListe @Override public void onSkipToPrevious() { LogHelper.d(TAG, "skipToPrevious"); - mCurrentIndexOnQueue--; if (mPlayingQueue != null && mCurrentIndexOnQueue < 0) { // This sample's behavior: skipping to previous when in first song restarts the @@ -456,7 +464,7 @@ public class MusicService extends MediaBrowserService implements OnPreparedListe mCurrentIndexOnQueue = 0; } if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) { - mState = PlaybackState.STATE_PLAYING; + mState = PlaybackState.STATE_STOPPED; handlePlayRequest(); } else { LogHelper.e(TAG, "skipToPrevious: cannot skip to previous. previous Index=" + @@ -486,12 +494,15 @@ public class MusicService extends MediaBrowserService implements OnPreparedListe public void onPlayFromSearch(String query, Bundle extras) { LogHelper.d(TAG, "playFromSearch query=", query); + if (mState == PlaybackState.STATE_PAUSED) { + mState = PlaybackState.STATE_STOPPED; + } + mPlayingQueue = QueueHelper.getPlayingQueueFromSearch(query, mMusicProvider); LogHelper.d(TAG, "playFromSearch playqueue.length=" + mPlayingQueue.size()); mSession.setQueue(mPlayingQueue); if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) { - // start playing from the beginning of the queue mCurrentIndexOnQueue = 0; diff --git a/samples/browseable/MessagingService/res/layout-land/fragment_message_me.xml b/samples/browseable/MessagingService/res/layout-land/fragment_message_me.xml index 8f7b60a23..6f4f88bac 100644 --- a/samples/browseable/MessagingService/res/layout-land/fragment_message_me.xml +++ b/samples/browseable/MessagingService/res/layout-land/fragment_message_me.xml @@ -61,7 +61,6 @@ android:layout_above="@id/clear" android:layout_width="match_parent" android:layout_height="match_parent" - android:maxLines="20" android:scrollbars="vertical"/> </RelativeLayout> </LinearLayout> diff --git a/samples/browseable/MessagingService/res/layout/fragment_message_me.xml b/samples/browseable/MessagingService/res/layout/fragment_message_me.xml index d01c5137a..29a8c441a 100644 --- a/samples/browseable/MessagingService/res/layout/fragment_message_me.xml +++ b/samples/browseable/MessagingService/res/layout/fragment_message_me.xml @@ -47,7 +47,6 @@ android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" - android:maxLines="20" android:scrollbars="vertical"/> <Button android:layout_width="match_parent" diff --git a/samples/browseable/MessagingService/src/com.example.android.messagingservice/Conversations.java b/samples/browseable/MessagingService/src/com.example.android.messagingservice/Conversations.java index 210e061f0..7425df499 100644 --- a/samples/browseable/MessagingService/src/com.example.android.messagingservice/Conversations.java +++ b/samples/browseable/MessagingService/src/com.example.android.messagingservice/Conversations.java @@ -45,10 +45,10 @@ public class Conversations { * Senders of the said messages. */ private static final String[] PARTICIPANTS = new String[]{ - "John Rambo", - "Han Solo", - "Rocky Balboa", - "Lara Croft" + "John Smith", + "Robert Lawrence", + "James Smith", + "Jane Doe" }; static class Conversation { diff --git a/samples/browseable/SpeedTracker/Application/AndroidManifest.xml b/samples/browseable/SpeedTracker/Application/AndroidManifest.xml index 3361a44df..97db73217 100644 --- a/samples/browseable/SpeedTracker/Application/AndroidManifest.xml +++ b/samples/browseable/SpeedTracker/Application/AndroidManifest.xml @@ -12,7 +12,7 @@ android:glEsVersion="0x00020000" android:required="true"/> <uses-sdk android:minSdkVersion="18" - android:targetSdkVersion="19" /> + android:targetSdkVersion="20" /> <application android:name=".PhoneApplication" diff --git a/samples/browseable/SpeedTracker/Application/res/values-v21/template-styles.xml b/samples/browseable/SpeedTracker/Application/res/values-v21/template-styles.xml deleted file mode 100644 index 134fcd9d3..000000000 --- a/samples/browseable/SpeedTracker/Application/res/values-v21/template-styles.xml +++ /dev/null @@ -1,22 +0,0 @@ -<!-- - Copyright 2014 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> - - <!-- Activity themes --> - <style name="Theme.Base" parent="android:Theme.Material.Light" /> - -</resources> diff --git a/sdk/platform_source.prop_template b/sdk/platform_source.prop_template index da04c30dd..101ca237c 100644 --- a/sdk/platform_source.prop_template +++ b/sdk/platform_source.prop_template @@ -2,7 +2,7 @@ Pkg.Desc=Android SDK Platform ${PLATFORM_VERSION} Pkg.UserSrc=false Platform.Version=${PLATFORM_VERSION} Platform.CodeName=LOLLIPOP -Pkg.Revision=1 +Pkg.Revision=2 AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION} AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME} Layoutlib.Api=12 |
