This commit is contained in:
h4h13 2018-11-28 13:18:19 +05:30
parent 5d2a30b65a
commit 8e6ab40d93
23 changed files with 266 additions and 253 deletions

View file

@ -17,7 +17,7 @@ import java.util.ArrayList;
public class AlbumLoader {
public static Observable<ArrayList<Album>> getAllAlbums(@NonNull Context context) {
Observable<ArrayList<Song>> songs = SongLoader.getSongs(SongLoader.makeSongCursor(
Observable<ArrayList<Song>> songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
context,
null,
null,
@ -30,7 +30,7 @@ public class AlbumLoader {
@NonNull
public static Observable<ArrayList<Album>> getAlbums(@NonNull final Context context,
String query) {
Observable<ArrayList<Song>> songs = SongLoader.getSongs(SongLoader.makeSongCursor(
Observable<ArrayList<Song>> songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
context,
AudioColumns.ALBUM + " LIKE ?",
new String[]{"%" + query + "%"},
@ -42,7 +42,7 @@ public class AlbumLoader {
@NonNull
public static Observable<Album> getAlbum(@NonNull final Context context, int albumId) {
return Observable.create(e -> {
Observable<ArrayList<Song>> songs = SongLoader.getSongs(SongLoader
Observable<ArrayList<Song>> songs = SongLoader.Companion.getSongs(SongLoader.Companion
.makeSongCursor(context, AudioColumns.ALBUM_ID + "=?",
new String[]{String.valueOf(albumId)}, getSongLoaderSortOrder(context)));
songs.subscribe(songs1 -> {

View file

@ -22,7 +22,7 @@ public class ArtistLoader {
@NonNull
public static Observable<Artist> getArtist(@NonNull final Context context, int artistId) {
return Observable.create(e -> SongLoader.getSongs(SongLoader.makeSongCursor(
return Observable.create(e -> SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
context,
AudioColumns.ARTIST_ID + "=?",
new String[]{String.valueOf(artistId)},
@ -36,8 +36,8 @@ public class ArtistLoader {
@NonNull
public static Observable<ArrayList<Artist>> getAllArtists(@NonNull final Context context) {
return Observable.create(e -> SongLoader
.getSongs(SongLoader.makeSongCursor(
return Observable.create(e -> SongLoader.Companion
.getSongs(SongLoader.Companion.makeSongCursor(
context,
null,
null,
@ -51,7 +51,7 @@ public class ArtistLoader {
@NonNull
public static Observable<ArrayList<Artist>> getArtists(@NonNull final Context context, String query) {
return Observable.create(e -> SongLoader.getSongs(SongLoader.makeSongCursor(
return Observable.create(e -> SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
context,
AudioColumns.ARTIST + " LIKE ?",
new String[]{"%" + query + "%"},

View file

@ -17,12 +17,12 @@ public class ArtistSongLoader extends SongLoader {
@NonNull
public static Observable<ArrayList<Song>> getArtistSongList(@NonNull final Context context, final int artistId) {
return getSongs(makeArtistSongCursor(context, artistId));
return Companion.getSongs(makeArtistSongCursor(context, artistId));
}
public static Cursor makeArtistSongCursor(@NonNull final Context context, final int artistId) {
try {
return makeSongCursor(
return Companion.makeSongCursor(
context,
MediaStore.Audio.AudioColumns.ARTIST_ID + "=?",
new String[]{

View file

@ -5,11 +5,11 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.MediaStore.Audio.Genres;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.PreferenceUtil;
@ -30,7 +30,7 @@ public class GenreLoader {
return getSongsWithNoGenre(context);
}
return SongLoader.getSongs(makeGenreSongCursor(context, genreId));
return SongLoader.Companion.getSongs(makeGenreSongCursor(context, genreId));
}
@NonNull
@ -46,11 +46,11 @@ public class GenreLoader {
private static Observable<ArrayList<Song>> getSongsWithNoGenre(@NonNull final Context context) {
String selection = BaseColumns._ID + " NOT IN " +
"(SELECT " + Genres.Members.AUDIO_ID + " FROM audio_genres_map)";
return SongLoader.getSongs(SongLoader.makeSongCursor(context, selection, null));
return SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, selection, null));
}
private static boolean hasSongsWithNoGenre(@NonNull final Context context) {
final Cursor allSongsCursor = SongLoader.makeSongCursor(context, null, null);
final Cursor allSongsCursor = SongLoader.Companion.makeSongCursor(context, null, null);
final Cursor allSongsWithGenreCursor = makeAllSongsWithGenreCursor(context);
if (allSongsCursor == null || allSongsWithGenreCursor == null) {
@ -79,7 +79,7 @@ public class GenreLoader {
try {
return context.getContentResolver().query(
Genres.Members.getContentUri("external", genreId),
SongLoader.BASE_PROJECTION, SongLoader.BASE_SELECTION, null, PreferenceUtil.getInstance().getSongSortOrder());
SongLoader.Companion.getBASE_PROJECTION(), SongLoader.BASE_SELECTION, null, PreferenceUtil.getInstance().getSongSortOrder());
} catch (SecurityException e) {
return null;
}

View file

@ -21,13 +21,13 @@ public class LastAddedSongsLoader {
@NonNull
public static Observable<ArrayList<Song>> getLastAddedSongs(@NonNull Context context) {
return SongLoader.getSongs(makeLastAddedCursor(context));
return SongLoader.Companion.getSongs(makeLastAddedCursor(context));
}
public static Cursor makeLastAddedCursor(@NonNull final Context context) {
long cutoff = PreferenceUtil.getInstance().getLastAddedCutoff();
return SongLoader.makeSongCursor(
return SongLoader.Companion.makeSongCursor(
context,
MediaStore.Audio.Media.DATE_ADDED + ">?",
new String[]{String.valueOf(cutoff)},

View file

@ -14,7 +14,7 @@ public class SearchLoader {
ArrayList<Object> results = new ArrayList<>();
return Observable.create(e -> {
if (!TextUtils.isEmpty(query)) {
SongLoader.getSongs(context, query)
SongLoader.Companion.getSongs(context, query)
.subscribe(songs -> {
if (!songs.isEmpty()) {
results.add(context.getResources().getString(R.string.songs));

View file

@ -1,196 +0,0 @@
package code.name.monkey.retromusic.loaders;
import android.content.Context;
import android.database.Cursor;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.AudioColumns;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import code.name.monkey.retromusic.helper.ShuffleHelper;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.providers.BlacklistStore;
import code.name.monkey.retromusic.util.PreferenceUtil;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;
/**
* Created by hemanths on 10/08/17.
*/
public class SongLoader {
protected static final String BASE_SELECTION =
AudioColumns.IS_MUSIC + "=1" + " AND " + AudioColumns.TITLE + " != ''";
protected static final String[] BASE_PROJECTION = new String[]{
BaseColumns._ID,// 0
AudioColumns.TITLE,// 1
AudioColumns.TRACK,// 2
AudioColumns.YEAR,// 3
AudioColumns.DURATION,// 4
AudioColumns.DATA,// 5
AudioColumns.DATE_MODIFIED,// 6
AudioColumns.ALBUM_ID,// 7
AudioColumns.ALBUM,// 8
AudioColumns.ARTIST_ID,// 9
AudioColumns.ARTIST,// 10
};
@NonNull
public static Observable<ArrayList<Song>> getAllSongs(@NonNull Context context) {
Cursor cursor = makeSongCursor(context, null, null);
return getSongs(cursor);
}
@NonNull
public static Observable<ArrayList<Song>> getSongs(@NonNull final Context context,
final String query) {
Cursor cursor = makeSongCursor(context, AudioColumns.TITLE + " LIKE ?",
new String[]{"%" + query + "%"});
return getSongs(cursor);
}
@NonNull
public static Observable<ArrayList<Song>> getSongs(@Nullable final Cursor cursor) {
return Observable.create(e -> {
ArrayList<Song> songs = new ArrayList<>();
if (cursor != null && cursor.moveToFirst()) {
do {
songs.add(getSongFromCursorImpl(cursor));
} while (cursor.moveToNext());
}
if (cursor != null) {
cursor.close();
}
e.onNext(songs);
e.onComplete();
});
}
@NonNull
private static Song getSongFromCursorImpl(@NonNull Cursor cursor) {
final int id = cursor.getInt(0);
final String title = cursor.getString(1);
final int trackNumber = cursor.getInt(2);
final int year = cursor.getInt(3);
final long duration = cursor.getLong(4);
final String data = cursor.getString(5);
final long dateModified = cursor.getLong(6);
final int albumId = cursor.getInt(7);
final String albumName = cursor.getString(8);
final int artistId = cursor.getInt(9);
final String artistName = cursor.getString(10);
return new Song(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName,
artistId, artistName);
}
@Nullable
public static Cursor makeSongCursor(@NonNull final Context context,
@Nullable final String selection, final String[] selectionValues) {
return makeSongCursor(context, selection, selectionValues,
PreferenceUtil.getInstance().getSongSortOrder());
}
@Nullable
public static Cursor makeSongCursor(@NonNull final Context context, @Nullable String selection,
String[] selectionValues, final String sortOrder) {
if (selection != null && !selection.trim().equals("")) {
selection = BASE_SELECTION + " AND " + selection;
} else {
selection = BASE_SELECTION;
}
// Blacklist
ArrayList<String> paths = BlacklistStore.getInstance(context).getPaths();
if (!paths.isEmpty()) {
selection = generateBlacklistSelection(selection, paths.size());
selectionValues = addBlacklistSelectionValues(selectionValues, paths);
}
try {
return context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
BASE_PROJECTION, selection, selectionValues, sortOrder);
} catch (SecurityException e) {
return null;
}
}
private static String generateBlacklistSelection(String selection, int pathCount) {
StringBuilder newSelection = new StringBuilder(
selection != null && !selection.trim().equals("") ? selection + " AND " : "");
newSelection.append(AudioColumns.DATA + " NOT LIKE ?");
for (int i = 0; i < pathCount - 1; i++) {
newSelection.append(" AND " + AudioColumns.DATA + " NOT LIKE ?");
}
return newSelection.toString();
}
private static String[] addBlacklistSelectionValues(String[] selectionValues,
ArrayList<String> paths) {
if (selectionValues == null) {
selectionValues = new String[0];
}
String[] newSelectionValues = new String[selectionValues.length + paths.size()];
System.arraycopy(selectionValues, 0, newSelectionValues, 0, selectionValues.length);
for (int i = selectionValues.length; i < newSelectionValues.length; i++) {
newSelectionValues[i] = paths.get(i - selectionValues.length) + "%";
}
return newSelectionValues;
}
@NonNull
public static Observable<Song> getSong(@Nullable Cursor cursor) {
return Observable.create(e -> {
Song song;
if (cursor != null && cursor.moveToFirst()) {
song = getSongFromCursorImpl(cursor);
} else {
song = Song.EMPTY_SONG;
}
if (cursor != null) {
cursor.close();
}
e.onNext(song);
e.onComplete();
});
}
@NonNull
public static Observable<Song> getSong(@NonNull final Context context, final int queryId) {
Cursor cursor = makeSongCursor(context, AudioColumns._ID + "=?",
new String[]{String.valueOf(queryId)});
return getSong(cursor);
}
public static Observable<ArrayList<Song>> suggestSongs(@NonNull Context context) {
return SongLoader.getAllSongs(context)
.flatMap((Function<ArrayList<Song>, ObservableSource<ArrayList<Song>>>) songs -> {
ArrayList<Song> list = new ArrayList<>();
ShuffleHelper.makeShuffleList(songs, -1);
if (songs.size() > 9) {
list.addAll(songs.subList(0, 9));
}
return Observable.just(list);
});
/*.subscribe(songs -> {
ArrayList<Song> list = new ArrayList<>();
if (songs.isEmpty()) {
return;
}
ShuffleHelper.makeShuffleList(songs, -1);
if (songs.size() > 10) {
list.addAll(songs.subList(0, 10));
} else {
list.addAll(songs);
}
return;
});*/
}
}

View file

@ -0,0 +1,182 @@
package code.name.monkey.retromusic.loaders
import android.content.Context
import android.database.Cursor
import android.provider.BaseColumns
import android.provider.MediaStore
import android.provider.MediaStore.Audio.AudioColumns
import code.name.monkey.retromusic.helper.ShuffleHelper
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.providers.BlacklistStore
import code.name.monkey.retromusic.util.PreferenceUtil
import io.reactivex.Observable
import java.util.*
/**
* Created by hemanths on 10/08/17.
*/
open class SongLoader {
companion object {
const val BASE_SELECTION = AudioColumns.IS_MUSIC + "=1" + " AND " + AudioColumns.TITLE + " != ''"
val BASE_PROJECTION = arrayOf(BaseColumns._ID, // 0
AudioColumns.TITLE, // 1
AudioColumns.TRACK, // 2
AudioColumns.YEAR, // 3
AudioColumns.DURATION, // 4
AudioColumns.DATA, // 5
AudioColumns.DATE_MODIFIED, // 6
AudioColumns.ALBUM_ID, // 7
AudioColumns.ALBUM, // 8
AudioColumns.ARTIST_ID, // 9
AudioColumns.ARTIST)// 10
fun getAllSongs(context: Context): Observable<ArrayList<Song>> {
val cursor = makeSongCursor(context, null, null)
return getSongs(cursor)
}
fun getSongs(context: Context, query: String): Observable<ArrayList<Song>> {
val cursor = makeSongCursor(context, AudioColumns.TITLE + " LIKE ?", arrayOf("%$query%"))
return getSongs(cursor)
}
fun getSongs(cursor: Cursor?): Observable<ArrayList<Song>> {
return Observable.create { e ->
val songs = ArrayList<Song>()
if (cursor != null && cursor.moveToFirst()) {
do {
songs.add(getSongFromCursorImpl(cursor))
} while (cursor.moveToNext())
}
cursor?.close()
e.onNext(songs)
e.onComplete()
}
}
private fun getSongFromCursorImpl(cursor: Cursor): Song {
val id = cursor.getInt(0)
val title = cursor.getString(1)
val trackNumber = cursor.getInt(2)
val year = cursor.getInt(3)
val duration = cursor.getLong(4)
val data = cursor.getString(5)
val dateModified = cursor.getLong(6)
val albumId = cursor.getInt(7)
val albumName = cursor.getString(8)
val artistId = cursor.getInt(9)
val artistName = cursor.getString(10)
return Song(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName,
artistId, artistName)
}
@JvmOverloads
fun makeSongCursor(context: Context, selection: String?, selectionValues: Array<String>?, sortOrder: String = PreferenceUtil.getInstance().songSortOrder): Cursor? {
var selectionFinal = selection
var selectionValuesFinal = selectionValues
selectionFinal = if (selection != null && selection.trim { it <= ' ' } != "") {
"$BASE_SELECTION AND $selectionFinal"
} else {
BASE_SELECTION
}
// Blacklist
val paths = BlacklistStore.getInstance(context).paths
if (!paths.isEmpty()) {
selectionFinal = generateBlacklistSelection(selectionFinal, paths.size)
selectionValuesFinal = addBlacklistSelectionValues(selectionValuesFinal, paths)
}
try {
return context.contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
BASE_PROJECTION, selectionFinal, selectionValuesFinal, sortOrder)
} catch (e: SecurityException) {
return null
}
}
private fun generateBlacklistSelection(selection: String?, pathCount: Int): String {
val newSelection = StringBuilder(
if (selection != null && selection.trim { it <= ' ' } != "") "$selection AND " else "")
newSelection.append(AudioColumns.DATA + " NOT LIKE ?")
for (i in 0 until pathCount - 1) {
newSelection.append(" AND " + AudioColumns.DATA + " NOT LIKE ?")
}
return newSelection.toString()
}
private fun addBlacklistSelectionValues(selectionValues: Array<String>?,
paths: ArrayList<String>): Array<String>? {
var selectionValuesFinal = selectionValues
if (selectionValuesFinal == null) {
selectionValuesFinal = emptyArray()
}
val newSelectionValues = Array(selectionValuesFinal.size + paths.size) {
"n = $it"
}
System.arraycopy(selectionValuesFinal, 0, newSelectionValues, 0, selectionValuesFinal.size)
for (i in selectionValuesFinal.size until newSelectionValues.size) {
newSelectionValues[i] = paths[i - selectionValuesFinal.size] + "%"
}
return newSelectionValues
}
fun getSong(cursor: Cursor?): Observable<Song> {
return Observable.create { e ->
val song: Song
if (cursor != null && cursor.moveToFirst()) {
song = getSongFromCursorImpl(cursor)
} else {
song = Song.EMPTY_SONG
}
cursor?.close()
e.onNext(song)
e.onComplete()
}
}
fun getSong(context: Context, queryId: Int): Observable<Song> {
val cursor = makeSongCursor(context, AudioColumns._ID + "=?",
arrayOf(queryId.toString()))
return getSong(cursor)
}
fun suggestSongs(context: Context): Observable<ArrayList<Song>> {
return SongLoader.getAllSongs(context)
.flatMap {
val list = ArrayList<Song>()
ShuffleHelper.makeShuffleList(it, -1)
if (it.size > 9) {
list.addAll(it.subList(0, 9))
}
return@flatMap Observable.just(list)
}
/*.flatMap({ songs ->
val list = ArrayList<Song>()
ShuffleHelper.makeShuffleList(songs, -1)
if (songs.size > 9) {
list.addAll(songs.subList(0, 9))
}
Observable.just(list)
} as Function<ArrayList<Song>, ObservableSource<ArrayList<Song>>>)*/
/*.subscribe(songs -> {
ArrayList<Song> list = new ArrayList<>();
if (songs.isEmpty()) {
return;
}
ShuffleHelper.makeShuffleList(songs, -1);
if (songs.size() > 10) {
list.addAll(songs.subList(0, 10));
} else {
list.addAll(songs);
}
return;
});*/
}
}
}

View file

@ -23,12 +23,12 @@ public class TopAndRecentlyPlayedTracksLoader {
@NonNull
public static Observable<ArrayList<Song>> getRecentlyPlayedTracks(@NonNull Context context) {
return SongLoader.getSongs(makeRecentTracksCursorAndClearUpDatabase(context));
return SongLoader.Companion.getSongs(makeRecentTracksCursorAndClearUpDatabase(context));
}
@NonNull
public static Observable<ArrayList<Song>> getTopTracks(@NonNull Context context) {
return SongLoader.getSongs(makeTopTracksCursorAndClearUpDatabase(context));
return SongLoader.Companion.getSongs(makeTopTracksCursorAndClearUpDatabase(context));
}
@Nullable
@ -122,7 +122,7 @@ public class TopAndRecentlyPlayedTracksLoader {
selection.append(")");
// get a list of songs with the data given the selection statement
Cursor songCursor = SongLoader.makeSongCursor(context, selection.toString(), null);
Cursor songCursor = SongLoader.Companion.makeSongCursor(context, selection.toString(), null);
if (songCursor != null) {
// now return the wrapped TopTracksCursor to handle sorting given order
return new SortedLongCursor(songCursor, order, BaseColumns._ID);