• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.music;
18 
19 import android.app.ExpandableListActivity;
20 import android.content.ComponentName;
21 import android.content.Intent;
22 import android.graphics.Bitmap;
23 import android.graphics.drawable.BitmapDrawable;
24 import android.graphics.drawable.Drawable;
25 import android.media.AudioManager;
26 import android.media.MediaDescription;
27 import android.media.MediaMetadata;
28 import android.media.browse.MediaBrowser;
29 import android.media.session.MediaController;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.view.Window;
35 import android.widget.ExpandableListView;
36 import android.widget.ImageView;
37 import android.widget.SimpleExpandableListAdapter;
38 import android.widget.TextView;
39 import android.widget.Toast;
40 
41 import com.android.music.utils.LogHelper;
42 import com.android.music.utils.MediaIDHelper;
43 
44 import java.util.ArrayList;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.concurrent.ConcurrentHashMap;
48 
49 public class ArtistAlbumBrowserActivity extends ExpandableListActivity {
50     private static final String TAG = LogHelper.makeLogTag(ArtistAlbumBrowserActivity.class);
51     private static final String KEY_NUM_ALBUMS = "__NUM_ALBUMS__";
52     private static final MediaBrowser.MediaItem DEFAULT_PARENT_ITEM =
53             new MediaBrowser.MediaItem(new MediaDescription.Builder()
54                                                .setMediaId(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST)
55                                                .build(),
56                     MediaBrowser.MediaItem.FLAG_BROWSABLE);
57 
58     private ArtistAlbumListAdapter mAdapter;
59     private MediaBrowser mMediaBrowser;
60     private MediaBrowser.MediaItem mParentItem;
61 
62     /** Called when the activity is first created. */
63     @Override
onCreate(Bundle icicle)64     public void onCreate(Bundle icicle) {
65         super.onCreate(icicle);
66         LogHelper.d(TAG, "onCreate()");
67         // Handle past states
68         if (icicle != null) {
69             mParentItem = icicle.getParcelable(MusicUtils.TAG_PARENT_ITEM);
70         } else if (getIntent() != null) {
71             mParentItem = getIntent().getExtras().getParcelable(MusicUtils.TAG_PARENT_ITEM);
72         }
73         if (mParentItem == null) {
74             mParentItem = DEFAULT_PARENT_ITEM;
75         }
76         requestWindowFeature(Window.FEATURE_NO_TITLE);
77         setVolumeControlStream(AudioManager.STREAM_MUSIC);
78 
79         // Init layout
80         setContentView(R.layout.media_picker_activity_expanding);
81         MusicUtils.updateButtonBar(this, R.id.artisttab);
82 
83         // Init expandable list
84         ExpandableListView lv = getExpandableListView();
85         lv.setTextFilterEnabled(true);
86         mAdapter = (ArtistAlbumListAdapter) getLastNonConfigurationInstance();
87         if (mAdapter == null) {
88             // Log.i("@@@", "starting query");
89             mAdapter = new ArtistAlbumListAdapter(this, new ArrayList<>(), new ArrayList<>());
90             setListAdapter(mAdapter);
91             setTitle(R.string.working_artists);
92         } else {
93             mAdapter.setActivity(this);
94         }
95         setListAdapter(mAdapter);
96         LogHelper.d(TAG, "Creating MediaBrowser");
97         mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
98                 mConnectionCallback, null);
99     }
100 
101     @Override
onRetainNonConfigurationInstance()102     public Object onRetainNonConfigurationInstance() {
103         return mAdapter;
104     }
105 
106     @Override
onSaveInstanceState(Bundle outcicle)107     public void onSaveInstanceState(Bundle outcicle) {
108         outcicle.putParcelable(MusicUtils.TAG_PARENT_ITEM, mParentItem);
109         super.onSaveInstanceState(outcicle);
110     }
111 
112     @Override
onDestroy()113     public void onDestroy() {
114         setListAdapter(null);
115         mAdapter = null;
116         setListAdapter(null);
117         super.onDestroy();
118     }
119 
120     @Override
onStart()121     public void onStart() {
122         LogHelper.d(TAG, "onStart()");
123         super.onStart();
124         mMediaBrowser.connect();
125     }
126 
127     @Override
onStop()128     public void onStop() {
129         LogHelper.d(TAG, "onStop()");
130         super.onStop();
131         mMediaBrowser.disconnect();
132     }
133 
134     private MediaBrowser
135             .SubscriptionCallback mSubscriptionCallback = new MediaBrowser.SubscriptionCallback() {
136         @Override
137         public void onChildrenLoaded(String parentId, List<MediaBrowser.MediaItem> children) {
138             if (parentId.equals(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST)) {
139                 mAdapter.getArtistMap().clear();
140                 mAdapter.getGroupData().clear();
141                 mAdapter.notifyDataSetInvalidated();
142                 for (MediaBrowser.MediaItem item : children) {
143                     ConcurrentHashMap<String, MediaBrowser.MediaItem> entry =
144                             new ConcurrentHashMap<>();
145                     entry.put(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST, item);
146                     synchronized (this) {
147                         mAdapter.getArtistMap().put(item.getDescription().getTitle().toString(),
148                                 mAdapter.getGroupData().size());
149                         mAdapter.getGroupData().add(entry);
150                         mAdapter.getChildData().add(new ArrayList<>());
151                     }
152                     mMediaBrowser.subscribe(item.getMediaId(), this);
153                 }
154                 mAdapter.notifyDataSetChanged();
155             } else if (parentId.startsWith(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST)) {
156                 String artist = MediaIDHelper.getHierarchy(parentId)[1];
157                 if (!mAdapter.getArtistMap().containsKey(artist)) {
158                     return;
159                 }
160                 int artistIndex = mAdapter.getArtistMap().get(artist);
161                 mAdapter.getChildData().get(artistIndex).clear();
162                 mAdapter.notifyDataSetInvalidated();
163                 Bundle extras = new Bundle();
164                 extras.putLong(KEY_NUM_ALBUMS, children.size());
165                 MediaBrowser.MediaItem newArtistItem =
166                         new MediaBrowser.MediaItem(new MediaDescription.Builder()
167                                                            .setMediaId("Count")
168                                                            .setExtras(extras)
169                                                            .build(),
170                                 0);
171                 mAdapter.getGroupData().get(artistIndex).put(KEY_NUM_ALBUMS, newArtistItem);
172                 for (MediaBrowser.MediaItem item : children) {
173                     ConcurrentHashMap<String, MediaBrowser.MediaItem> entry =
174                             new ConcurrentHashMap<>();
175                     entry.put(MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM, item);
176                     mAdapter.getChildData().get(artistIndex).add(entry);
177                 }
178                 mAdapter.notifyDataSetChanged();
179             }
180         }
181 
182         @Override
183         public void onError(String id) {
184             Toast.makeText(getApplicationContext(), R.string.error_loading_media, Toast.LENGTH_LONG)
185                     .show();
186         }
187     };
188 
189     private MediaBrowser.ConnectionCallback mConnectionCallback =
190             new MediaBrowser.ConnectionCallback() {
191                 @Override
192                 public void onConnected() {
193                     LogHelper.d(
194                             TAG, "onConnected: session token ", mMediaBrowser.getSessionToken());
195                     mMediaBrowser.subscribe(mParentItem.getMediaId(), mSubscriptionCallback);
196                     if (mMediaBrowser.getSessionToken() == null) {
197                         throw new IllegalArgumentException("No Session token");
198                     }
199                     MediaController mediaController = new MediaController(
200                             ArtistAlbumBrowserActivity.this, mMediaBrowser.getSessionToken());
201                     mediaController.registerCallback(mMediaControllerCallback);
202                     ArtistAlbumBrowserActivity.this.setMediaController(mediaController);
203                     if (mediaController.getMetadata() != null) {
204                         MusicUtils.updateNowPlaying(ArtistAlbumBrowserActivity.this);
205                     }
206                 }
207 
208                 @Override
209                 public void onConnectionFailed() {
210                     LogHelper.d(TAG, "onConnectionFailed");
211                 }
212 
213                 @Override
214                 public void onConnectionSuspended() {
215                     LogHelper.d(TAG, "onConnectionSuspended");
216                     ArtistAlbumBrowserActivity.this.setMediaController(null);
217                 }
218             };
219 
220     private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
221         @Override
222         public void onMetadataChanged(MediaMetadata metadata) {
223             super.onMetadataChanged(metadata);
224             MusicUtils.updateNowPlaying(ArtistAlbumBrowserActivity.this);
225         }
226     };
227 
228     private class ArtistAlbumListAdapter extends SimpleExpandableListAdapter {
229         private final Drawable mNowPlayingOverlay;
230         private final BitmapDrawable mDefaultAlbumIcon;
231         private ArtistAlbumBrowserActivity mActivity;
232         private ArrayList<ConcurrentHashMap<String, MediaBrowser.MediaItem>> mGroupData;
233         private ArrayList < ArrayList
234                 < ConcurrentHashMap<String, MediaBrowser.MediaItem>>> mChildData;
235         private ConcurrentHashMap<String, Integer> mArtistMap;
236 
237         private class ViewHolder {
238             TextView line1;
239             TextView line2;
240             ImageView play_indicator;
241             ImageView icon;
242         }
243 
ArtistAlbumListAdapter(ArtistAlbumBrowserActivity currentActivity, ArrayList<ConcurrentHashMap<String, MediaBrowser.MediaItem>> groupData, ArrayList < ArrayList < ConcurrentHashMap<String, MediaBrowser.MediaItem>>> childData)244         ArtistAlbumListAdapter(ArtistAlbumBrowserActivity currentActivity,
245                 ArrayList<ConcurrentHashMap<String, MediaBrowser.MediaItem>> groupData,
246                 ArrayList < ArrayList
247                         < ConcurrentHashMap<String, MediaBrowser.MediaItem>>> childData) {
248             super(currentActivity, groupData, R.layout.track_list_item_group, new String[] {},
249                     new int[] {}, childData, R.layout.track_list_item_child, new String[] {},
250                     new int[] {});
251             mGroupData = groupData;
252             mChildData = childData;
253             mActivity = currentActivity;
254             mNowPlayingOverlay = currentActivity.getResources().getDrawable(
255                     R.drawable.indicator_ic_mp_playing_list, currentActivity.getTheme());
256             mDefaultAlbumIcon = (BitmapDrawable) currentActivity.getResources().getDrawable(
257                     R.drawable.albumart_mp_unknown_list, currentActivity.getTheme());
258             // no filter or dither, it's a lot faster and we can't tell the difference
259             mDefaultAlbumIcon.setFilterBitmap(false);
260             mDefaultAlbumIcon.setDither(false);
261             mArtistMap = new ConcurrentHashMap<>();
262         }
263 
getGroupData()264         public ArrayList<ConcurrentHashMap<String, MediaBrowser.MediaItem>> getGroupData() {
265             return mGroupData;
266         }
267 
268         public ArrayList < ArrayList
getChildData()269                 < ConcurrentHashMap<String, MediaBrowser.MediaItem>>> getChildData() {
270             return mChildData;
271         }
272 
getArtistMap()273         public Map<String, Integer> getArtistMap() {
274             return mArtistMap;
275         }
276 
setActivity(ArtistAlbumBrowserActivity newactivity)277         public void setActivity(ArtistAlbumBrowserActivity newactivity) {
278             mActivity = newactivity;
279         }
280 
281         @Override
newGroupView(boolean isExpanded, ViewGroup parent)282         public View newGroupView(boolean isExpanded, ViewGroup parent) {
283             View v = super.newGroupView(isExpanded, parent);
284             ImageView iv = (ImageView) v.findViewById(R.id.icon);
285             ViewGroup.LayoutParams p = iv.getLayoutParams();
286             p.width = ViewGroup.LayoutParams.WRAP_CONTENT;
287             p.height = ViewGroup.LayoutParams.WRAP_CONTENT;
288             ViewHolder vh = new ViewHolder();
289             vh.line1 = (TextView) v.findViewById(R.id.line1);
290             vh.line2 = (TextView) v.findViewById(R.id.line2);
291             vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
292             vh.icon = (ImageView) v.findViewById(R.id.icon);
293             vh.icon.setPadding(0, 0, 1, 0);
294             v.setTag(vh);
295             return v;
296         }
297 
298         @Override
newChildView(boolean isLastChild, ViewGroup parent)299         public View newChildView(boolean isLastChild, ViewGroup parent) {
300             View v = super.newChildView(isLastChild, parent);
301             ViewHolder vh = new ViewHolder();
302             vh.line1 = (TextView) v.findViewById(R.id.line1);
303             vh.line2 = (TextView) v.findViewById(R.id.line2);
304             vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
305             vh.icon = (ImageView) v.findViewById(R.id.icon);
306             vh.icon.setBackground(mDefaultAlbumIcon);
307             vh.icon.setPadding(0, 0, 1, 0);
308             v.setTag(vh);
309             return v;
310         }
311 
312         @Override
getGroupView( int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)313         public View getGroupView(
314                 int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
315             if (convertView == null) {
316                 convertView = newGroupView(isExpanded, parent);
317             }
318             Map<String, MediaBrowser.MediaItem> artistEntry =
319                     (Map<String, MediaBrowser.MediaItem>) getGroup(groupPosition);
320             MediaBrowser.MediaItem artistItem =
321                     artistEntry.get(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST);
322             MediaBrowser.MediaItem countItem = artistEntry.get(KEY_NUM_ALBUMS);
323             ViewHolder vh = (ViewHolder) convertView.getTag();
324             vh.line1.setText(artistItem.getDescription().getTitle());
325             int numalbums = -1;
326             if (countItem != null) {
327                 Bundle extras = countItem.getDescription().getExtras();
328                 if (extras != null) {
329                     numalbums = (int) extras.getLong(KEY_NUM_ALBUMS);
330                 }
331             }
332             String songs_albums = MusicUtils.makeAlbumsLabel(mActivity, numalbums, -1, false);
333             vh.line2.setText(songs_albums);
334             MediaController mediaController = mActivity.getMediaController();
335             if (mediaController == null) {
336                 vh.play_indicator.setImageDrawable(null);
337                 return convertView;
338             }
339             MediaMetadata metadata = mediaController.getMetadata();
340             if (metadata == null) {
341                 vh.play_indicator.setImageDrawable(null);
342                 return convertView;
343             }
344             if (metadata.getString(MediaMetadata.METADATA_KEY_ARTIST)
345                             .equals(artistItem.getDescription().getTitle())
346                     && !isExpanded) {
347                 vh.play_indicator.setImageDrawable(mNowPlayingOverlay);
348             } else {
349                 vh.play_indicator.setImageDrawable(null);
350             }
351             return convertView;
352         }
353 
354         @Override
getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent)355         public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
356                 View convertView, ViewGroup parent) {
357             if (convertView == null) {
358                 convertView = newChildView(isLastChild, parent);
359             }
360             Map<String, MediaBrowser.MediaItem> albumEntry =
361                     (Map<String, MediaBrowser.MediaItem>) getChild(groupPosition, childPosition);
362             MediaBrowser.MediaItem albumItem =
363                     albumEntry.get(MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM);
364             ViewHolder vh = (ViewHolder) convertView.getTag();
365             vh.line1.setText(albumItem.getDescription().getTitle());
366             vh.line2.setText(albumItem.getDescription().getDescription());
367             Bitmap albumArt = albumItem.getDescription().getIconBitmap();
368             if (albumArt == null) {
369                 vh.icon.setBackground(mDefaultAlbumIcon);
370             } else {
371                 vh.icon.setImageDrawable(MusicUtils.getDrawableBitmap(albumArt, mDefaultAlbumIcon));
372             }
373             MediaController mediaController = mActivity.getMediaController();
374             if (mediaController == null) {
375                 vh.play_indicator.setImageDrawable(null);
376                 return convertView;
377             }
378             MediaMetadata metadata = mediaController.getMetadata();
379             if (metadata == null) {
380                 vh.play_indicator.setImageDrawable(null);
381                 return convertView;
382             }
383             if (albumItem.getDescription().getTitle().equals(
384                         metadata.getString(MediaMetadata.METADATA_KEY_ALBUM))) {
385                 vh.play_indicator.setImageDrawable(mNowPlayingOverlay);
386             } else {
387                 vh.play_indicator.setImageDrawable(null);
388             }
389             return convertView;
390         }
391     }
392 
393     @Override
onChildClick( ExpandableListView parent, View v, int groupPosition, int childPosition, long id)394     public boolean onChildClick(
395             ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
396         Map<String, MediaBrowser.MediaItem> albumEntry =
397                 (Map<String, MediaBrowser.MediaItem>) mAdapter.getChild(
398                         groupPosition, childPosition);
399         Intent intent = new Intent(Intent.ACTION_PICK);
400         intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
401         intent.putExtra(
402                 MusicUtils.TAG_PARENT_ITEM, albumEntry.get(MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM));
403         startActivity(intent);
404         return true;
405     }
406 }
407