/* * Copyright (C) 2015 Naman Dwivedi * * Licensed under the GNU General Public License v3 * * This is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ package com.naman14.timber.dataloaders; import android.content.ContentProviderOperation; import android.content.Context; import android.content.OperationApplicationException; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; import android.provider.MediaStore; import android.provider.MediaStore.Audio.AudioColumns; import android.provider.MediaStore.Audio.Playlists; import com.naman14.timber.models.Song; import java.util.ArrayList; import java.util.List; public class PlaylistSongLoader { private static Cursor mCursor; private static long mPlaylistID; private static Context context; public static List<Song> getSongsInPlaylist(Context mContext, long playlistID) { ArrayList<Song> mSongList = new ArrayList<>(); context = mContext; mPlaylistID = playlistID; final int playlistCount = countPlaylist(context, mPlaylistID); mCursor = makePlaylistSongCursor(context, mPlaylistID); if (mCursor != null) { boolean runCleanup = false; if (mCursor.getCount() != playlistCount) { runCleanup = true; } if (!runCleanup && mCursor.moveToFirst()) { final int playOrderCol = mCursor.getColumnIndexOrThrow(Playlists.Members.PLAY_ORDER); int lastPlayOrder = -1; do { int playOrder = mCursor.getInt(playOrderCol); if (playOrder == lastPlayOrder) { runCleanup = true; break; } lastPlayOrder = playOrder; } while (mCursor.moveToNext()); } if (runCleanup) { cleanupPlaylist(context, mPlaylistID, mCursor); mCursor.close(); mCursor = makePlaylistSongCursor(context, mPlaylistID); if (mCursor != null) { } } } if (mCursor != null && mCursor.moveToFirst()) { do { final long id = mCursor.getLong(mCursor .getColumnIndexOrThrow(MediaStore.Audio.Playlists.Members.AUDIO_ID)); final String songName = mCursor.getString(mCursor .getColumnIndexOrThrow(AudioColumns.TITLE)); final String artist = mCursor.getString(mCursor .getColumnIndexOrThrow(AudioColumns.ARTIST)); final long albumId = mCursor.getLong(mCursor .getColumnIndexOrThrow(AudioColumns.ALBUM_ID)); final long artistId = mCursor.getLong(mCursor .getColumnIndexOrThrow(AudioColumns.ARTIST_ID)); final String album = mCursor.getString(mCursor .getColumnIndexOrThrow(AudioColumns.ALBUM)); final long duration = mCursor.getLong(mCursor .getColumnIndexOrThrow(AudioColumns.DURATION)); final int durationInSecs = (int) duration / 1000; final int tracknumber = mCursor.getInt(mCursor .getColumnIndexOrThrow(AudioColumns.TRACK)); final Song song = new Song(id, albumId, artistId, songName, artist, album, durationInSecs, tracknumber); mSongList.add(song); } while (mCursor.moveToNext()); } // Close the cursor if (mCursor != null) { mCursor.close(); mCursor = null; } return mSongList; } private static void cleanupPlaylist(final Context context, final long playlistId, final Cursor cursor) { final int idCol = cursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists.Members.AUDIO_ID); final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId); ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); ops.add(ContentProviderOperation.newDelete(uri).build()); final int YIELD_FREQUENCY = 100; if (cursor.moveToFirst() && cursor.getCount() > 0) { do { final ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(uri) .withValue(Playlists.Members.PLAY_ORDER, cursor.getPosition()) .withValue(Playlists.Members.AUDIO_ID, cursor.getLong(idCol)); if ((cursor.getPosition() + 1) % YIELD_FREQUENCY == 0) { builder.withYieldAllowed(true); } ops.add(builder.build()); } while (cursor.moveToNext()); } try { context.getContentResolver().applyBatch(MediaStore.AUTHORITY, ops); } catch (RemoteException e) { } catch (OperationApplicationException e) { } } private static int countPlaylist(final Context context, final long playlistId) { Cursor c = null; try { c = context.getContentResolver().query( MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId), new String[]{ MediaStore.Audio.Playlists.Members.AUDIO_ID, }, null, null, MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER); if (c != null) { return c.getCount(); } } finally { if (c != null) { c.close(); c = null; } } return 0; } public static final Cursor makePlaylistSongCursor(final Context context, final Long playlistID) { final StringBuilder mSelection = new StringBuilder(); mSelection.append(AudioColumns.IS_MUSIC + "=1"); mSelection.append(" AND " + AudioColumns.TITLE + " != ''"); return context.getContentResolver().query( MediaStore.Audio.Playlists.Members.getContentUri("external", playlistID), new String[]{ MediaStore.Audio.Playlists.Members._ID, MediaStore.Audio.Playlists.Members.AUDIO_ID, AudioColumns.TITLE, AudioColumns.ARTIST, AudioColumns.ALBUM_ID, AudioColumns.ARTIST_ID, AudioColumns.ALBUM, AudioColumns.DURATION, AudioColumns.TRACK, Playlists.Members.PLAY_ORDER, }, mSelection.toString(), null, MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER); } }