📄 musicutils.java
字号:
MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM_ID }; StringBuilder where = new StringBuilder(); where.append(MediaStore.Audio.Media._ID + " IN ("); for (int i = 0; i < list.length; i++) { where.append(list[i]); if (i < list.length - 1) { where.append(","); } } where.append(")"); Cursor c = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, cols, where.toString(), null, null); if (c != null) { // step 1: remove selected tracks from the current playlist, as well // as from the album art cache try { c.moveToFirst(); while (! c.isAfterLast()) { // remove from current playlist int id = c.getInt(0); sService.removeTrack(id); // remove from album art cache int artIndex = c.getInt(2); synchronized(sArtCache) { sArtCache.remove(artIndex); } c.moveToNext(); } } catch (RemoteException ex) { } // step 2: remove selected tracks from the database context.getContentResolver().delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, where.toString(), null); // step 3: remove files from card c.moveToFirst(); while (! c.isAfterLast()) { String name = c.getString(1); File f = new File(name); try { // File.delete can throw a security exception if (!f.delete()) { // I'm not sure if we'd ever get here (deletion would // have to fail, but no exception thrown) Log.e("MusicUtils", "Failed to delete file " + name); } c.moveToNext(); } catch (SecurityException ex) { c.moveToNext(); } }// c.commitUpdates(); c.close(); } String message = context.getResources().getQuantityString( R.plurals.NNNtracksdeleted, list.length, Integer.valueOf(list.length)); Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); // We deleted a number of tracks, which could affect any number of things // in the media content domain, so update everything. context.getContentResolver().notifyChange(Uri.parse("content://media"), null); } public static void addToCurrentPlaylist(Context context, int [] list) { if (sService == null) { return; } try { sService.enqueue(list, MediaPlaybackService.LAST); String message = context.getResources().getQuantityString( R.plurals.NNNtrackstoplaylist, list.length, Integer.valueOf(list.length)); Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); } catch (RemoteException ex) { } } public static void addToPlaylist(Context context, int [] ids, long playlistid) { if (ids == null) { // this shouldn't happen (the menuitems shouldn't be visible // unless the selected item represents something playable Log.e("MusicBase", "ListSelection null"); } else { int size = ids.length; ContentValues values [] = new ContentValues[size]; ContentResolver resolver = context.getContentResolver(); // need to determine the number of items currently in the playlist, // so the play_order field can be maintained. String[] cols = new String[] { "count(*)" }; Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistid); Cursor cur = resolver.query(uri, cols, null, null, null); cur.moveToFirst(); int base = cur.getInt(0); cur.close(); for (int i = 0; i < size; i++) { values[i] = new ContentValues(); values[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + i)); values[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, ids[i]); } resolver.bulkInsert(uri, values); String message = context.getResources().getQuantityString( R.plurals.NNNtrackstoplaylist, size, Integer.valueOf(size)); Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); //mLastPlaylistSelected = playlistid; } } public static Cursor query(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { try { ContentResolver resolver = context.getContentResolver(); if (resolver == null) { return null; } return resolver.query(uri, projection, selection, selectionArgs, sortOrder); } catch (UnsupportedOperationException ex) { return null; } } public static boolean isMediaScannerScanning(Context context) { boolean result = false; Uri uri = MediaStore.getMediaScannerUri(); Cursor cursor = query(context, MediaStore.getMediaScannerUri(), new String [] { MediaStore.MEDIA_SCANNER_VOLUME }, null, null, null); if (cursor != null) { if (cursor.getCount() == 1) { cursor.moveToFirst(); result = "external".equals(cursor.getString(0)); } cursor.close(); } return result; } public static void setSpinnerState(Activity a) { if (isMediaScannerScanning(a)) { // start the progress spinner a.getWindow().setFeatureInt( Window.FEATURE_INDETERMINATE_PROGRESS, Window.PROGRESS_INDETERMINATE_ON); a.getWindow().setFeatureInt( Window.FEATURE_INDETERMINATE_PROGRESS, Window.PROGRESS_VISIBILITY_ON); } else { // stop the progress spinner a.getWindow().setFeatureInt( Window.FEATURE_INDETERMINATE_PROGRESS, Window.PROGRESS_VISIBILITY_OFF); } } public static void displayDatabaseError(Activity a) { String status = Environment.getExternalStorageState(); int title = R.string.sdcard_error_title; int message = R.string.sdcard_error_message; if (status.equals(Environment.MEDIA_SHARED)) { title = R.string.sdcard_busy_title; message = R.string.sdcard_busy_message; } else if (status.equals(Environment.MEDIA_REMOVED)) { title = R.string.sdcard_missing_title; message = R.string.sdcard_missing_message; } else if (status.equals(Environment.MEDIA_MOUNTED)){ // The card is mounted, but we didn't get a valid cursor. // This probably means the mediascanner hasn't started scanning the // card yet (there is a small window of time during boot where this // will happen). a.setTitle(""); Intent intent = new Intent(); intent.setClass(a, ScanningProgress.class); a.startActivityForResult(intent, Defs.SCAN_DONE); } else { Log.d(TAG, "sd card: " + status); } a.setTitle(title); if (a instanceof ExpandableListActivity) { a.setContentView(R.layout.no_sd_card_expanding); } else { a.setContentView(R.layout.no_sd_card); } TextView tv = (TextView) a.findViewById(R.id.sd_message); tv.setText(message); } static protected Uri getContentURIForPath(String path) { return Uri.fromFile(new File(path)); } /* Try to use String.format() as little as possible, because it creates a * new Formatter every time you call it, which is very inefficient. * Reusing an existing Formatter more than tripled the speed of * makeTimeString(). * This Formatter/StringBuilder are also used by makeAlbumSongsLabel() */ private static StringBuilder sFormatBuilder = new StringBuilder(); private static Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault()); private static final Object[] sTimeArgs = new Object[5]; public static String makeTimeString(Context context, long secs) { String durationformat = context.getString(R.string.durationformat); /* Provide multiple arguments so the format can be changed easily * by modifying the xml. */ sFormatBuilder.setLength(0); final Object[] timeArgs = sTimeArgs; timeArgs[0] = secs / 3600; timeArgs[1] = secs / 60; timeArgs[2] = (secs / 60) % 60; timeArgs[3] = secs; timeArgs[4] = secs % 60; return sFormatter.format(durationformat, timeArgs).toString(); } public static void shuffleAll(Context context, Cursor cursor) { playAll(context, cursor, 0, true); } public static void playAll(Context context, Cursor cursor) { playAll(context, cursor, 0, false); } public static void playAll(Context context, Cursor cursor, int position) { playAll(context, cursor, position, false); } public static void playAll(Context context, int [] list, int position) { playAll(context, list, position, false); } private static void playAll(Context context, Cursor cursor, int position, boolean force_shuffle) { int [] list = getSongListForCursor(cursor); playAll(context, list, position, force_shuffle); } private static void playAll(Context context, int [] list, int position, boolean force_shuffle) { if (list.length == 0 || sService == null) { Log.d("MusicUtils", "attempt to play empty song list"); // Don't try to play empty playlists. Nothing good will come of it. String message = context.getString(R.string.emptyplaylist, list.length); Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); return; } try { if (force_shuffle) { sService.setShuffleMode(MediaPlaybackService.SHUFFLE_NORMAL); } int curid = sService.getAudioId(); int curpos = sService.getQueuePosition(); if (position != -1 && curpos == position && curid == list[position]) { // The selected file is the file that's currently playing; // figure out if we need to restart with a new playlist, // or just launch the playback activity. int [] playlist = sService.getQueue(); if (Arrays.equals(list, playlist)) { // we don't need to set a new list, but we should resume playback if needed sService.play(); return; // the 'finally' block will still run } } if (position < 0) { position = 0; } sService.open(list, position); sService.play(); } catch (RemoteException ex) { } finally { Intent intent = new Intent("com.android.imusic.playing") .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(intent); } } public static void clearQueue() { try { sService.removeTracks(0, Integer.MAX_VALUE); } catch (RemoteException ex) { } } // A really simple BitmapDrawable-like class, that doesn't do // scaling, dithering or filtering. private static class FastBitmapDrawable extends Drawable { private Bitmap mBitmap; public FastBitmapDrawable(Bitmap b) { mBitmap = b; } @Override public void draw(Canvas canvas) { canvas.drawBitmap(mBitmap, 0, 0, null); } @Override public int getOpacity() { return PixelFormat.OPAQUE; } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter cf) { } } private static int sArtId = -2; private static byte [] mCachedArt; private static Bitmap mCachedBit = null; private static final BitmapFactory.Options sBitmapOptionsCache = new BitmapFactory.Options(); private static final BitmapFactory.Options sBitmapOptions = new BitmapFactory.Options(); private static final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart"); private static final HashMap<Integer, Drawable> sArtCache = new HashMap<Integer, Drawable>(); private static int sArtCacheId = -1; static { // for the cache, // 565 is faster to decode and display // and we don't want to dither here because the image will be scaled down later sBitmapOptionsCache.inPreferredConfig = Bitmap.Config.RGB_565; sBitmapOptionsCache.inDither = false; sBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565; sBitmapOptions.inDither = false; } public static void initAlbumArtCache() { try { int id = sService.getMediaMountedCount(); if (id != sArtCacheId) { clearAlbumArtCache(); sArtCacheId = id; } } catch (RemoteException e) { e.printStackTrace(); } } public static void clearAlbumArtCache() { synchronized(sArtCache) { sArtCache.clear(); } } public static Drawable getCachedArtwork(Context context, int artIndex, BitmapDrawable defaultArtwork) { Drawable d = null; synchronized(sArtCache) { d = sArtCache.get(artIndex); } if (d == null) { d = defaultArtwork; final Bitmap icon = defaultArtwork.getBitmap(); int w = icon.getWidth(); int h = icon.getHeight(); Bitmap b = MusicUtils.getArtworkQuick(context, artIndex, w, h); if (b != null) { d = new FastBitmapDrawable(b); synchronized(sArtCache) { // the cache may have changed since we checked Drawable value = sArtCache.get(artIndex); if (value == null) { sArtCache.put(artIndex, d); } else { d = value; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -