blob: 7fb41b45207fb37af7f14cc8e828fcd51a44fa55 [file] [log] [blame]
The Android Open Source Project792a2202009-03-03 19:32:30 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.music;
18
Jack Hef02d3c62017-02-21 00:39:22 -050019import android.app.Activity;
The Android Open Source Project792a2202009-03-03 19:32:30 -080020import android.app.ListActivity;
The Android Open Source Project792a2202009-03-03 19:32:30 -080021import android.content.ComponentName;
The Android Open Source Project792a2202009-03-03 19:32:30 -080022import android.content.Context;
23import android.content.Intent;
Jack Hef02d3c62017-02-21 00:39:22 -050024import android.graphics.Color;
25import android.graphics.drawable.Drawable;
The Android Open Source Project792a2202009-03-03 19:32:30 -080026import android.media.AudioManager;
Jack Hef02d3c62017-02-21 00:39:22 -050027import android.media.MediaDescription;
28import android.media.MediaMetadata;
29import android.media.browse.MediaBrowser;
30import android.media.session.MediaController;
31import android.media.session.MediaSession;
The Android Open Source Project792a2202009-03-03 19:32:30 -080032import android.os.Bundle;
The Android Open Source Project792a2202009-03-03 19:32:30 -080033import android.util.Log;
Jack Hef02d3c62017-02-21 00:39:22 -050034import android.view.LayoutInflater;
The Android Open Source Project792a2202009-03-03 19:32:30 -080035import android.view.View;
36import android.view.ViewGroup;
37import android.view.Window;
Jack Hef02d3c62017-02-21 00:39:22 -050038import android.widget.*;
39import com.android.music.utils.LogHelper;
40import com.android.music.utils.MediaIDHelper;
The Android Open Source Project792a2202009-03-03 19:32:30 -080041
Jack Hef02d3c62017-02-21 00:39:22 -050042import java.util.ArrayList;
43import java.util.List;
The Android Open Source Project792a2202009-03-03 19:32:30 -080044
Jack Hef02d3c62017-02-21 00:39:22 -050045/*
46This activity shows when there is a need for
47 1. Songs tab [withtab = true]
48 2. Browse songs within an album [withtab = false]
49 3. Browse songs within a playlist [withtab = false]
50 4. Browse songs within now playing queue [withtab = false]
51 */
52public class TrackBrowserActivity extends ListActivity {
53 private static final String TAG = LogHelper.makeLogTag(TrackBrowserActivity.class);
54 private static final MediaBrowser.MediaItem DEFAULT_PARENT_ITEM =
55 new MediaBrowser.MediaItem(new MediaDescription.Builder()
56 .setMediaId(MediaIDHelper.MEDIA_ID_MUSICS_BY_SONG)
57 .setTitle("Songs")
58 .build(),
59 MediaBrowser.MediaItem.FLAG_BROWSABLE);
The Android Open Source Project792a2202009-03-03 19:32:30 -080060
Jack Hef02d3c62017-02-21 00:39:22 -050061 // Underlining ListView of this Activity
The Android Open Source Project792a2202009-03-03 19:32:30 -080062 private ListView mTrackList;
Jack Hef02d3c62017-02-21 00:39:22 -050063 // The mediaId to be used for subscribing for children using the MediaBrowser.
64 private MediaBrowser.MediaItem mParentItem;
65 private MediaBrowser mMediaBrowser;
66 private TrackBrowseAdapter mBrowseListAdapter;
67 private boolean mWithTabs;
The Android Open Source Project792a2202009-03-03 19:32:30 -080068
Jack Hef02d3c62017-02-21 00:39:22 -050069 /**
70 * Called when the activity is first created.
71 */
The Android Open Source Project792a2202009-03-03 19:32:30 -080072 @Override
Jack Heb0fba8b2017-01-26 15:54:38 -080073 public void onCreate(Bundle icicle) {
Jack Hef02d3c62017-02-21 00:39:22 -050074 Log.d(TAG, "onCreate()");
The Android Open Source Project792a2202009-03-03 19:32:30 -080075 super.onCreate(icicle);
Jack Hef02d3c62017-02-21 00:39:22 -050076 // Process past states
Marco Nelissenec0c57a2009-12-12 12:27:11 -080077 Intent intent = getIntent();
The Android Open Source Project792a2202009-03-03 19:32:30 -080078 if (icicle != null) {
Jack Hef02d3c62017-02-21 00:39:22 -050079 LogHelper.d(TAG, "Launch by saved instance state");
80 mParentItem = icicle.getParcelable(MusicUtils.TAG_PARENT_ITEM);
81 mWithTabs = icicle.getBoolean(MusicUtils.TAG_WITH_TABS);
82 MusicUtils.updateNowPlaying(this);
83 } else if (intent != null) {
84 LogHelper.d(TAG, "Launch by intent");
Hansong Zhang80cfa562018-04-26 12:26:49 -070085 mParentItem = intent.getParcelableExtra(MusicUtils.TAG_PARENT_ITEM);
Jack Hef02d3c62017-02-21 00:39:22 -050086 mWithTabs = intent.getBooleanExtra(MusicUtils.TAG_WITH_TABS, false);
The Android Open Source Project792a2202009-03-03 19:32:30 -080087 }
Jack Hef02d3c62017-02-21 00:39:22 -050088 if (mParentItem == null) {
89 LogHelper.d(TAG, "Launch by default parameters");
90 mParentItem = DEFAULT_PARENT_ITEM;
91 mWithTabs = true;
92 }
93 if (mWithTabs) {
94 requestWindowFeature(Window.FEATURE_NO_TITLE);
95 }
96 setTitle(mParentItem.getDescription().getTitle());
97 setVolumeControlStream(AudioManager.STREAM_MUSIC);
The Android Open Source Project792a2202009-03-03 19:32:30 -080098
Jack Hef02d3c62017-02-21 00:39:22 -050099 // Init layout
100 LogHelper.d(TAG, "init layout");
The Android Open Source Project792a2202009-03-03 19:32:30 -0800101 setContentView(R.layout.media_picker_activity);
Jack Hef02d3c62017-02-21 00:39:22 -0500102 MusicUtils.updateButtonBar(this, R.id.songtab);
103
104 // Init the ListView
105 Log.d(TAG, "Creating ListView");
The Android Open Source Project792a2202009-03-03 19:32:30 -0800106 mTrackList = getListView();
Marco Nelissen355e1342010-07-30 17:34:03 -0700107 mTrackList.setCacheColorHint(0);
Jack Hef02d3c62017-02-21 00:39:22 -0500108 mTrackList.setTextFilterEnabled(true);
109 mBrowseListAdapter = (TrackBrowseAdapter) getLastNonConfigurationInstance();
110 if (mBrowseListAdapter == null) {
111 mBrowseListAdapter = new TrackBrowseAdapter(this, R.layout.track_list_item);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800112 }
Jack Hef02d3c62017-02-21 00:39:22 -0500113 setListAdapter(mBrowseListAdapter);
Marco Nelissen3193d7d2009-12-14 15:31:28 -0800114 // don't set the album art until after the view has been layed out
115 mTrackList.post(new Runnable() {
Marco Nelissen3193d7d2009-12-14 15:31:28 -0800116 public void run() {
Jack Hef02d3c62017-02-21 00:39:22 -0500117 mTrackList.setBackgroundColor(Color.WHITE);
118 mTrackList.setCacheColorHint(0);
Marco Nelissen3193d7d2009-12-14 15:31:28 -0800119 }
120 });
The Android Open Source Project792a2202009-03-03 19:32:30 -0800121
Jack Hef02d3c62017-02-21 00:39:22 -0500122 // Create media browser
123 Log.d(TAG, "Creating MediaBrowser");
124 mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
125 mConnectionCallback, null);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800126 }
127
128 @Override
Jack Hef02d3c62017-02-21 00:39:22 -0500129 public void onStart() {
130 Log.d(TAG, "onStart()");
131 super.onStart();
132 mMediaBrowser.connect();
133 }
134
135 @Override
136 public void onStop() {
137 Log.d(TAG, "onStop()");
138 super.onStop();
139 mMediaBrowser.disconnect();
The Android Open Source Project792a2202009-03-03 19:32:30 -0800140 }
Jack Heb0fba8b2017-01-26 15:54:38 -0800141
The Android Open Source Project792a2202009-03-03 19:32:30 -0800142 @Override
143 public void onDestroy() {
Jack Hef02d3c62017-02-21 00:39:22 -0500144 Log.d(TAG, "onDestroy()");
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800145 ListView lv = getListView();
Marco Nelissen0164ebf2009-08-13 09:58:43 -0700146 // Because we pass the adapter to the next activity, we need to make
147 // sure it doesn't keep a reference to this activity. We can do this
148 // by clearing its DatasetObservers, which setListAdapter(null) does.
149 setListAdapter(null);
Jack Hef02d3c62017-02-21 00:39:22 -0500150 mBrowseListAdapter = null;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800151 super.onDestroy();
The Android Open Source Project6a9c41c2009-03-09 11:52:14 -0700152 }
Jack Heb0fba8b2017-01-26 15:54:38 -0800153
The Android Open Source Project792a2202009-03-03 19:32:30 -0800154 @Override
155 public void onResume() {
Jack Hef02d3c62017-02-21 00:39:22 -0500156 Log.d(TAG, "onResume()");
The Android Open Source Project792a2202009-03-03 19:32:30 -0800157 super.onResume();
The Android Open Source Project792a2202009-03-03 19:32:30 -0800158 }
Jack Hef02d3c62017-02-21 00:39:22 -0500159
The Android Open Source Project792a2202009-03-03 19:32:30 -0800160 @Override
161 public void onPause() {
Jack Hef02d3c62017-02-21 00:39:22 -0500162 Log.d(TAG, "onPause()");
The Android Open Source Project792a2202009-03-03 19:32:30 -0800163 super.onPause();
164 }
Jack Heb0fba8b2017-01-26 15:54:38 -0800165
Jack Hef02d3c62017-02-21 00:39:22 -0500166 @Override
The Android Open Source Project792a2202009-03-03 19:32:30 -0800167 public void onSaveInstanceState(Bundle outcicle) {
Jack Hef02d3c62017-02-21 00:39:22 -0500168 outcicle.putParcelable(MusicUtils.TAG_PARENT_ITEM, mParentItem);
169 outcicle.putBoolean(MusicUtils.TAG_WITH_TABS, mWithTabs);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800170 super.onSaveInstanceState(outcicle);
171 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800172
Jack Hef02d3c62017-02-21 00:39:22 -0500173 private MediaBrowser.SubscriptionCallback mSubscriptionCallback =
174 new MediaBrowser.SubscriptionCallback() {
Jack Heb0fba8b2017-01-26 15:54:38 -0800175
Jack Hef02d3c62017-02-21 00:39:22 -0500176 @Override
177 public void onChildrenLoaded(
178 String parentId, List<MediaBrowser.MediaItem> children) {
179 mBrowseListAdapter.clear();
180 mBrowseListAdapter.notifyDataSetInvalidated();
181 for (MediaBrowser.MediaItem item : children) {
182 mBrowseListAdapter.add(item);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800183 }
Jack Hef02d3c62017-02-21 00:39:22 -0500184 mBrowseListAdapter.notifyDataSetChanged();
The Android Open Source Project792a2202009-03-03 19:32:30 -0800185 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800186
Jack Hef02d3c62017-02-21 00:39:22 -0500187 @Override
188 public void onError(String id) {
189 Toast.makeText(getApplicationContext(), R.string.error_loading_media,
190 Toast.LENGTH_LONG)
191 .show();
Jack Heb0fba8b2017-01-26 15:54:38 -0800192 }
193 };
The Android Open Source Project792a2202009-03-03 19:32:30 -0800194
Jack Hef02d3c62017-02-21 00:39:22 -0500195 private MediaBrowser.ConnectionCallback mConnectionCallback =
196 new MediaBrowser.ConnectionCallback() {
197 @Override
198 public void onConnected() {
199 Log.d(TAG, "onConnected: session token " + mMediaBrowser.getSessionToken());
200 mMediaBrowser.subscribe(mParentItem.getMediaId(), mSubscriptionCallback);
201 if (mMediaBrowser.getSessionToken() == null) {
202 throw new IllegalArgumentException("No Session token");
203 }
204 MediaController mediaController = new MediaController(
205 TrackBrowserActivity.this, mMediaBrowser.getSessionToken());
206 mediaController.registerCallback(mMediaControllerCallback);
207 TrackBrowserActivity.this.setMediaController(mediaController);
208 if (mediaController.getMetadata() != null && mWithTabs) {
209 MusicUtils.updateNowPlaying(TrackBrowserActivity.this);
210 }
211 }
Jack Heb0fba8b2017-01-26 15:54:38 -0800212
Jack Hef02d3c62017-02-21 00:39:22 -0500213 @Override
214 public void onConnectionFailed() {
215 Log.d(TAG, "onConnectionFailed");
216 }
217
218 @Override
219 public void onConnectionSuspended() {
220 Log.d(TAG, "onConnectionSuspended");
221 TrackBrowserActivity.this.setMediaController(null);
222 }
223 };
224
225 private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
The Android Open Source Project792a2202009-03-03 19:32:30 -0800226 @Override
Jack Hef02d3c62017-02-21 00:39:22 -0500227 public void onMetadataChanged(MediaMetadata metadata) {
228 super.onMetadataChanged(metadata);
229 if (mWithTabs) {
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800230 MusicUtils.updateNowPlaying(TrackBrowserActivity.this);
231 }
Jack Hef02d3c62017-02-21 00:39:22 -0500232 if (mBrowseListAdapter != null) {
233 mBrowseListAdapter.notifyDataSetChanged();
The Android Open Source Project792a2202009-03-03 19:32:30 -0800234 }
235 }
236 };
237
Jack Hef02d3c62017-02-21 00:39:22 -0500238 // An adapter for showing the list of browsed MediaItem's
239 private static class TrackBrowseAdapter extends ArrayAdapter<MediaBrowser.MediaItem> {
240 private int mLayoutId;
241 private final Drawable mNowPlayingOverlay;
242 private Activity mActivity;
Jack Heb0fba8b2017-01-26 15:54:38 -0800243
Marco Nelissen756c3f52009-05-14 10:07:23 -0700244 static class ViewHolder {
The Android Open Source Project792a2202009-03-03 19:32:30 -0800245 TextView line1;
246 TextView line2;
247 TextView duration;
248 ImageView play_indicator;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800249 }
250
Jack Hef02d3c62017-02-21 00:39:22 -0500251 TrackBrowseAdapter(Activity activity, int layout) {
252 super(activity, layout, new ArrayList<>());
253 mLayoutId = layout;
254 mNowPlayingOverlay = activity.getResources().getDrawable(
255 R.drawable.indicator_ic_mp_playing_list, activity.getTheme());
256 mActivity = activity;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800257 }
258
259 @Override
Jack Hef02d3c62017-02-21 00:39:22 -0500260 public View getView(int position, View convertView, ViewGroup parent) {
261 Log.d(TAG, "getView()");
262 if (convertView == null) {
263 convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
264 ImageView iv = (ImageView) convertView.findViewById(R.id.icon);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800265 iv.setVisibility(View.GONE);
Jack Hef02d3c62017-02-21 00:39:22 -0500266 ViewHolder vh = new ViewHolder();
267 vh.line1 = (TextView) convertView.findViewById(R.id.line1);
268 vh.line2 = (TextView) convertView.findViewById(R.id.line2);
269 vh.duration = (TextView) convertView.findViewById(R.id.duration);
270 vh.play_indicator = (ImageView) convertView.findViewById(R.id.play_indicator);
271 convertView.setTag(vh);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800272 }
Jack Hef02d3c62017-02-21 00:39:22 -0500273 ViewHolder holder = (ViewHolder) convertView.getTag();
274 MediaBrowser.MediaItem item = getItem(position);
275 Log.d(TAG, "title: " + item.getDescription().getTitle());
276 holder.line1.setText(item.getDescription().getTitle());
277 Log.d(TAG, "artist: " + item.getDescription().getSubtitle());
278 holder.line2.setText(item.getDescription().getSubtitle());
279 long duration =
280 item.getDescription().getExtras().getLong(MediaMetadata.METADATA_KEY_DURATION);
281 LogHelper.d(TAG, "duration: ", duration);
282 holder.duration.setText(MusicUtils.makeTimeString(getContext(), duration / 1000));
283 MediaController mediaController = mActivity.getMediaController();
284 if (mediaController == null) {
285 holder.play_indicator.setImageDrawable(null);
286 return convertView;
Marco Nelissen0e175782009-12-03 14:24:53 -0800287 }
Jack Hef02d3c62017-02-21 00:39:22 -0500288 MediaMetadata metadata = mediaController.getMetadata();
289 if (metadata == null) {
290 holder.play_indicator.setImageDrawable(null);
291 return convertView;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800292 }
Jack Hef02d3c62017-02-21 00:39:22 -0500293 if (item.getDescription().getMediaId().endsWith(
294 metadata.getString(MediaMetadata.METADATA_KEY_MEDIA_ID))) {
295 holder.play_indicator.setImageDrawable(mNowPlayingOverlay);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800296 } else {
Jack Hef02d3c62017-02-21 00:39:22 -0500297 holder.play_indicator.setImageDrawable(null);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800298 }
Jack Hef02d3c62017-02-21 00:39:22 -0500299 return convertView;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800300 }
Jack Hef02d3c62017-02-21 00:39:22 -0500301 }
Jack Heb0fba8b2017-01-26 15:54:38 -0800302
Jack Hef02d3c62017-02-21 00:39:22 -0500303 @Override
304 public Object onRetainNonConfigurationInstance() {
305 TrackBrowseAdapter a = mBrowseListAdapter;
306 return a;
307 }
Jack Heb0fba8b2017-01-26 15:54:38 -0800308
Jack Hef02d3c62017-02-21 00:39:22 -0500309 @Override
310 protected void onListItemClick(ListView l, View v, int position, long id) {
311 Log.d(TAG, "onListItemClick at position " + position + ", id " + id);
312 MediaBrowser.MediaItem item = mBrowseListAdapter.getItem(position);
313 if (item.isPlayable()) {
314 getMediaController().getTransportControls().playFromMediaId(item.getMediaId(), null);
Jack Heb0fba8b2017-01-26 15:54:38 -0800315 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800316 }
317}