Support for Android Marshmallow's permission system
This commit is contained in:
parent
193f716029
commit
6f3617650a
12 changed files with 305 additions and 176 deletions
|
|
@ -28,6 +28,8 @@
|
||||||
<h3>Version 0.9.43 beta5</h3>
|
<h3>Version 0.9.43 beta5</h3>
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
|
<li><b>NEW:</b> Support for Android Marshmallow's permission system.</a>.
|
||||||
|
</li>
|
||||||
<li><b>IMPROVEMENT:</b> The sliding panel should open and close a bit smoother now.</a>.
|
<li><b>IMPROVEMENT:</b> The sliding panel should open and close a bit smoother now.</a>.
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
|
||||||
|
|
@ -77,15 +77,19 @@ public class AlbumLoader {
|
||||||
return new Album(id, albumName, artist, artistId, songCount, year);
|
return new Album(id, albumName, artist, artistId, songCount, year);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static Cursor makeAlbumCursor(@NonNull final Context context, final String selection, final String[] values) {
|
public static Cursor makeAlbumCursor(@NonNull final Context context, final String selection, final String[] values) {
|
||||||
return makeAlbumCursor(context, selection, values, PreferenceUtil.getInstance(context).getAlbumSortOrder());
|
return makeAlbumCursor(context, selection, values, PreferenceUtil.getInstance(context).getAlbumSortOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static Cursor makeAlbumCursor(@NonNull final Context context, final String selection, final String[] values, final String sortOrder) {
|
public static Cursor makeAlbumCursor(@NonNull final Context context, final String selection, final String[] values, final String sortOrder) {
|
||||||
return makeAlbumCursor(context, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, selection, values, sortOrder);
|
return makeAlbumCursor(context, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, selection, values, sortOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static Cursor makeAlbumCursor(@NonNull final Context context, @NonNull final Uri contentUri, final String selection, final String[] values, final String sortOrder) {
|
public static Cursor makeAlbumCursor(@NonNull final Context context, @NonNull final Uri contentUri, final String selection, final String[] values, final String sortOrder) {
|
||||||
|
try {
|
||||||
return context.getContentResolver().query(contentUri,
|
return context.getContentResolver().query(contentUri,
|
||||||
new String[]{
|
new String[]{
|
||||||
/* 0 */
|
/* 0 */
|
||||||
|
|
@ -101,5 +105,8 @@ public class AlbumLoader {
|
||||||
/* 5 */
|
/* 5 */
|
||||||
AlbumColumns.FIRST_YEAR,
|
AlbumColumns.FIRST_YEAR,
|
||||||
}, selection, values, sortOrder);
|
}, selection, values, sortOrder);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,15 @@ public class ArtistAlbumLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cursor makeArtistAlbumCursor(@NonNull final Context context, final int artistId) {
|
public static Cursor makeArtistAlbumCursor(@NonNull final Context context, final int artistId) {
|
||||||
|
try {
|
||||||
return AlbumLoader.makeAlbumCursor(context,
|
return AlbumLoader.makeAlbumCursor(context,
|
||||||
MediaStore.Audio.Artists.Albums.getContentUri("external", artistId),
|
MediaStore.Audio.Artists.Albums.getContentUri("external", artistId),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
PreferenceUtil.getInstance(context).getArtistAlbumSortOrder()
|
PreferenceUtil.getInstance(context).getArtistAlbumSortOrder()
|
||||||
);
|
);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,9 @@ public class ArtistLoader {
|
||||||
return new Artist(id, artistName, albumCount, songCount);
|
return new Artist(id, artistName, albumCount, songCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static Cursor makeArtistCursor(@NonNull final Context context, final String selection, final String[] values) {
|
public static Cursor makeArtistCursor(@NonNull final Context context, final String selection, final String[] values) {
|
||||||
|
try {
|
||||||
return context.getContentResolver().query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
|
return context.getContentResolver().query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
|
||||||
new String[]{
|
new String[]{
|
||||||
/* 0 */
|
/* 0 */
|
||||||
|
|
@ -86,5 +88,8 @@ public class ArtistLoader {
|
||||||
/* 3 */
|
/* 3 */
|
||||||
ArtistColumns.NUMBER_OF_TRACKS
|
ArtistColumns.NUMBER_OF_TRACKS
|
||||||
}, selection, values, PreferenceUtil.getInstance(context).getArtistSortOrder());
|
}, selection, values, PreferenceUtil.getInstance(context).getArtistSortOrder());
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ public class ArtistSongLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cursor makeArtistSongCursor(@NonNull final Context context, final int artistId) {
|
public static Cursor makeArtistSongCursor(@NonNull final Context context, final int artistId) {
|
||||||
|
try {
|
||||||
return SongLoader.makeSongCursor(
|
return SongLoader.makeSongCursor(
|
||||||
context,
|
context,
|
||||||
MediaStore.Audio.AudioColumns.ARTIST_ID + "=?",
|
MediaStore.Audio.AudioColumns.ARTIST_ID + "=?",
|
||||||
|
|
@ -29,5 +30,8 @@ public class ArtistSongLoader {
|
||||||
},
|
},
|
||||||
PreferenceUtil.getInstance(context).getArtistSongSortOrder()
|
PreferenceUtil.getInstance(context).getArtistSongSortOrder()
|
||||||
);
|
);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +75,9 @@ public class PlaylistLoader {
|
||||||
return new Playlist(id, name);
|
return new Playlist(id, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static Cursor makePlaylistCursor(@NonNull final Context context, final String selection, final String[] values) {
|
public static Cursor makePlaylistCursor(@NonNull final Context context, final String selection, final String[] values) {
|
||||||
|
try {
|
||||||
return context.getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
return context.getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
new String[]{
|
new String[]{
|
||||||
/* 0 */
|
/* 0 */
|
||||||
|
|
@ -83,5 +85,8 @@ public class PlaylistLoader {
|
||||||
/* 1 */
|
/* 1 */
|
||||||
PlaylistsColumns.NAME
|
PlaylistsColumns.NAME
|
||||||
}, selection, values, MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER);
|
}, selection, values, MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -45,6 +45,7 @@ public class PlaylistSongLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cursor makePlaylistSongCursor(@NonNull final Context context, final int playlistId) {
|
public static Cursor makePlaylistSongCursor(@NonNull final Context context, final int playlistId) {
|
||||||
|
try {
|
||||||
return context.getContentResolver().query(
|
return context.getContentResolver().query(
|
||||||
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId),
|
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId),
|
||||||
new String[]{
|
new String[]{
|
||||||
|
|
@ -70,5 +71,8 @@ public class PlaylistSongLoader {
|
||||||
MediaStore.Audio.Playlists.Members._ID
|
MediaStore.Audio.Playlists.Members._ID
|
||||||
}, SongLoader.BASE_SELECTION, null,
|
}, SongLoader.BASE_SELECTION, null,
|
||||||
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER);
|
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import com.kabouzeid.gramophone.util.PreferenceUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import hugo.weaving.DebugLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid)
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
*/
|
*/
|
||||||
|
|
@ -77,16 +79,20 @@ public class SongLoader {
|
||||||
return new Song(id, albumId, artistId, songName, artist, album, duration, trackNumber, data);
|
return new Song(id, albumId, artistId, songName, artist, album, duration, trackNumber, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static Cursor makeSongCursor(@NonNull final Context context, final String selection, final String[] values) {
|
public static Cursor makeSongCursor(@NonNull final Context context, final String selection, final String[] values) {
|
||||||
return makeSongCursor(context, selection, values, PreferenceUtil.getInstance(context).getSongSortOrder());
|
return makeSongCursor(context, selection, values, PreferenceUtil.getInstance(context).getSongSortOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DebugLog
|
||||||
|
@Nullable
|
||||||
public static Cursor makeSongCursor(@NonNull final Context context, @Nullable final String selection, final String[] values, final String sortOrder) {
|
public static Cursor makeSongCursor(@NonNull final Context context, @Nullable final String selection, final String[] values, final String sortOrder) {
|
||||||
String baseSelection = BASE_SELECTION;
|
String baseSelection = BASE_SELECTION;
|
||||||
if (selection != null && !selection.trim().equals("")) {
|
if (selection != null && !selection.trim().equals("")) {
|
||||||
baseSelection += " AND " + selection;
|
baseSelection += " AND " + selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
return context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
return context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||||
new String[]{
|
new String[]{
|
||||||
/* 0 */
|
/* 0 */
|
||||||
|
|
@ -108,5 +114,8 @@ public class SongLoader {
|
||||||
/* 8 */
|
/* 8 */
|
||||||
AudioColumns.DATA
|
AudioColumns.DATA
|
||||||
}, baseSelection, values, sortOrder);
|
}, baseSelection, values, sortOrder);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
|
@ -139,7 +138,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
||||||
private boolean isServiceInUse;
|
private boolean isServiceInUse;
|
||||||
|
|
||||||
private static String getTrackUri(@NonNull Song song) {
|
private static String getTrackUri(@NonNull Song song) {
|
||||||
return ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.id).toString();
|
return MusicUtil.getSongUri(song.id).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
package com.kabouzeid.gramophone.ui.activities.base;
|
package com.kabouzeid.gramophone.ui.activities.base;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
|
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
|
||||||
|
|
@ -17,24 +22,53 @@ import com.kabouzeid.gramophone.service.MusicService;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import hugo.weaving.DebugLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid)
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
*/
|
*/
|
||||||
public abstract class AbsMusicServiceActivity extends AbsBaseActivity implements ServiceConnection, MusicServiceEventListener {
|
public abstract class AbsMusicServiceActivity extends AbsBaseActivity implements ServiceConnection, MusicServiceEventListener {
|
||||||
public static final String TAG = AbsMusicServiceActivity.class.getSimpleName();
|
public static final String TAG = AbsMusicServiceActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
public static final int REQUEST_EXTERNAL_STORAGE_PERMISSION = 0;
|
||||||
|
|
||||||
private final ArrayList<MusicServiceEventListener> mMusicServiceEventListener = new ArrayList<>();
|
private final ArrayList<MusicServiceEventListener> mMusicServiceEventListener = new ArrayList<>();
|
||||||
|
|
||||||
private MusicPlayerRemote.ServiceToken serviceToken;
|
private MusicPlayerRemote.ServiceToken serviceToken;
|
||||||
private MusicStateReceiver musicStateReceiver;
|
private MusicStateReceiver musicStateReceiver;
|
||||||
private boolean receiverRegistered;
|
private boolean receiverRegistered;
|
||||||
|
|
||||||
|
private boolean hasExternalStoragePermission;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
checkExternalStoragePermissions();
|
||||||
serviceToken = MusicPlayerRemote.bindToService(this, this);
|
serviceToken = MusicPlayerRemote.bindToService(this, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
// the handler is necessary to avoid "java.lang.RuntimeException: Performing pause of activity that is not resumed"
|
||||||
|
new Handler().postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
recreateIfPermissionsChanged();
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void recreateIfPermissionsChanged() {
|
||||||
|
if (didPermissionsChanged()) {
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean didPermissionsChanged() {
|
||||||
|
return hasExternalStoragePermission != hasExternalStoragePermission();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
if (!receiverRegistered) {
|
if (!receiverRegistered) {
|
||||||
|
|
@ -161,4 +195,30 @@ public abstract class AbsMusicServiceActivity extends AbsBaseActivity implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkExternalStoragePermissions() {
|
||||||
|
hasExternalStoragePermission = hasExternalStoragePermission();
|
||||||
|
if (hasExternalStoragePermission) {
|
||||||
|
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE_PERMISSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasExternalStoragePermission() {
|
||||||
|
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DebugLog
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
if (requestCode == REQUEST_EXTERNAL_STORAGE_PERMISSION) {
|
||||||
|
for (int grantResult : grantResults) {
|
||||||
|
if (grantResult == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
recreate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Toast.makeText(AbsMusicServiceActivity.this, "You must grant permission to external storage in order to explore your music", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ public class MusicUtil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
Cursor cursor = resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
Cursor cursor = resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||||
new String[]{MediaStore.MediaColumns.TITLE},
|
new String[]{MediaStore.MediaColumns.TITLE},
|
||||||
BaseColumns._ID + "=?",
|
BaseColumns._ID + "=?",
|
||||||
|
|
@ -103,6 +104,8 @@ public class MusicUtil {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|
@ -174,6 +177,8 @@ public class MusicUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selection.append(")");
|
selection.append(")");
|
||||||
|
|
||||||
|
try {
|
||||||
final Cursor cursor = context.getContentResolver().query(
|
final Cursor cursor = context.getContentResolver().query(
|
||||||
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection.toString(),
|
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection.toString(),
|
||||||
null, null);
|
null, null);
|
||||||
|
|
@ -214,6 +219,8 @@ public class MusicUtil {
|
||||||
}
|
}
|
||||||
context.getContentResolver().notifyChange(Uri.parse("content://media"), null);
|
context.getContentResolver().notifyChange(Uri.parse("content://media"), null);
|
||||||
Toast.makeText(context, context.getString(R.string.deleted_x_songs, songs.size()), Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, context.getString(R.string.deleted_x_songs, songs.size()), Toast.LENGTH_SHORT).show();
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Playlist getFavoritesPlaylist(@NonNull final Context context) {
|
public static Playlist getFavoritesPlaylist(@NonNull final Context context) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.util;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
|
@ -16,7 +15,6 @@ import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.service.MusicService;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -29,6 +27,7 @@ public class PlaylistsUtil {
|
||||||
public static int createPlaylist(@NonNull final Context context, @Nullable final String name) {
|
public static int createPlaylist(@NonNull final Context context, @Nullable final String name) {
|
||||||
int id = -1;
|
int id = -1;
|
||||||
if (name != null && name.length() > 0) {
|
if (name != null && name.length() > 0) {
|
||||||
|
try {
|
||||||
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
new String[]{MediaStore.Audio.Playlists._ID}, MediaStore.Audio.PlaylistsColumns.NAME + "=?", new String[]{name}, null);
|
new String[]{MediaStore.Audio.Playlists._ID}, MediaStore.Audio.PlaylistsColumns.NAME + "=?", new String[]{name}, null);
|
||||||
if (cursor == null || cursor.getCount() < 1) {
|
if (cursor == null || cursor.getCount() < 1) {
|
||||||
|
|
@ -39,7 +38,7 @@ public class PlaylistsUtil {
|
||||||
values);
|
values);
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
// necessary because somehow the MediaStoreObserver is not notified when adding a playlist
|
// necessary because somehow the MediaStoreObserver is not notified when adding a playlist
|
||||||
context.sendBroadcast(new Intent(MusicService.MEDIA_STORE_CHANGED));
|
context.getContentResolver().notifyChange(Uri.parse("content://media"), null);
|
||||||
Toast.makeText(context, context.getResources().getString(
|
Toast.makeText(context, context.getResources().getString(
|
||||||
R.string.created_playlist_x, name), Toast.LENGTH_SHORT).show();
|
R.string.created_playlist_x, name), Toast.LENGTH_SHORT).show();
|
||||||
id = Integer.parseInt(uri.getLastPathSegment());
|
id = Integer.parseInt(uri.getLastPathSegment());
|
||||||
|
|
@ -52,6 +51,8 @@ public class PlaylistsUtil {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
Toast.makeText(context, context.getResources().getString(
|
Toast.makeText(context, context.getResources().getString(
|
||||||
|
|
@ -70,7 +71,10 @@ public class PlaylistsUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selection.append(")");
|
selection.append(")");
|
||||||
|
try {
|
||||||
context.getContentResolver().delete(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, selection.toString(), null);
|
context.getContentResolver().delete(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, selection.toString(), null);
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addToPlaylist(@NonNull final Context context, final Song song, final int playlistId, final boolean showToastOnFinish) {
|
public static void addToPlaylist(@NonNull final Context context, final Song song, final int playlistId, final boolean showToastOnFinish) {
|
||||||
|
|
@ -89,6 +93,7 @@ public class PlaylistsUtil {
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
int base = 0;
|
int base = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
try {
|
try {
|
||||||
cursor = resolver.query(uri, projection, null, null, null);
|
cursor = resolver.query(uri, projection, null, null, null);
|
||||||
|
|
||||||
|
|
@ -101,13 +106,15 @@ public class PlaylistsUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int numinserted = 0;
|
int numInserted = 0;
|
||||||
for (int offSet = 0; offSet < size; offSet += 1000)
|
for (int offSet = 0; offSet < size; offSet += 1000)
|
||||||
numinserted += resolver.bulkInsert(uri, makeInsertItems(songs, offSet, 1000, base));
|
numInserted += resolver.bulkInsert(uri, makeInsertItems(songs, offSet, 1000, base));
|
||||||
|
|
||||||
if (showToastOnFinish) {
|
if (showToastOnFinish) {
|
||||||
Toast.makeText(context, context.getResources().getString(
|
Toast.makeText(context, context.getResources().getString(
|
||||||
R.string.inserted_x_songs_into_playlist, numinserted), Toast.LENGTH_SHORT).show();
|
R.string.inserted_x_songs_into_playlist, numInserted), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,7 +140,10 @@ public class PlaylistsUtil {
|
||||||
String selection = MediaStore.Audio.Playlists.Members.AUDIO_ID + " =?";
|
String selection = MediaStore.Audio.Playlists.Members.AUDIO_ID + " =?";
|
||||||
String[] selectionArgs = new String[]{String.valueOf(song.id)};
|
String[] selectionArgs = new String[]{String.valueOf(song.id)};
|
||||||
|
|
||||||
|
try {
|
||||||
context.getContentResolver().delete(uri, selection, selectionArgs);
|
context.getContentResolver().delete(uri, selection, selectionArgs);
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeFromPlaylist(@NonNull final Context context, @NonNull final List<PlaylistSong> songs) {
|
public static void removeFromPlaylist(@NonNull final Context context, @NonNull final List<PlaylistSong> songs) {
|
||||||
|
|
@ -145,14 +155,19 @@ public class PlaylistsUtil {
|
||||||
selectionArgs[i] = String.valueOf(songs.get(i).idInPlayList);
|
selectionArgs[i] = String.valueOf(songs.get(i).idInPlayList);
|
||||||
}
|
}
|
||||||
String selection = MediaStore.Audio.Playlists.Members._ID + " in (";
|
String selection = MediaStore.Audio.Playlists.Members._ID + " in (";
|
||||||
|
//noinspection unused
|
||||||
for (String selectionArg : selectionArgs) selection += "?, ";
|
for (String selectionArg : selectionArgs) selection += "?, ";
|
||||||
selection = selection.substring(0, selection.length() - 2) + ")";
|
selection = selection.substring(0, selection.length() - 2) + ")";
|
||||||
|
|
||||||
|
try {
|
||||||
context.getContentResolver().delete(uri, selection, selectionArgs);
|
context.getContentResolver().delete(uri, selection, selectionArgs);
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean doPlaylistContains(@NonNull final Context context, final long playlistId, final int songId) {
|
public static boolean doPlaylistContains(@NonNull final Context context, final long playlistId, final int songId) {
|
||||||
if (playlistId != -1) {
|
if (playlistId != -1) {
|
||||||
|
try {
|
||||||
Cursor c = context.getContentResolver().query(
|
Cursor c = context.getContentResolver().query(
|
||||||
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId),
|
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId),
|
||||||
new String[]{MediaStore.Audio.Playlists.Members.AUDIO_ID}, MediaStore.Audio.Playlists.Members.AUDIO_ID + "=?", new String[]{String.valueOf(songId)}, null);
|
new String[]{MediaStore.Audio.Playlists.Members.AUDIO_ID}, MediaStore.Audio.Playlists.Members.AUDIO_ID + "=?", new String[]{String.valueOf(songId)}, null);
|
||||||
|
|
@ -162,6 +177,8 @@ public class PlaylistsUtil {
|
||||||
c.close();
|
c.close();
|
||||||
}
|
}
|
||||||
return count > 0;
|
return count > 0;
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -174,13 +191,17 @@ public class PlaylistsUtil {
|
||||||
public static void renamePlaylist(@NonNull final Context context, final long id, final String newName) {
|
public static void renamePlaylist(@NonNull final Context context, final long id, final String newName) {
|
||||||
ContentValues contentValues = new ContentValues();
|
ContentValues contentValues = new ContentValues();
|
||||||
contentValues.put(MediaStore.Audio.PlaylistsColumns.NAME, newName);
|
contentValues.put(MediaStore.Audio.PlaylistsColumns.NAME, newName);
|
||||||
|
try {
|
||||||
context.getContentResolver().update(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
context.getContentResolver().update(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
contentValues,
|
contentValues,
|
||||||
MediaStore.Audio.Playlists._ID + "=?",
|
MediaStore.Audio.Playlists._ID + "=?",
|
||||||
new String[]{String.valueOf(id)});
|
new String[]{String.valueOf(id)});
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getNameForPlaylist(@NonNull final Context context, final long id) {
|
public static String getNameForPlaylist(@NonNull final Context context, final long id) {
|
||||||
|
try {
|
||||||
Cursor cursor = context.getContentResolver().query(
|
Cursor cursor = context.getContentResolver().query(
|
||||||
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
new String[]{MediaStore.Audio.PlaylistsColumns.NAME},
|
new String[]{MediaStore.Audio.PlaylistsColumns.NAME},
|
||||||
|
|
@ -196,6 +217,8 @@ public class PlaylistsUtil {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue