use query backend for playlists
This commit is contained in:
parent
1366060040
commit
6592a0e0d5
5 changed files with 16 additions and 287 deletions
|
|
@ -7,7 +7,6 @@ import androidx.fragment.app.DialogFragment;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||||
|
|
@ -36,7 +35,8 @@ public class AddToPlaylistDialog extends DialogFragment {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
final List<Playlist> playlists = PlaylistLoader.getAllPlaylists(getActivity());
|
final List<Playlist> playlists = new ArrayList<>();
|
||||||
|
|
||||||
CharSequence[] playlistNames = new CharSequence[playlists.size() + 1];
|
CharSequence[] playlistNames = new CharSequence[playlists.size() + 1];
|
||||||
playlistNames[0] = getActivity().getResources().getString(R.string.action_new_playlist);
|
playlistNames[0] = getActivity().getResources().getString(R.string.action_new_playlist);
|
||||||
for (int i = 1; i < playlistNames.length; i++) {
|
for (int i = 1; i < playlistNames.length; i++) {
|
||||||
|
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
package com.kabouzeid.gramophone.loader;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.provider.BaseColumns;
|
|
||||||
import android.provider.MediaStore;
|
|
||||||
import android.provider.MediaStore.Audio.PlaylistsColumns;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PlaylistLoader {
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static List<Playlist> getAllPlaylists(@NonNull final Context context) {
|
|
||||||
return getAllPlaylists(makePlaylistCursor(context, null, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static Playlist getPlaylist(@NonNull final Context context, final int playlistId) {
|
|
||||||
return getPlaylist(makePlaylistCursor(
|
|
||||||
context,
|
|
||||||
BaseColumns._ID + "=?",
|
|
||||||
new String[]{
|
|
||||||
String.valueOf(playlistId)
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static Playlist getPlaylist(@NonNull final Context context, final String playlistName) {
|
|
||||||
return getPlaylist(makePlaylistCursor(
|
|
||||||
context,
|
|
||||||
PlaylistsColumns.NAME + "=?",
|
|
||||||
new String[]{
|
|
||||||
playlistName
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static Playlist getPlaylist(@Nullable final Cursor cursor) {
|
|
||||||
Playlist playlist = new Playlist();
|
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
playlist = getPlaylistFromCursorImpl(cursor);
|
|
||||||
}
|
|
||||||
if (cursor != null)
|
|
||||||
cursor.close();
|
|
||||||
return playlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static List<Playlist> getAllPlaylists(@Nullable final Cursor cursor) {
|
|
||||||
List<Playlist> playlists = new ArrayList<>();
|
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
playlists.add(getPlaylistFromCursorImpl(cursor));
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
}
|
|
||||||
if (cursor != null)
|
|
||||||
cursor.close();
|
|
||||||
return playlists;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private static Playlist getPlaylistFromCursorImpl(@NonNull final Cursor cursor) {
|
|
||||||
final int id = cursor.getInt(0);
|
|
||||||
final String name = cursor.getString(1);
|
|
||||||
return new Playlist(id, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
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,
|
|
||||||
new String[]{
|
|
||||||
/* 0 */
|
|
||||||
BaseColumns._ID,
|
|
||||||
/* 1 */
|
|
||||||
PlaylistsColumns.NAME
|
|
||||||
}, selection, values, MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 The CyanogenMod Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.kabouzeid.gramophone.loader;
|
|
||||||
|
|
||||||
import android.database.AbstractCursor;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This cursor basically wraps a song cursor and is given a list of the order of the ids of the
|
|
||||||
* contents of the cursor. It wraps the Cursor and simulates the internal cursor being sorted
|
|
||||||
* by moving the point to the appropriate spot
|
|
||||||
*/
|
|
||||||
public class SortedCursor extends AbstractCursor {
|
|
||||||
// cursor to wrap
|
|
||||||
private final Cursor mCursor;
|
|
||||||
// the map of external indices to internal indices
|
|
||||||
private List<Integer> mOrderedPositions;
|
|
||||||
// this contains the ids that weren't found in the underlying cursor
|
|
||||||
private List<String> mMissingValues;
|
|
||||||
// this contains the mapped cursor positions and afterwards the extra ids that weren't found
|
|
||||||
private HashMap<String, Integer> mMapCursorPositions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cursor to wrap
|
|
||||||
* @param order the list of unique ids in sorted order to display
|
|
||||||
* @param columnName the column name of the id to look up in the internal cursor
|
|
||||||
*/
|
|
||||||
public SortedCursor(@NonNull final Cursor cursor, @Nullable final String[] order, final String columnName) {
|
|
||||||
mCursor = cursor;
|
|
||||||
mMissingValues = buildCursorPositionMapping(order, columnName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function populates mOrderedPositions with the cursor positions in the order based
|
|
||||||
* on the order passed in
|
|
||||||
*
|
|
||||||
* @param order the target order of the internal cursor
|
|
||||||
* @return returns the ids that aren't found in the underlying cursor
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private List<String> buildCursorPositionMapping(@Nullable final String[] order, final String columnName) {
|
|
||||||
List<String> missingValues = new ArrayList<>();
|
|
||||||
|
|
||||||
mOrderedPositions = new ArrayList<>(mCursor.getCount());
|
|
||||||
|
|
||||||
mMapCursorPositions = new HashMap<>(mCursor.getCount());
|
|
||||||
final int valueColumnIndex = mCursor.getColumnIndex(columnName);
|
|
||||||
|
|
||||||
if (mCursor.moveToFirst()) {
|
|
||||||
// first figure out where each of the ids are in the cursor
|
|
||||||
do {
|
|
||||||
mMapCursorPositions.put(mCursor.getString(valueColumnIndex), mCursor.getPosition());
|
|
||||||
} while (mCursor.moveToNext());
|
|
||||||
|
|
||||||
if (order != null) {
|
|
||||||
// now create the ordered positions to map to the internal cursor given the
|
|
||||||
// external sort order
|
|
||||||
for (final String value : order) {
|
|
||||||
if (mMapCursorPositions.containsKey(value)) {
|
|
||||||
mOrderedPositions.add(mMapCursorPositions.get(value));
|
|
||||||
mMapCursorPositions.remove(value);
|
|
||||||
} else {
|
|
||||||
missingValues.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mCursor.moveToFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
return missingValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the list of ids that weren't found in the underlying cursor
|
|
||||||
*/
|
|
||||||
public List<String> getMissingValues() {
|
|
||||||
return mMissingValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the list of ids that were in the underlying cursor but not part of the ordered list
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public Collection<String> getExtraValues() {
|
|
||||||
return mMapCursorPositions.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
mCursor.close();
|
|
||||||
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return mOrderedPositions.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getColumnNames() {
|
|
||||||
return mCursor.getColumnNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getString(int column) {
|
|
||||||
return mCursor.getString(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short getShort(int column) {
|
|
||||||
return mCursor.getShort(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInt(int column) {
|
|
||||||
return mCursor.getInt(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getLong(int column) {
|
|
||||||
return mCursor.getLong(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getFloat(int column) {
|
|
||||||
return mCursor.getFloat(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getDouble(int column) {
|
|
||||||
return mCursor.getDouble(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNull(int column) {
|
|
||||||
return mCursor.isNull(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onMove(int oldPosition, int newPosition) {
|
|
||||||
if (newPosition >= 0 && newPosition < getCount()) {
|
|
||||||
mCursor.moveToPosition(mOrderedPositions.get(newPosition));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -25,7 +25,6 @@ import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.menu.PlaylistMenuHelper;
|
import com.kabouzeid.gramophone.helper.menu.PlaylistMenuHelper;
|
||||||
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
import com.kabouzeid.gramophone.interfaces.MediaCallback;
|
import com.kabouzeid.gramophone.interfaces.MediaCallback;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.model.playlist.AbsSmartPlaylist;
|
import com.kabouzeid.gramophone.model.playlist.AbsSmartPlaylist;
|
||||||
|
|
@ -78,6 +77,16 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
|
||||||
|
|
||||||
setUpRecyclerView();
|
setUpRecyclerView();
|
||||||
setUpToolbar();
|
setUpToolbar();
|
||||||
|
|
||||||
|
ItemQuery query = new ItemQuery();
|
||||||
|
query.setParentId(playlist.id);
|
||||||
|
QueryUtil.getSongs(query, new MediaCallback() {
|
||||||
|
@Override
|
||||||
|
public void onLoadMedia(List<?> media) {
|
||||||
|
adapter.getDataSet().addAll((List<Song>) media);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -178,27 +187,10 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
|
||||||
@Override
|
@Override
|
||||||
public void onMediaStoreChanged() {
|
public void onMediaStoreChanged() {
|
||||||
super.onMediaStoreChanged();
|
super.onMediaStoreChanged();
|
||||||
|
|
||||||
if (!(playlist instanceof AbsSmartPlaylist)) {
|
|
||||||
// Playlist deleted
|
|
||||||
if (!PlaylistsUtil.doesPlaylistExist(this, playlist.id)) {
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Playlist renamed
|
|
||||||
final String playlistName = PlaylistsUtil.getNameForPlaylist(this, playlist.id.hashCode());
|
|
||||||
if (!playlistName.equals(playlist.name)) {
|
|
||||||
playlist = PlaylistLoader.getPlaylist(this, playlist.id);
|
|
||||||
setToolbarTitle(playlist.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkIsEmpty() {
|
private void checkIsEmpty() {
|
||||||
empty.setVisibility(
|
empty.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||||
adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -206,6 +198,7 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
|
||||||
if (recyclerViewDragDropManager != null) {
|
if (recyclerViewDragDropManager != null) {
|
||||||
recyclerViewDragDropManager.cancelDrag();
|
recyclerViewDragDropManager.cancelDrag();
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.App;
|
import com.kabouzeid.gramophone.App;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
|
||||||
import com.kabouzeid.gramophone.model.Album;
|
import com.kabouzeid.gramophone.model.Album;
|
||||||
import com.kabouzeid.gramophone.model.Artist;
|
import com.kabouzeid.gramophone.model.Artist;
|
||||||
import com.kabouzeid.gramophone.model.Genre;
|
import com.kabouzeid.gramophone.model.Genre;
|
||||||
|
|
@ -152,15 +151,14 @@ public class MusicUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Playlist getFavoritesPlaylist(@NonNull final Context context) {
|
public static Playlist getFavoritesPlaylist(@NonNull final Context context) {
|
||||||
return PlaylistLoader.getPlaylist(context, context.getString(R.string.favorites));
|
return new Playlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Playlist getOrCreateFavoritesPlaylist(@NonNull final Context context) {
|
private static Playlist getOrCreateFavoritesPlaylist(@NonNull final Context context) {
|
||||||
return PlaylistLoader.getPlaylist(context, PlaylistsUtil.createPlaylist(context, context.getString(R.string.favorites)));
|
return new Playlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isFavorite(@NonNull final Context context, @NonNull final Song song) {
|
public static boolean isFavorite(@NonNull final Context context, @NonNull final Song song) {
|
||||||
//return PlaylistsUtil.doPlaylistContains(context, getFavoritesPlaylist(context).id, song.id);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue