OSDN Git Service

When doing a youtube/amazon/browser search from the music app, make it a new task.
[android-x86/packages-apps-Music.git] / src / com / android / music / AlbumBrowserActivity.java
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.ListActivity;
20 import android.app.SearchManager;
21 import android.content.AsyncQueryHandler;
22 import android.content.BroadcastReceiver;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.res.Resources;
28 import android.database.Cursor;
29 import android.graphics.Bitmap;
30 import android.graphics.BitmapFactory;
31 import android.graphics.drawable.BitmapDrawable;
32 import android.graphics.drawable.Drawable;
33 import android.media.AudioManager;
34 import android.media.MediaFile;
35 import android.net.Uri;
36 import android.os.Bundle;
37 import android.os.Handler;
38 import android.os.Message;
39 import android.provider.MediaStore;
40 import android.view.ContextMenu;
41 import android.view.Menu;
42 import android.view.MenuItem;
43 import android.view.SubMenu;
44 import android.view.View;
45 import android.view.ViewGroup;
46 import android.view.Window;
47 import android.view.ContextMenu.ContextMenuInfo;
48 import android.widget.Adapter;
49 import android.widget.AlphabetIndexer;
50 import android.widget.CursorAdapter;
51 import android.widget.ImageView;
52 import android.widget.ListAdapter;
53 import android.widget.ListView;
54 import android.widget.SectionIndexer;
55 import android.widget.SimpleCursorAdapter;
56 import android.widget.TextView;
57 import android.widget.AdapterView.AdapterContextMenuInfo;
58
59 import java.text.Collator;
60
61 public class AlbumBrowserActivity extends ListActivity
62     implements View.OnCreateContextMenuListener, MusicUtils.Defs
63 {
64     private String mCurrentAlbumId;
65     private String mCurrentAlbumName;
66     private String mCurrentArtistNameForAlbum;
67     private AlbumListAdapter mAdapter;
68     private boolean mAdapterSent;
69     private final static int SEARCH = CHILD_MENU_BASE;
70
71     public AlbumBrowserActivity()
72     {
73     }
74
75     /** Called when the activity is first created. */
76     @Override
77     public void onCreate(Bundle icicle)
78     {
79         if (icicle != null) {
80             mCurrentAlbumId = icicle.getString("selectedalbum");
81             mArtistId = icicle.getString("artist");
82         } else {
83             mArtistId = getIntent().getStringExtra("artist");
84         }
85         super.onCreate(icicle);
86         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
87         setVolumeControlStream(AudioManager.STREAM_MUSIC);
88         MusicUtils.bindToService(this);
89
90         IntentFilter f = new IntentFilter();
91         f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
92         f.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
93         f.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
94         f.addDataScheme("file");
95         registerReceiver(mScanListener, f);
96
97         setContentView(R.layout.media_picker_activity);
98         ListView lv = getListView();
99         lv.setFastScrollEnabled(true);
100         lv.setOnCreateContextMenuListener(this);
101         lv.setTextFilterEnabled(true);
102
103         mAdapter = (AlbumListAdapter) getLastNonConfigurationInstance();
104         if (mAdapter == null) {
105             //Log.i("@@@", "starting query");
106             mAdapter = new AlbumListAdapter(
107                     getApplication(),
108                     this,
109                     R.layout.track_list_item,
110                     mAlbumCursor,
111                     new String[] {},
112                     new int[] {});
113             setListAdapter(mAdapter);
114             setTitle(R.string.working_albums);
115             getAlbumCursor(mAdapter.getQueryHandler(), null);
116         } else {
117             mAdapter.setActivity(this);
118             setListAdapter(mAdapter);
119             mAlbumCursor = mAdapter.getCursor();
120             if (mAlbumCursor != null) {
121                 init(mAlbumCursor);
122             } else {
123                 getAlbumCursor(mAdapter.getQueryHandler(), null);
124             }
125         }
126     }
127
128     @Override
129     public Object onRetainNonConfigurationInstance() {
130         mAdapterSent = true;
131         return mAdapter;
132     }
133     
134     @Override
135     public void onSaveInstanceState(Bundle outcicle) {
136         // need to store the selected item so we don't lose it in case
137         // of an orientation switch. Otherwise we could lose it while
138         // in the middle of specifying a playlist to add the item to.
139         outcicle.putString("selectedalbum", mCurrentAlbumId);
140         outcicle.putString("artist", mArtistId);
141         super.onSaveInstanceState(outcicle);
142     }
143
144     @Override
145     public void onDestroy() {
146         MusicUtils.unbindFromService(this);
147         if (!mAdapterSent) {
148             Cursor c = mAdapter.getCursor();
149             if (c != null) {
150                 c.close();
151             }
152         }
153         unregisterReceiver(mScanListener);
154         super.onDestroy();
155     }
156     
157     @Override
158     public void onResume() {
159         super.onResume();
160         IntentFilter f = new IntentFilter();
161         f.addAction(MediaPlaybackService.META_CHANGED);
162         f.addAction(MediaPlaybackService.QUEUE_CHANGED);
163         registerReceiver(mTrackListListener, f);
164         mTrackListListener.onReceive(null, null);
165
166         MusicUtils.setSpinnerState(this);
167     }
168
169     private BroadcastReceiver mTrackListListener = new BroadcastReceiver() {
170         @Override
171         public void onReceive(Context context, Intent intent) {
172             getListView().invalidateViews();
173         }
174     };
175     private BroadcastReceiver mScanListener = new BroadcastReceiver() {
176         @Override
177         public void onReceive(Context context, Intent intent) {
178             MusicUtils.setSpinnerState(AlbumBrowserActivity.this);
179             mReScanHandler.sendEmptyMessage(0);
180             if (intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
181                 MusicUtils.clearAlbumArtCache();
182             }
183         }
184     };
185     
186     private Handler mReScanHandler = new Handler() {
187         @Override
188         public void handleMessage(Message msg) {
189             getAlbumCursor(mAdapter.getQueryHandler(), null);
190         }
191     };
192
193     @Override
194     public void onPause() {
195         unregisterReceiver(mTrackListListener);
196         mReScanHandler.removeCallbacksAndMessages(null);
197         super.onPause();
198     }
199
200     public void init(Cursor c) {
201
202         mAdapter.changeCursor(c); // also sets mAlbumCursor
203
204         if (mAlbumCursor == null) {
205             MusicUtils.displayDatabaseError(this);
206             closeContextMenu();
207             mReScanHandler.sendEmptyMessageDelayed(0, 1000);
208             return;
209         }
210         
211         MusicUtils.hideDatabaseError(this);
212         setTitle();
213     }
214
215     private void setTitle() {
216         CharSequence fancyName = "";
217         if (mAlbumCursor != null && mAlbumCursor.getCount() > 0) {
218             mAlbumCursor.moveToFirst();
219             fancyName = mAlbumCursor.getString(3);
220             if (fancyName == null || fancyName.equals(MediaFile.UNKNOWN_STRING))
221                 fancyName = getText(R.string.unknown_artist_name);
222         }
223
224         if (mArtistId != null && fancyName != null)
225             setTitle(fancyName);
226         else
227             setTitle(R.string.albums_title);
228     }
229     
230     @Override
231     public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfoIn) {
232         menu.add(0, PLAY_SELECTION, 0, R.string.play_selection);
233         SubMenu sub = menu.addSubMenu(0, ADD_TO_PLAYLIST, 0, R.string.add_to_playlist);
234         MusicUtils.makePlaylistMenu(this, sub);
235         menu.add(0, DELETE_ITEM, 0, R.string.delete_item);
236         menu.add(0, SEARCH, 0, R.string.search_title);
237
238         AdapterContextMenuInfo mi = (AdapterContextMenuInfo) menuInfoIn;
239         mAlbumCursor.moveToPosition(mi.position);
240         mCurrentAlbumId = mAlbumCursor.getString(mAlbumCursor.getColumnIndexOrThrow(MediaStore.Audio.Albums._ID));
241         mCurrentAlbumName = mAlbumCursor.getString(mAlbumCursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM));
242         mCurrentArtistNameForAlbum = mAlbumCursor.getString(
243                 mAlbumCursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ARTIST));
244         menu.setHeaderTitle(mCurrentAlbumName);
245     }
246
247     @Override
248     public boolean onContextItemSelected(MenuItem item) {
249         switch (item.getItemId()) {
250             case PLAY_SELECTION: {
251                 // play the selected album
252                 int [] list = MusicUtils.getSongListForAlbum(this, Integer.parseInt(mCurrentAlbumId));
253                 MusicUtils.playAll(this, list, 0);
254                 return true;
255             }
256
257             case QUEUE: {
258                 int [] list = MusicUtils.getSongListForAlbum(this, Integer.parseInt(mCurrentAlbumId));
259                 MusicUtils.addToCurrentPlaylist(this, list);
260                 return true;
261             }
262
263             case NEW_PLAYLIST: {
264                 Intent intent = new Intent();
265                 intent.setClass(this, CreatePlaylist.class);
266                 startActivityForResult(intent, NEW_PLAYLIST);
267                 return true;
268             }
269
270             case PLAYLIST_SELECTED: {
271                 int [] list = MusicUtils.getSongListForAlbum(this, Integer.parseInt(mCurrentAlbumId));
272                 int playlist = item.getIntent().getIntExtra("playlist", 0);
273                 MusicUtils.addToPlaylist(this, list, playlist);
274                 return true;
275             }
276             case DELETE_ITEM: {
277                 int [] list = MusicUtils.getSongListForAlbum(this, Integer.parseInt(mCurrentAlbumId));
278                 String f = getString(R.string.delete_album_desc); 
279                 String desc = String.format(f, mCurrentAlbumName);
280                 Bundle b = new Bundle();
281                 b.putString("description", desc);
282                 b.putIntArray("items", list);
283                 Intent intent = new Intent();
284                 intent.setClass(this, DeleteItems.class);
285                 intent.putExtras(b);
286                 startActivityForResult(intent, -1);
287                 return true;
288             }
289             case SEARCH:
290                 doSearch();
291                 return true;
292
293         }
294         return super.onContextItemSelected(item);
295     }
296
297     void doSearch() {
298         CharSequence title = null;
299         String query = null;
300         
301         Intent i = new Intent();
302         i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);
303         i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
304         
305         title = mCurrentAlbumName;
306         query = mCurrentArtistNameForAlbum + " " + mCurrentAlbumName;
307         i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, mCurrentArtistNameForAlbum);
308         i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, mCurrentAlbumName);
309         i.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE);
310         title = getString(R.string.mediasearch, title);
311         i.putExtra(SearchManager.QUERY, query);
312
313         startActivity(Intent.createChooser(i, title));
314     }
315
316     @Override
317     protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
318         switch (requestCode) {
319             case SCAN_DONE:
320                 if (resultCode == RESULT_CANCELED) {
321                     finish();
322                 } else {
323                     getAlbumCursor(mAdapter.getQueryHandler(), null);
324                 }
325                 break;
326
327             case NEW_PLAYLIST:
328                 if (resultCode == RESULT_OK) {
329                     Uri uri = intent.getData();
330                     if (uri != null) {
331                         int [] list = MusicUtils.getSongListForAlbum(this, Integer.parseInt(mCurrentAlbumId));
332                         MusicUtils.addToPlaylist(this, list, Integer.parseInt(uri.getLastPathSegment()));
333                     }
334                 }
335                 break;
336         }
337     }
338
339     @Override
340     protected void onListItemClick(ListView l, View v, int position, long id)
341     {
342         Intent intent = new Intent(Intent.ACTION_PICK);
343         intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
344         intent.putExtra("album", Long.valueOf(id).toString());
345         intent.putExtra("artist", mArtistId);
346         startActivity(intent);
347     }
348
349     @Override
350     public boolean onCreateOptionsMenu(Menu menu) {
351         super.onCreateOptionsMenu(menu);
352         menu.add(0, GOTO_START, 0, R.string.goto_start).setIcon(R.drawable.ic_menu_music_library);
353         menu.add(0, GOTO_PLAYBACK, 0, R.string.goto_playback).setIcon(R.drawable.ic_menu_playback);
354         menu.add(0, SHUFFLE_ALL, 0, R.string.shuffle_all).setIcon(R.drawable.ic_menu_shuffle);
355         return true;
356     }
357
358     @Override
359     public boolean onPrepareOptionsMenu(Menu menu) {
360         menu.findItem(GOTO_PLAYBACK).setVisible(MusicUtils.isMusicLoaded());
361         return super.onPrepareOptionsMenu(menu);
362     }
363
364     @Override
365     public boolean onOptionsItemSelected(MenuItem item) {
366         Intent intent;
367         Cursor cursor;
368         switch (item.getItemId()) {
369             case GOTO_START:
370                 intent = new Intent();
371                 intent.setClass(this, MusicBrowserActivity.class);
372                 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
373                 startActivity(intent);
374                 return true;
375
376             case GOTO_PLAYBACK:
377                 intent = new Intent("com.android.music.PLAYBACK_VIEWER");
378                 startActivity(intent);
379                 return true;
380
381             case SHUFFLE_ALL:
382                 cursor = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
383                         new String [] { MediaStore.Audio.Media._ID},
384                         MediaStore.Audio.Media.IS_MUSIC + "=1", null,
385                         MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
386                 if (cursor != null) {
387                     MusicUtils.shuffleAll(this, cursor);
388                     cursor.close();
389                 }
390                 return true;
391         }
392         return super.onOptionsItemSelected(item);
393     }
394
395     private Cursor getAlbumCursor(AsyncQueryHandler async, String filter) {
396         StringBuilder where = new StringBuilder();
397         where.append(MediaStore.Audio.Albums.ALBUM + " != ''");
398         
399         // Add in the filtering constraints
400         String [] keywords = null;
401         if (filter != null) {
402             String [] searchWords = filter.split(" ");
403             keywords = new String[searchWords.length];
404             Collator col = Collator.getInstance();
405             col.setStrength(Collator.PRIMARY);
406             for (int i = 0; i < searchWords.length; i++) {
407                 keywords[i] = '%' + MediaStore.Audio.keyFor(searchWords[i]) + '%';
408             }
409             for (int i = 0; i < searchWords.length; i++) {
410                 where.append(" AND ");
411                 where.append(MediaStore.Audio.Media.ARTIST_KEY + "||");
412                 where.append(MediaStore.Audio.Media.ALBUM_KEY + " LIKE ?");
413             }
414         }
415
416         String whereclause = where.toString();  
417             
418         String[] cols = new String[] {
419                 MediaStore.Audio.Albums._ID,
420                 MediaStore.Audio.Albums.ALBUM,
421                 MediaStore.Audio.Albums.ALBUM_KEY,
422                 MediaStore.Audio.Albums.ARTIST,
423                 MediaStore.Audio.Albums.NUMBER_OF_SONGS,
424                 MediaStore.Audio.Albums.ALBUM_ART
425         };
426         Cursor ret = null;
427         if (mArtistId != null) {
428             if (async != null) {
429                 async.startQuery(0, null,
430                         MediaStore.Audio.Artists.Albums.getContentUri("external",
431                                 Long.valueOf(mArtistId)),
432                         cols, whereclause, keywords, MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
433             } else {
434                 ret = MusicUtils.query(this,
435                         MediaStore.Audio.Artists.Albums.getContentUri("external",
436                                 Long.valueOf(mArtistId)),
437                         cols, whereclause, keywords, MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
438             }
439         } else {
440             if (async != null) {
441                 async.startQuery(0, null,
442                         MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
443                         cols, whereclause, keywords, MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
444             } else {
445                 ret = MusicUtils.query(this, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
446                         cols, whereclause, keywords, MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
447             }
448         }
449         return ret;
450     }
451     
452     static class AlbumListAdapter extends SimpleCursorAdapter implements SectionIndexer {
453         
454         private final Drawable mNowPlayingOverlay;
455         private final BitmapDrawable mDefaultAlbumIcon;
456         private int mAlbumIdx;
457         private int mArtistIdx;
458         private int mNumSongsIdx;
459         private int mAlbumArtIndex;
460         private final Resources mResources;
461         private final StringBuilder mStringBuilder = new StringBuilder();
462         private final String mUnknownAlbum;
463         private final String mUnknownArtist;
464         private final String mAlbumSongSeparator;
465         private final Object[] mFormatArgs = new Object[1];
466         private AlphabetIndexer mIndexer;
467         private AlbumBrowserActivity mActivity;
468         private AsyncQueryHandler mQueryHandler;
469         private String mConstraint = null;
470         private boolean mConstraintIsValid = false;
471         
472         class ViewHolder {
473             TextView line1;
474             TextView line2;
475             TextView duration;
476             ImageView play_indicator;
477             ImageView icon;
478         }
479
480         class QueryHandler extends AsyncQueryHandler {
481             QueryHandler(ContentResolver res) {
482                 super(res);
483             }
484             
485             @Override
486             protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
487                 //Log.i("@@@", "query complete");
488                 mActivity.init(cursor);
489             }
490         }
491
492         AlbumListAdapter(Context context, AlbumBrowserActivity currentactivity,
493                 int layout, Cursor cursor, String[] from, int[] to) {
494             super(context, layout, cursor, from, to);
495
496             mActivity = currentactivity;
497             mQueryHandler = new QueryHandler(context.getContentResolver());
498             
499             mUnknownAlbum = context.getString(R.string.unknown_album_name);
500             mUnknownArtist = context.getString(R.string.unknown_artist_name);
501             mAlbumSongSeparator = context.getString(R.string.albumsongseparator);
502
503             Resources r = context.getResources();
504             mNowPlayingOverlay = r.getDrawable(R.drawable.indicator_ic_mp_playing_list);
505
506             Bitmap b = BitmapFactory.decodeResource(r, R.drawable.albumart_mp_unknown_list);
507             mDefaultAlbumIcon = new BitmapDrawable(b);
508             // no filter or dither, it's a lot faster and we can't tell the difference
509             mDefaultAlbumIcon.setFilterBitmap(false);
510             mDefaultAlbumIcon.setDither(false);
511             getColumnIndices(cursor);
512             mResources = context.getResources();
513         }
514
515         private void getColumnIndices(Cursor cursor) {
516             if (cursor != null) {
517                 mAlbumIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM);
518                 mArtistIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ARTIST);
519                 mNumSongsIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.NUMBER_OF_SONGS);
520                 mAlbumArtIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM_ART);
521                 
522                 if (mIndexer != null) {
523                     mIndexer.setCursor(cursor);
524                 } else {
525                     mIndexer = new MusicAlphabetIndexer(cursor, mAlbumIdx, mResources.getString(
526                             com.android.internal.R.string.fast_scroll_alphabet));
527                 }
528             }
529         }
530         
531         public void setActivity(AlbumBrowserActivity newactivity) {
532             mActivity = newactivity;
533         }
534         
535         public AsyncQueryHandler getQueryHandler() {
536             return mQueryHandler;
537         }
538
539         @Override
540         public View newView(Context context, Cursor cursor, ViewGroup parent) {
541            View v = super.newView(context, cursor, parent);
542            ViewHolder vh = new ViewHolder();
543            vh.line1 = (TextView) v.findViewById(R.id.line1);
544            vh.line2 = (TextView) v.findViewById(R.id.line2);
545            vh.duration = (TextView) v.findViewById(R.id.duration);
546            vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
547            vh.icon = (ImageView) v.findViewById(R.id.icon);
548            vh.icon.setBackgroundDrawable(mDefaultAlbumIcon);
549            vh.icon.setPadding(0, 0, 1, 0);
550            v.setTag(vh);
551            return v;
552         }
553
554         @Override
555         public void bindView(View view, Context context, Cursor cursor) {
556             
557             ViewHolder vh = (ViewHolder) view.getTag();
558
559             String name = cursor.getString(mAlbumIdx);
560             String displayname = name;
561             boolean unknown = name == null || name.equals(MediaFile.UNKNOWN_STRING); 
562             if (unknown) {
563                 displayname = mUnknownAlbum;
564             }
565             vh.line1.setText(displayname);
566             
567             name = cursor.getString(mArtistIdx);
568             displayname = name;
569             if (name == null || name.equals(MediaFile.UNKNOWN_STRING)) {
570                 displayname = mUnknownArtist;
571             }
572             vh.line2.setText(displayname);
573
574             ImageView iv = vh.icon;
575             // We don't actually need the path to the thumbnail file,
576             // we just use it to see if there is album art or not
577             String art = cursor.getString(mAlbumArtIndex);
578             if (unknown || art == null || art.length() == 0) {
579                 iv.setImageDrawable(null);
580             } else {
581                 int artIndex = cursor.getInt(0);
582                 Drawable d = MusicUtils.getCachedArtwork(context, artIndex, mDefaultAlbumIcon);
583                 iv.setImageDrawable(d);
584             }
585             
586             int currentalbumid = MusicUtils.getCurrentAlbumId();
587             int aid = cursor.getInt(0);
588             iv = vh.play_indicator;
589             if (currentalbumid == aid) {
590                 iv.setImageDrawable(mNowPlayingOverlay);
591             } else {
592                 iv.setImageDrawable(null);
593             }
594         }
595         
596         @Override
597         public void changeCursor(Cursor cursor) {
598             if (cursor != mActivity.mAlbumCursor) {
599                 mActivity.mAlbumCursor = cursor;
600                 getColumnIndices(cursor);
601                 super.changeCursor(cursor);
602             }
603         }
604         
605         @Override
606         public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
607             String s = constraint.toString();
608             if (mConstraintIsValid && (
609                     (s == null && mConstraint == null) ||
610                     (s != null && s.equals(mConstraint)))) {
611                 return getCursor();
612             }
613             Cursor c = mActivity.getAlbumCursor(null, s);
614             mConstraint = s;
615             mConstraintIsValid = true;
616             return c;
617         }
618         
619         public Object[] getSections() {
620             return mIndexer.getSections();
621         }
622         
623         public int getPositionForSection(int section) {
624             return mIndexer.getPositionForSection(section);
625         }
626         
627         public int getSectionForPosition(int position) {
628             return 0;
629         }
630     }
631
632     private Cursor mAlbumCursor;
633     private String mArtistId;
634 }
635