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