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