Add Spotless
This commit is contained in:
parent
2af13a4e6c
commit
defcd86152
286 changed files with 15604 additions and 13757 deletions
|
@ -14,6 +14,8 @@
|
|||
|
||||
package code.name.monkey.retromusic.providers;
|
||||
|
||||
import static code.name.monkey.retromusic.service.MusicService.MEDIA_STORE_CHANGED;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -21,150 +23,164 @@ import android.database.Cursor;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.Environment;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import code.name.monkey.retromusic.util.FileUtil;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.util.FileUtil;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
|
||||
import static code.name.monkey.retromusic.service.MusicService.MEDIA_STORE_CHANGED;
|
||||
|
||||
public class BlacklistStore extends SQLiteOpenHelper {
|
||||
public static final String DATABASE_NAME = "blacklist.db";
|
||||
private static final int VERSION = 2;
|
||||
private static BlacklistStore sInstance = null;
|
||||
private Context context;
|
||||
public static final String DATABASE_NAME = "blacklist.db";
|
||||
private static final int VERSION = 2;
|
||||
private static BlacklistStore sInstance = null;
|
||||
private Context context;
|
||||
|
||||
public BlacklistStore(final Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
this.context = context;
|
||||
public BlacklistStore(final Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static synchronized BlacklistStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new BlacklistStore(context.getApplicationContext());
|
||||
if (!PreferenceUtil.INSTANCE.isInitializedBlacklist()) {
|
||||
// blacklisted by default
|
||||
sInstance.addPathImpl(
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS));
|
||||
sInstance.addPathImpl(
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS));
|
||||
sInstance.addPathImpl(
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES));
|
||||
|
||||
PreferenceUtil.INSTANCE.setInitializedBlacklist(true);
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS "
|
||||
+ BlacklistStoreColumns.NAME
|
||||
+ " ("
|
||||
+ BlacklistStoreColumns.PATH
|
||||
+ " STRING NOT NULL);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(
|
||||
@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + BlacklistStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + BlacklistStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public void addPath(File file) {
|
||||
addPathImpl(file);
|
||||
notifyMediaStoreChanged();
|
||||
}
|
||||
|
||||
private void addPathImpl(File file) {
|
||||
if (file == null || contains(file)) {
|
||||
return;
|
||||
}
|
||||
String path = FileUtil.safeGetCanonicalPath(file);
|
||||
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
try {
|
||||
// add the entry
|
||||
final ContentValues values = new ContentValues(1);
|
||||
values.put(BlacklistStoreColumns.PATH, path);
|
||||
database.insert(BlacklistStoreColumns.NAME, null, values);
|
||||
|
||||
database.setTransactionSuccessful();
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(File file) {
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
String path = FileUtil.safeGetCanonicalPath(file);
|
||||
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
Cursor cursor =
|
||||
database.query(
|
||||
BlacklistStoreColumns.NAME,
|
||||
new String[] {BlacklistStoreColumns.PATH},
|
||||
BlacklistStoreColumns.PATH + "=?",
|
||||
new String[] {path},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
boolean containsPath = cursor != null && cursor.moveToFirst();
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return containsPath;
|
||||
}
|
||||
|
||||
public void removePath(File file) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
String path = FileUtil.safeGetCanonicalPath(file);
|
||||
|
||||
database.delete(
|
||||
BlacklistStoreColumns.NAME, BlacklistStoreColumns.PATH + "=?", new String[] {path});
|
||||
|
||||
notifyMediaStoreChanged();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(BlacklistStoreColumns.NAME, null, null);
|
||||
|
||||
notifyMediaStoreChanged();
|
||||
}
|
||||
|
||||
private void notifyMediaStoreChanged() {
|
||||
context.sendBroadcast(new Intent(MEDIA_STORE_CHANGED));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<String> getPaths() {
|
||||
Cursor cursor =
|
||||
getReadableDatabase()
|
||||
.query(
|
||||
BlacklistStoreColumns.NAME,
|
||||
new String[] {BlacklistStoreColumns.PATH},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
ArrayList<String> paths = new ArrayList<>();
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
paths.add(cursor.getString(0));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static synchronized BlacklistStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new BlacklistStore(context.getApplicationContext());
|
||||
if (!PreferenceUtil.INSTANCE.isInitializedBlacklist()) {
|
||||
// blacklisted by default
|
||||
sInstance.addPathImpl(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS));
|
||||
sInstance.addPathImpl(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS));
|
||||
sInstance.addPathImpl(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES));
|
||||
if (cursor != null) cursor.close();
|
||||
return paths;
|
||||
}
|
||||
|
||||
PreferenceUtil.INSTANCE.setInitializedBlacklist(true);
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
public interface BlacklistStoreColumns {
|
||||
String NAME = "blacklist";
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE IF NOT EXISTS " + BlacklistStoreColumns.NAME + " (" + BlacklistStoreColumns.PATH + " STRING NOT NULL);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + BlacklistStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + BlacklistStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public void addPath(File file) {
|
||||
addPathImpl(file);
|
||||
notifyMediaStoreChanged();
|
||||
}
|
||||
|
||||
private void addPathImpl(File file) {
|
||||
if (file == null || contains(file)) {
|
||||
return;
|
||||
}
|
||||
String path = FileUtil.safeGetCanonicalPath(file);
|
||||
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
try {
|
||||
// add the entry
|
||||
final ContentValues values = new ContentValues(1);
|
||||
values.put(BlacklistStoreColumns.PATH, path);
|
||||
database.insert(BlacklistStoreColumns.NAME, null, values);
|
||||
|
||||
database.setTransactionSuccessful();
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(File file) {
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
String path = FileUtil.safeGetCanonicalPath(file);
|
||||
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
Cursor cursor = database.query(BlacklistStoreColumns.NAME,
|
||||
new String[]{BlacklistStoreColumns.PATH},
|
||||
BlacklistStoreColumns.PATH + "=?",
|
||||
new String[]{path},
|
||||
null, null, null, null);
|
||||
|
||||
boolean containsPath = cursor != null && cursor.moveToFirst();
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return containsPath;
|
||||
}
|
||||
|
||||
public void removePath(File file) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
String path = FileUtil.safeGetCanonicalPath(file);
|
||||
|
||||
database.delete(BlacklistStoreColumns.NAME,
|
||||
BlacklistStoreColumns.PATH + "=?",
|
||||
new String[]{path});
|
||||
|
||||
notifyMediaStoreChanged();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(BlacklistStoreColumns.NAME, null, null);
|
||||
|
||||
notifyMediaStoreChanged();
|
||||
}
|
||||
|
||||
private void notifyMediaStoreChanged() {
|
||||
context.sendBroadcast(new Intent(MEDIA_STORE_CHANGED));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<String> getPaths() {
|
||||
Cursor cursor = getReadableDatabase().query(BlacklistStoreColumns.NAME,
|
||||
new String[]{BlacklistStoreColumns.PATH},
|
||||
null, null, null, null, null);
|
||||
|
||||
ArrayList<String> paths = new ArrayList<>();
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
paths.add(cursor.getString(0));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
return paths;
|
||||
}
|
||||
|
||||
public interface BlacklistStoreColumns {
|
||||
String NAME = "blacklist";
|
||||
|
||||
String PATH = "path";
|
||||
}
|
||||
}
|
||||
String PATH = "path";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,148 +19,169 @@ import android.content.Context;
|
|||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class HistoryStore extends SQLiteOpenHelper {
|
||||
public static final String DATABASE_NAME = "history.db";
|
||||
private static final int MAX_ITEMS_IN_DB = 100;
|
||||
private static final int VERSION = 1;
|
||||
@Nullable
|
||||
private static HistoryStore sInstance = null;
|
||||
public static final String DATABASE_NAME = "history.db";
|
||||
private static final int MAX_ITEMS_IN_DB = 100;
|
||||
private static final int VERSION = 1;
|
||||
@Nullable private static HistoryStore sInstance = null;
|
||||
|
||||
public HistoryStore(final Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
public HistoryStore(final Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static synchronized HistoryStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new HistoryStore(context.getApplicationContext());
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS "
|
||||
+ RecentStoreColumns.NAME
|
||||
+ " ("
|
||||
+ RecentStoreColumns.ID
|
||||
+ " LONG NOT NULL,"
|
||||
+ RecentStoreColumns.TIME_PLAYED
|
||||
+ " LONG NOT NULL);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + RecentStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + RecentStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public void addSongId(final long songId) {
|
||||
if (songId == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static synchronized HistoryStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new HistoryStore(context.getApplicationContext());
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
try {
|
||||
// remove previous entries
|
||||
removeSongId(songId);
|
||||
|
||||
// add the entry
|
||||
final ContentValues values = new ContentValues(2);
|
||||
values.put(RecentStoreColumns.ID, songId);
|
||||
values.put(RecentStoreColumns.TIME_PLAYED, System.currentTimeMillis());
|
||||
database.insert(RecentStoreColumns.NAME, null, values);
|
||||
|
||||
// if our db is too large, delete the extra items
|
||||
Cursor oldest = null;
|
||||
try {
|
||||
oldest =
|
||||
database.query(
|
||||
RecentStoreColumns.NAME,
|
||||
new String[] {RecentStoreColumns.TIME_PLAYED},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
RecentStoreColumns.TIME_PLAYED + " ASC");
|
||||
|
||||
if (oldest != null && oldest.getCount() > MAX_ITEMS_IN_DB) {
|
||||
oldest.moveToPosition(oldest.getCount() - MAX_ITEMS_IN_DB);
|
||||
long timeOfRecordToKeep = oldest.getLong(0);
|
||||
|
||||
database.delete(
|
||||
RecentStoreColumns.NAME,
|
||||
RecentStoreColumns.TIME_PLAYED + " < ?",
|
||||
new String[] {String.valueOf(timeOfRecordToKeep)});
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE IF NOT EXISTS " + RecentStoreColumns.NAME + " ("
|
||||
+ RecentStoreColumns.ID + " LONG NOT NULL," + RecentStoreColumns.TIME_PLAYED
|
||||
+ " LONG NOT NULL);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + RecentStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + RecentStoreColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public void addSongId(final long songId) {
|
||||
if (songId == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
try {
|
||||
// remove previous entries
|
||||
removeSongId(songId);
|
||||
|
||||
// add the entry
|
||||
final ContentValues values = new ContentValues(2);
|
||||
values.put(RecentStoreColumns.ID, songId);
|
||||
values.put(RecentStoreColumns.TIME_PLAYED, System.currentTimeMillis());
|
||||
database.insert(RecentStoreColumns.NAME, null, values);
|
||||
|
||||
// if our db is too large, delete the extra items
|
||||
Cursor oldest = null;
|
||||
try {
|
||||
oldest = database.query(RecentStoreColumns.NAME,
|
||||
new String[]{RecentStoreColumns.TIME_PLAYED}, null, null, null, null,
|
||||
RecentStoreColumns.TIME_PLAYED + " ASC");
|
||||
|
||||
if (oldest != null && oldest.getCount() > MAX_ITEMS_IN_DB) {
|
||||
oldest.moveToPosition(oldest.getCount() - MAX_ITEMS_IN_DB);
|
||||
long timeOfRecordToKeep = oldest.getLong(0);
|
||||
|
||||
database.delete(RecentStoreColumns.NAME,
|
||||
RecentStoreColumns.TIME_PLAYED + " < ?",
|
||||
new String[]{String.valueOf(timeOfRecordToKeep)});
|
||||
|
||||
}
|
||||
} finally {
|
||||
if (oldest != null) {
|
||||
oldest.close();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
} finally {
|
||||
if (oldest != null) {
|
||||
oldest.close();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeSongId(final long songId) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(RecentStoreColumns.NAME, RecentStoreColumns.ID + " = ?", new String[]{
|
||||
String.valueOf(songId)
|
||||
});
|
||||
public void removeSongId(final long songId) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(
|
||||
RecentStoreColumns.NAME,
|
||||
RecentStoreColumns.ID + " = ?",
|
||||
new String[] {String.valueOf(songId)});
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(RecentStoreColumns.NAME, null, null);
|
||||
}
|
||||
|
||||
public boolean contains(long id) {
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
Cursor cursor =
|
||||
database.query(
|
||||
RecentStoreColumns.NAME,
|
||||
new String[] {RecentStoreColumns.ID},
|
||||
RecentStoreColumns.ID + "=?",
|
||||
new String[] {String.valueOf(id)},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
boolean containsId = cursor != null && cursor.moveToFirst();
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return containsId;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(RecentStoreColumns.NAME, null, null);
|
||||
}
|
||||
public Cursor queryRecentIds() {
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
return database.query(
|
||||
RecentStoreColumns.NAME,
|
||||
new String[] {RecentStoreColumns.ID},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
RecentStoreColumns.TIME_PLAYED + " DESC");
|
||||
}
|
||||
|
||||
public boolean contains(long id) {
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
Cursor cursor = database.query(RecentStoreColumns.NAME,
|
||||
new String[]{RecentStoreColumns.ID},
|
||||
RecentStoreColumns.ID + "=?",
|
||||
new String[]{String.valueOf(id)},
|
||||
null, null, null, null);
|
||||
public Cursor queryRecentIds(long cutoff) {
|
||||
final boolean noCutoffTime = (cutoff == 0);
|
||||
final boolean reverseOrder = (cutoff < 0);
|
||||
if (reverseOrder) cutoff = -cutoff;
|
||||
|
||||
boolean containsId = cursor != null && cursor.moveToFirst();
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return containsId;
|
||||
}
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
|
||||
public Cursor queryRecentIds() {
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
return database.query(RecentStoreColumns.NAME,
|
||||
new String[]{RecentStoreColumns.ID}, null, null, null, null,
|
||||
RecentStoreColumns.TIME_PLAYED + " DESC");
|
||||
}
|
||||
return database.query(
|
||||
RecentStoreColumns.NAME,
|
||||
new String[] {RecentStoreColumns.ID},
|
||||
noCutoffTime ? null : RecentStoreColumns.TIME_PLAYED + (reverseOrder ? "<?" : ">?"),
|
||||
noCutoffTime ? null : new String[] {String.valueOf(cutoff)},
|
||||
null,
|
||||
null,
|
||||
RecentStoreColumns.TIME_PLAYED + (reverseOrder ? " ASC" : " DESC"));
|
||||
}
|
||||
|
||||
public Cursor queryRecentIds(long cutoff) {
|
||||
final boolean noCutoffTime = (cutoff == 0);
|
||||
final boolean reverseOrder = (cutoff < 0);
|
||||
if (reverseOrder) cutoff = -cutoff;
|
||||
public interface RecentStoreColumns {
|
||||
String NAME = "recent_history";
|
||||
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
String ID = "song_id";
|
||||
|
||||
return database.query(RecentStoreColumns.NAME,
|
||||
new String[]{RecentStoreColumns.ID},
|
||||
noCutoffTime ? null : RecentStoreColumns.TIME_PLAYED + (reverseOrder ? "<?" : ">?"),
|
||||
noCutoffTime ? null : new String[]{String.valueOf(cutoff)},
|
||||
null, null,
|
||||
RecentStoreColumns.TIME_PLAYED + (reverseOrder ? " ASC" : " DESC"));
|
||||
}
|
||||
|
||||
public interface RecentStoreColumns {
|
||||
String NAME = "recent_history";
|
||||
|
||||
String ID = "song_id";
|
||||
|
||||
String TIME_PLAYED = "time_played";
|
||||
}
|
||||
String TIME_PLAYED = "time_played";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,195 +20,190 @@ import android.database.sqlite.SQLiteDatabase;
|
|||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.MediaStore.Audio.AudioColumns;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import code.name.monkey.retromusic.App;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.repository.RealSongRepository;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Andrew Neal, modified for Phonograph by Karim Abou Zeid
|
||||
* <p/>
|
||||
* This keeps track of the music playback and history state of the playback service
|
||||
* <p>This keeps track of the music playback and history state of the playback service
|
||||
*/
|
||||
public class MusicPlaybackQueueStore extends SQLiteOpenHelper {
|
||||
|
||||
public static final String DATABASE_NAME = "music_playback_state.db";
|
||||
public static final String DATABASE_NAME = "music_playback_state.db";
|
||||
|
||||
public static final String PLAYING_QUEUE_TABLE_NAME = "playing_queue";
|
||||
public static final String PLAYING_QUEUE_TABLE_NAME = "playing_queue";
|
||||
|
||||
public static final String ORIGINAL_PLAYING_QUEUE_TABLE_NAME = "original_playing_queue";
|
||||
public static final String ORIGINAL_PLAYING_QUEUE_TABLE_NAME = "original_playing_queue";
|
||||
|
||||
private static final int VERSION = 12;
|
||||
private static final int VERSION = 12;
|
||||
|
||||
@Nullable
|
||||
private static MusicPlaybackQueueStore sInstance = null;
|
||||
@Nullable private static MusicPlaybackQueueStore sInstance = null;
|
||||
|
||||
/**
|
||||
* Constructor of <code>MusicPlaybackState</code>
|
||||
*
|
||||
* @param context The {@link Context} to use
|
||||
*/
|
||||
public MusicPlaybackQueueStore(final @NonNull Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
/**
|
||||
* Constructor of <code>MusicPlaybackState</code>
|
||||
*
|
||||
* @param context The {@link Context} to use
|
||||
*/
|
||||
public MusicPlaybackQueueStore(final @NonNull Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context The {@link Context} to use
|
||||
* @return A new instance of this class.
|
||||
*/
|
||||
@NonNull
|
||||
public static synchronized MusicPlaybackQueueStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new MusicPlaybackQueueStore(context.getApplicationContext());
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
createTable(db, PLAYING_QUEUE_TABLE_NAME);
|
||||
createTable(db, ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Song> getSavedOriginalPlayingQueue() {
|
||||
return getQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Song> getSavedPlayingQueue() {
|
||||
return getQueue(PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// If we ever have downgrade, drop the table to be safe
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(
|
||||
@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
// not necessary yet
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public synchronized void saveQueues(
|
||||
@NonNull final List<Song> playingQueue, @NonNull final List<Song> originalPlayingQueue) {
|
||||
saveQueue(PLAYING_QUEUE_TABLE_NAME, playingQueue);
|
||||
saveQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME, originalPlayingQueue);
|
||||
}
|
||||
|
||||
private void createTable(@NonNull final SQLiteDatabase db, final String tableName) {
|
||||
//noinspection StringBufferReplaceableByString
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("CREATE TABLE IF NOT EXISTS ");
|
||||
builder.append(tableName);
|
||||
builder.append("(");
|
||||
|
||||
builder.append(BaseColumns._ID);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.TITLE);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.TRACK);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.YEAR);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.DURATION);
|
||||
builder.append(" LONG NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.DATA);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.DATE_MODIFIED);
|
||||
builder.append(" LONG NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ALBUM_ID);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ALBUM);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ARTIST_ID);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ARTIST);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.COMPOSER);
|
||||
builder.append(" STRING,");
|
||||
|
||||
builder.append("album_artist");
|
||||
builder.append(" STRING);");
|
||||
|
||||
db.execSQL(builder.toString());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Song> getQueue(@NonNull final String tableName) {
|
||||
Cursor cursor = getReadableDatabase().query(tableName, null, null, null, null, null, null);
|
||||
return new RealSongRepository(App.Companion.getContext()).songs(cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the existing database and saves the queue into the db so that when the app is restarted,
|
||||
* the tracks you were listening to is restored
|
||||
*
|
||||
* @param queue the queue to save
|
||||
*/
|
||||
private synchronized void saveQueue(final String tableName, @NonNull final List<Song> queue) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
try {
|
||||
database.delete(tableName, null, null);
|
||||
database.setTransactionSuccessful();
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context The {@link Context} to use
|
||||
* @return A new instance of this class.
|
||||
*/
|
||||
@NonNull
|
||||
public static synchronized MusicPlaybackQueueStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new MusicPlaybackQueueStore(context.getApplicationContext());
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
createTable(db, PLAYING_QUEUE_TABLE_NAME);
|
||||
createTable(db, ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Song> getSavedOriginalPlayingQueue() {
|
||||
return getQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Song> getSavedPlayingQueue() {
|
||||
return getQueue(PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// If we ever have downgrade, drop the table to be safe
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
// not necessary yet
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public synchronized void saveQueues(@NonNull final List<Song> playingQueue,
|
||||
@NonNull final List<Song> originalPlayingQueue) {
|
||||
saveQueue(PLAYING_QUEUE_TABLE_NAME, playingQueue);
|
||||
saveQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME, originalPlayingQueue);
|
||||
}
|
||||
|
||||
private void createTable(@NonNull final SQLiteDatabase db, final String tableName) {
|
||||
//noinspection StringBufferReplaceableByString
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("CREATE TABLE IF NOT EXISTS ");
|
||||
builder.append(tableName);
|
||||
builder.append("(");
|
||||
|
||||
builder.append(BaseColumns._ID);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.TITLE);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.TRACK);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.YEAR);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.DURATION);
|
||||
builder.append(" LONG NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.DATA);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.DATE_MODIFIED);
|
||||
builder.append(" LONG NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ALBUM_ID);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ALBUM);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ARTIST_ID);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.ARTIST);
|
||||
builder.append(" STRING NOT NULL,");
|
||||
|
||||
builder.append(AudioColumns.COMPOSER);
|
||||
builder.append(" STRING,");
|
||||
|
||||
builder.append("album_artist");
|
||||
builder.append(" STRING);");
|
||||
|
||||
db.execSQL(builder.toString());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Song> getQueue(@NonNull final String tableName) {
|
||||
Cursor cursor = getReadableDatabase().query(tableName, null,
|
||||
null, null, null, null, null);
|
||||
return new RealSongRepository(App.Companion.getContext()).songs(cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the existing database and saves the queue into the db so that when the
|
||||
* app is restarted, the tracks you were listening to is restored
|
||||
*
|
||||
* @param queue the queue to save
|
||||
*/
|
||||
private synchronized void saveQueue(final String tableName, @NonNull final List<Song> queue) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
try {
|
||||
database.delete(tableName, null, null);
|
||||
database.setTransactionSuccessful();
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
}
|
||||
|
||||
final int NUM_PROCESS = 20;
|
||||
int position = 0;
|
||||
while (position < queue.size()) {
|
||||
database.beginTransaction();
|
||||
try {
|
||||
for (int i = position; i < queue.size() && i < position + NUM_PROCESS; i++) {
|
||||
Song song = queue.get(i);
|
||||
ContentValues values = new ContentValues(4);
|
||||
|
||||
values.put(BaseColumns._ID, song.getId());
|
||||
values.put(AudioColumns.TITLE, song.getTitle());
|
||||
values.put(AudioColumns.TRACK, song.getTrackNumber());
|
||||
values.put(AudioColumns.YEAR, song.getYear());
|
||||
values.put(AudioColumns.DURATION, song.getDuration());
|
||||
values.put(AudioColumns.DATA, song.getData());
|
||||
values.put(AudioColumns.DATE_MODIFIED, song.getDateModified());
|
||||
values.put(AudioColumns.ALBUM_ID, song.getAlbumId());
|
||||
values.put(AudioColumns.ALBUM, song.getAlbumName());
|
||||
values.put(AudioColumns.ARTIST_ID, song.getArtistId());
|
||||
values.put(AudioColumns.ARTIST, song.getArtistName());
|
||||
values.put(AudioColumns.COMPOSER, song.getComposer());
|
||||
|
||||
database.insert(tableName, null, values);
|
||||
}
|
||||
database.setTransactionSuccessful();
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
position += NUM_PROCESS;
|
||||
}
|
||||
final int NUM_PROCESS = 20;
|
||||
int position = 0;
|
||||
while (position < queue.size()) {
|
||||
database.beginTransaction();
|
||||
try {
|
||||
for (int i = position; i < queue.size() && i < position + NUM_PROCESS; i++) {
|
||||
Song song = queue.get(i);
|
||||
ContentValues values = new ContentValues(4);
|
||||
|
||||
values.put(BaseColumns._ID, song.getId());
|
||||
values.put(AudioColumns.TITLE, song.getTitle());
|
||||
values.put(AudioColumns.TRACK, song.getTrackNumber());
|
||||
values.put(AudioColumns.YEAR, song.getYear());
|
||||
values.put(AudioColumns.DURATION, song.getDuration());
|
||||
values.put(AudioColumns.DATA, song.getData());
|
||||
values.put(AudioColumns.DATE_MODIFIED, song.getDateModified());
|
||||
values.put(AudioColumns.ALBUM_ID, song.getAlbumId());
|
||||
values.put(AudioColumns.ALBUM, song.getAlbumName());
|
||||
values.put(AudioColumns.ARTIST_ID, song.getArtistId());
|
||||
values.put(AudioColumns.ARTIST, song.getArtistName());
|
||||
values.put(AudioColumns.COMPOSER, song.getComposer());
|
||||
|
||||
database.insert(tableName, null, values);
|
||||
}
|
||||
database.setTransactionSuccessful();
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
position += NUM_PROCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,383 +21,400 @@ import android.database.sqlite.SQLiteDatabase;
|
|||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This database tracks the number of play counts for an individual song. This is used to drive
|
||||
* the top played tracks as well as the playlist images
|
||||
* This database tracks the number of play counts for an individual song. This is used to drive the
|
||||
* top played tracks as well as the playlist images
|
||||
*/
|
||||
public class SongPlayCountStore extends SQLiteOpenHelper {
|
||||
public static final String DATABASE_NAME = "song_play_count.db";
|
||||
private static final int VERSION = 3;
|
||||
// how many weeks worth of playback to track
|
||||
private static final int NUM_WEEKS = 52;
|
||||
@Nullable
|
||||
private static SongPlayCountStore sInstance = null;
|
||||
// interpolator curve applied for measuring the curve
|
||||
@NonNull
|
||||
private static Interpolator sInterpolator = new AccelerateInterpolator(1.5f);
|
||||
// how high to multiply the interpolation curve
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static int INTERPOLATOR_HEIGHT = 50;
|
||||
public static final String DATABASE_NAME = "song_play_count.db";
|
||||
private static final int VERSION = 3;
|
||||
// how many weeks worth of playback to track
|
||||
private static final int NUM_WEEKS = 52;
|
||||
@Nullable private static SongPlayCountStore sInstance = null;
|
||||
// interpolator curve applied for measuring the curve
|
||||
@NonNull private static Interpolator sInterpolator = new AccelerateInterpolator(1.5f);
|
||||
// how high to multiply the interpolation curve
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static int INTERPOLATOR_HEIGHT = 50;
|
||||
|
||||
// how high the base value is. The ratio of the Height to Base is what really matters
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static int INTERPOLATOR_BASE = 25;
|
||||
// how high the base value is. The ratio of the Height to Base is what really matters
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static int INTERPOLATOR_BASE = 25;
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static int ONE_WEEK_IN_MS = 1000 * 60 * 60 * 24 * 7;
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static int ONE_WEEK_IN_MS = 1000 * 60 * 60 * 24 * 7;
|
||||
|
||||
@NonNull
|
||||
private static String WHERE_ID_EQUALS = SongPlayCountColumns.ID + "=?";
|
||||
@NonNull private static String WHERE_ID_EQUALS = SongPlayCountColumns.ID + "=?";
|
||||
|
||||
// number of weeks since epoch time
|
||||
private int mNumberOfWeeksSinceEpoch;
|
||||
// number of weeks since epoch time
|
||||
private int mNumberOfWeeksSinceEpoch;
|
||||
|
||||
// used to track if we've walked through the db and updated all the rows
|
||||
private boolean mDatabaseUpdated;
|
||||
// used to track if we've walked through the db and updated all the rows
|
||||
private boolean mDatabaseUpdated;
|
||||
|
||||
public SongPlayCountStore(final Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
public SongPlayCountStore(final Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
|
||||
long msSinceEpoch = System.currentTimeMillis();
|
||||
mNumberOfWeeksSinceEpoch = (int) (msSinceEpoch / ONE_WEEK_IN_MS);
|
||||
long msSinceEpoch = System.currentTimeMillis();
|
||||
mNumberOfWeeksSinceEpoch = (int) (msSinceEpoch / ONE_WEEK_IN_MS);
|
||||
|
||||
mDatabaseUpdated = false;
|
||||
mDatabaseUpdated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context The {@link Context} to use
|
||||
* @return A new instance of this class.
|
||||
*/
|
||||
@NonNull
|
||||
public static synchronized SongPlayCountStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SongPlayCountStore(context.getApplicationContext());
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the score of the song given the play counts
|
||||
*
|
||||
* @param playCounts an array of the # of times a song has been played for each week where
|
||||
* playCounts[N] is the # of times it was played N weeks ago
|
||||
* @return the score
|
||||
*/
|
||||
private static float calculateScore(@Nullable final int[] playCounts) {
|
||||
if (playCounts == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context The {@link Context} to use
|
||||
* @return A new instance of this class.
|
||||
*/
|
||||
@NonNull
|
||||
public static synchronized SongPlayCountStore getInstance(@NonNull final Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SongPlayCountStore(context.getApplicationContext());
|
||||
float score = 0;
|
||||
for (int i = 0; i < Math.min(playCounts.length, NUM_WEEKS); i++) {
|
||||
score += playCounts[i] * getScoreMultiplierForWeek(i);
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the column name for each week #
|
||||
*
|
||||
* @param week number
|
||||
* @return the column name
|
||||
*/
|
||||
@NonNull
|
||||
private static String getColumnNameForWeek(final int week) {
|
||||
return SongPlayCountColumns.WEEK_PLAY_COUNT + week;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the score multiplier for each week
|
||||
*
|
||||
* @param week number
|
||||
* @return the multiplier to apply
|
||||
*/
|
||||
private static float getScoreMultiplierForWeek(final int week) {
|
||||
return sInterpolator.getInterpolation(1 - (week / (float) NUM_WEEKS)) * INTERPOLATOR_HEIGHT
|
||||
+ INTERPOLATOR_BASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* For some performance gain, return a static value for the column index for a week WARNING: This
|
||||
* function assumes you have selected all columns for it to work
|
||||
*
|
||||
* @param week number
|
||||
* @return column index of that week
|
||||
*/
|
||||
private static int getColumnIndexForWeek(final int week) {
|
||||
// ID, followed by the weeks columns
|
||||
return 1 + week;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
// create the play count table
|
||||
// WARNING: If you change the order of these columns
|
||||
// please update getColumnIndexForWeek
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("CREATE TABLE IF NOT EXISTS ");
|
||||
builder.append(SongPlayCountColumns.NAME);
|
||||
builder.append("(");
|
||||
builder.append(SongPlayCountColumns.ID);
|
||||
builder.append(" INT UNIQUE,");
|
||||
|
||||
for (int i = 0; i < NUM_WEEKS; i++) {
|
||||
builder.append(getColumnNameForWeek(i));
|
||||
builder.append(" INT DEFAULT 0,");
|
||||
}
|
||||
|
||||
builder.append(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX);
|
||||
builder.append(" INT NOT NULL,");
|
||||
|
||||
builder.append(SongPlayCountColumns.PLAY_COUNT_SCORE);
|
||||
builder.append(" REAL DEFAULT 0);");
|
||||
|
||||
db.execSQL(builder.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(
|
||||
@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + SongPlayCountColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// If we ever have downgrade, drop the table to be safe
|
||||
db.execSQL("DROP TABLE IF EXISTS " + SongPlayCountColumns.NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the play count of a song by 1
|
||||
*
|
||||
* @param songId The song id to increase the play count
|
||||
*/
|
||||
public void bumpPlayCount(final long songId) {
|
||||
if (songId == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
updateExistingRow(database, songId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a new entry that indicates a song has been played once as well as its score
|
||||
*
|
||||
* @param database a write able database
|
||||
* @param songId the id of the track
|
||||
*/
|
||||
private void createNewPlayedEntry(@NonNull final SQLiteDatabase database, final long songId) {
|
||||
// no row exists, create a new one
|
||||
float newScore = getScoreMultiplierForWeek(0);
|
||||
int newPlayCount = 1;
|
||||
|
||||
final ContentValues values = new ContentValues(3);
|
||||
values.put(SongPlayCountColumns.ID, songId);
|
||||
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, newScore);
|
||||
values.put(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX, mNumberOfWeeksSinceEpoch);
|
||||
values.put(getColumnNameForWeek(0), newPlayCount);
|
||||
|
||||
database.insert(SongPlayCountColumns.NAME, null, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will take a song entry and update it to the latest week and increase the count
|
||||
* for the current week by 1 if necessary
|
||||
*
|
||||
* @param database a writeable database
|
||||
* @param id the id of the track to bump
|
||||
* @param bumpCount whether to bump the current's week play count by 1 and adjust the score
|
||||
*/
|
||||
private void updateExistingRow(
|
||||
@NonNull final SQLiteDatabase database, final long id, boolean bumpCount) {
|
||||
String stringId = String.valueOf(id);
|
||||
|
||||
// begin the transaction
|
||||
database.beginTransaction();
|
||||
|
||||
// get the cursor of this content inside the transaction
|
||||
final Cursor cursor =
|
||||
database.query(
|
||||
SongPlayCountColumns.NAME,
|
||||
null,
|
||||
WHERE_ID_EQUALS,
|
||||
new String[] {stringId},
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
// if we have a result
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// figure how many weeks since we last updated
|
||||
int lastUpdatedIndex = cursor.getColumnIndex(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX);
|
||||
int lastUpdatedWeek = cursor.getInt(lastUpdatedIndex);
|
||||
int weekDiff = mNumberOfWeeksSinceEpoch - lastUpdatedWeek;
|
||||
|
||||
// if it's more than the number of weeks we track, delete it and create a new entry
|
||||
if (Math.abs(weekDiff) >= NUM_WEEKS) {
|
||||
// this entry needs to be dropped since it is too outdated
|
||||
deleteEntry(database, stringId);
|
||||
if (bumpCount) {
|
||||
createNewPlayedEntry(database, id);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
} else if (weekDiff != 0) {
|
||||
// else, shift the weeks
|
||||
int[] playCounts = new int[NUM_WEEKS];
|
||||
|
||||
/**
|
||||
* Calculates the score of the song given the play counts
|
||||
*
|
||||
* @param playCounts an array of the # of times a song has been played for each week
|
||||
* where playCounts[N] is the # of times it was played N weeks ago
|
||||
* @return the score
|
||||
*/
|
||||
private static float calculateScore(@Nullable final int[] playCounts) {
|
||||
if (playCounts == null) {
|
||||
return 0;
|
||||
if (weekDiff > 0) {
|
||||
// time is shifted forwards
|
||||
for (int i = 0; i < NUM_WEEKS - weekDiff; i++) {
|
||||
playCounts[i + weekDiff] = cursor.getInt(getColumnIndexForWeek(i));
|
||||
}
|
||||
} else if (weekDiff < 0) {
|
||||
// time is shifted backwards (by user) - nor typical behavior but we
|
||||
// will still handle it
|
||||
|
||||
// since weekDiff is -ve, NUM_WEEKS + weekDiff is the real # of weeks we have to
|
||||
// transfer. Then we transfer the old week i - weekDiff to week i
|
||||
// for example if the user shifted back 2 weeks, ie -2, then for 0 to
|
||||
// NUM_WEEKS + (-2) we set the new week i = old week i - (-2) or i+2
|
||||
for (int i = 0; i < NUM_WEEKS + weekDiff; i++) {
|
||||
playCounts[i] = cursor.getInt(getColumnIndexForWeek(i - weekDiff));
|
||||
}
|
||||
}
|
||||
|
||||
float score = 0;
|
||||
for (int i = 0; i < Math.min(playCounts.length, NUM_WEEKS); i++) {
|
||||
score += playCounts[i] * getScoreMultiplierForWeek(i);
|
||||
// bump the count
|
||||
if (bumpCount) {
|
||||
playCounts[0]++;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
float score = calculateScore(playCounts);
|
||||
|
||||
/**
|
||||
* Gets the column name for each week #
|
||||
*
|
||||
* @param week number
|
||||
* @return the column name
|
||||
*/
|
||||
@NonNull
|
||||
private static String getColumnNameForWeek(final int week) {
|
||||
return SongPlayCountColumns.WEEK_PLAY_COUNT + week;
|
||||
}
|
||||
// if the score is non-existant, then delete it
|
||||
if (score < .01f) {
|
||||
deleteEntry(database, stringId);
|
||||
} else {
|
||||
// create the content values
|
||||
ContentValues values = new ContentValues(NUM_WEEKS + 2);
|
||||
values.put(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX, mNumberOfWeeksSinceEpoch);
|
||||
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, score);
|
||||
|
||||
/**
|
||||
* Gets the score multiplier for each week
|
||||
*
|
||||
* @param week number
|
||||
* @return the multiplier to apply
|
||||
*/
|
||||
private static float getScoreMultiplierForWeek(final int week) {
|
||||
return sInterpolator.getInterpolation(1 - (week / (float) NUM_WEEKS)) * INTERPOLATOR_HEIGHT
|
||||
+ INTERPOLATOR_BASE;
|
||||
}
|
||||
for (int i = 0; i < NUM_WEEKS; i++) {
|
||||
values.put(getColumnNameForWeek(i), playCounts[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* For some performance gain, return a static value for the column index for a week
|
||||
* WARNING: This function assumes you have selected all columns for it to work
|
||||
*
|
||||
* @param week number
|
||||
* @return column index of that week
|
||||
*/
|
||||
private static int getColumnIndexForWeek(final int week) {
|
||||
// ID, followed by the weeks columns
|
||||
return 1 + week;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
// create the play count table
|
||||
// WARNING: If you change the order of these columns
|
||||
// please update getColumnIndexForWeek
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("CREATE TABLE IF NOT EXISTS ");
|
||||
builder.append(SongPlayCountColumns.NAME);
|
||||
builder.append("(");
|
||||
builder.append(SongPlayCountColumns.ID);
|
||||
builder.append(" INT UNIQUE,");
|
||||
|
||||
for (int i = 0; i < NUM_WEEKS; i++) {
|
||||
builder.append(getColumnNameForWeek(i));
|
||||
builder.append(" INT DEFAULT 0,");
|
||||
// update the entry
|
||||
database.update(
|
||||
SongPlayCountColumns.NAME, values, WHERE_ID_EQUALS, new String[] {stringId});
|
||||
}
|
||||
} else if (bumpCount) {
|
||||
// else no shifting, just update the scores
|
||||
ContentValues values = new ContentValues(2);
|
||||
|
||||
builder.append(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX);
|
||||
builder.append(" INT NOT NULL,");
|
||||
// increase the score by a single score amount
|
||||
int scoreIndex = cursor.getColumnIndex(SongPlayCountColumns.PLAY_COUNT_SCORE);
|
||||
float score = cursor.getFloat(scoreIndex) + getScoreMultiplierForWeek(0);
|
||||
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, score);
|
||||
|
||||
builder.append(SongPlayCountColumns.PLAY_COUNT_SCORE);
|
||||
builder.append(" REAL DEFAULT 0);");
|
||||
// increase the play count by 1
|
||||
values.put(getColumnNameForWeek(0), cursor.getInt(getColumnIndexForWeek(0)) + 1);
|
||||
|
||||
db.execSQL(builder.toString());
|
||||
// update the entry
|
||||
database.update(
|
||||
SongPlayCountColumns.NAME, values, WHERE_ID_EQUALS, new String[] {stringId});
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
} else if (bumpCount) {
|
||||
// if we have no existing results, create a new one
|
||||
createNewPlayedEntry(database, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + SongPlayCountColumns.NAME);
|
||||
onCreate(db);
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(SongPlayCountColumns.NAME, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a cursor containing the top songs played. Note this only returns songs that have been
|
||||
* played at least once in the past NUM_WEEKS
|
||||
*
|
||||
* @param numResults number of results to limit by. If <= 0 it returns all results
|
||||
* @return the top tracks
|
||||
*/
|
||||
public Cursor getTopPlayedResults(int numResults) {
|
||||
updateResults();
|
||||
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
return database.query(
|
||||
SongPlayCountColumns.NAME,
|
||||
new String[] {SongPlayCountColumns.ID},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
SongPlayCountColumns.PLAY_COUNT_SCORE + " DESC",
|
||||
(numResults <= 0 ? null : String.valueOf(numResults)));
|
||||
}
|
||||
|
||||
/**
|
||||
* This updates all the results for the getTopPlayedResults so that we can get an accurate list of
|
||||
* the top played results
|
||||
*/
|
||||
private synchronized void updateResults() {
|
||||
if (mDatabaseUpdated) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// If we ever have downgrade, drop the table to be safe
|
||||
db.execSQL("DROP TABLE IF EXISTS " + SongPlayCountColumns.NAME);
|
||||
onCreate(db);
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
|
||||
database.beginTransaction();
|
||||
|
||||
int oldestWeekWeCareAbout = mNumberOfWeeksSinceEpoch - NUM_WEEKS + 1;
|
||||
// delete rows we don't care about anymore
|
||||
database.delete(
|
||||
SongPlayCountColumns.NAME,
|
||||
SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX + " < " + oldestWeekWeCareAbout,
|
||||
null);
|
||||
|
||||
// get the remaining rows
|
||||
Cursor cursor =
|
||||
database.query(
|
||||
SongPlayCountColumns.NAME,
|
||||
new String[] {SongPlayCountColumns.ID},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// for each row, update it
|
||||
do {
|
||||
updateExistingRow(database, cursor.getLong(0), false);
|
||||
} while (cursor.moveToNext());
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the play count of a song by 1
|
||||
*
|
||||
* @param songId The song id to increase the play count
|
||||
*/
|
||||
public void bumpPlayCount(final long songId) {
|
||||
if (songId == -1) {
|
||||
return;
|
||||
}
|
||||
mDatabaseUpdated = true;
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
}
|
||||
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
updateExistingRow(database, songId, true);
|
||||
}
|
||||
/** @param songId The song Id to remove. */
|
||||
public void removeItem(final long songId) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
deleteEntry(database, String.valueOf(songId));
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a new entry that indicates a song has been played once as well as its score
|
||||
*
|
||||
* @param database a write able database
|
||||
* @param songId the id of the track
|
||||
*/
|
||||
private void createNewPlayedEntry(@NonNull final SQLiteDatabase database, final long songId) {
|
||||
// no row exists, create a new one
|
||||
float newScore = getScoreMultiplierForWeek(0);
|
||||
int newPlayCount = 1;
|
||||
/**
|
||||
* Deletes the entry
|
||||
*
|
||||
* @param database database to use
|
||||
* @param stringId id to delete
|
||||
*/
|
||||
private void deleteEntry(@NonNull final SQLiteDatabase database, final String stringId) {
|
||||
database.delete(SongPlayCountColumns.NAME, WHERE_ID_EQUALS, new String[] {stringId});
|
||||
}
|
||||
|
||||
final ContentValues values = new ContentValues(3);
|
||||
values.put(SongPlayCountColumns.ID, songId);
|
||||
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, newScore);
|
||||
values.put(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX, mNumberOfWeeksSinceEpoch);
|
||||
values.put(getColumnNameForWeek(0), newPlayCount);
|
||||
public interface SongPlayCountColumns {
|
||||
|
||||
database.insert(SongPlayCountColumns.NAME, null, values);
|
||||
}
|
||||
String NAME = "song_play_count";
|
||||
|
||||
/**
|
||||
* This function will take a song entry and update it to the latest week and increase the count
|
||||
* for the current week by 1 if necessary
|
||||
*
|
||||
* @param database a writeable database
|
||||
* @param id the id of the track to bump
|
||||
* @param bumpCount whether to bump the current's week play count by 1 and adjust the score
|
||||
*/
|
||||
private void updateExistingRow(@NonNull final SQLiteDatabase database, final long id, boolean bumpCount) {
|
||||
String stringId = String.valueOf(id);
|
||||
String ID = "song_id";
|
||||
|
||||
// begin the transaction
|
||||
database.beginTransaction();
|
||||
String WEEK_PLAY_COUNT = "week";
|
||||
|
||||
// get the cursor of this content inside the transaction
|
||||
final Cursor cursor = database.query(SongPlayCountColumns.NAME, null, WHERE_ID_EQUALS,
|
||||
new String[]{stringId}, null, null, null);
|
||||
String LAST_UPDATED_WEEK_INDEX = "week_index";
|
||||
|
||||
// if we have a result
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// figure how many weeks since we last updated
|
||||
int lastUpdatedIndex = cursor.getColumnIndex(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX);
|
||||
int lastUpdatedWeek = cursor.getInt(lastUpdatedIndex);
|
||||
int weekDiff = mNumberOfWeeksSinceEpoch - lastUpdatedWeek;
|
||||
|
||||
// if it's more than the number of weeks we track, delete it and create a new entry
|
||||
if (Math.abs(weekDiff) >= NUM_WEEKS) {
|
||||
// this entry needs to be dropped since it is too outdated
|
||||
deleteEntry(database, stringId);
|
||||
if (bumpCount) {
|
||||
createNewPlayedEntry(database, id);
|
||||
}
|
||||
} else if (weekDiff != 0) {
|
||||
// else, shift the weeks
|
||||
int[] playCounts = new int[NUM_WEEKS];
|
||||
|
||||
if (weekDiff > 0) {
|
||||
// time is shifted forwards
|
||||
for (int i = 0; i < NUM_WEEKS - weekDiff; i++) {
|
||||
playCounts[i + weekDiff] = cursor.getInt(getColumnIndexForWeek(i));
|
||||
}
|
||||
} else if (weekDiff < 0) {
|
||||
// time is shifted backwards (by user) - nor typical behavior but we
|
||||
// will still handle it
|
||||
|
||||
// since weekDiff is -ve, NUM_WEEKS + weekDiff is the real # of weeks we have to
|
||||
// transfer. Then we transfer the old week i - weekDiff to week i
|
||||
// for example if the user shifted back 2 weeks, ie -2, then for 0 to
|
||||
// NUM_WEEKS + (-2) we set the new week i = old week i - (-2) or i+2
|
||||
for (int i = 0; i < NUM_WEEKS + weekDiff; i++) {
|
||||
playCounts[i] = cursor.getInt(getColumnIndexForWeek(i - weekDiff));
|
||||
}
|
||||
}
|
||||
|
||||
// bump the count
|
||||
if (bumpCount) {
|
||||
playCounts[0]++;
|
||||
}
|
||||
|
||||
float score = calculateScore(playCounts);
|
||||
|
||||
// if the score is non-existant, then delete it
|
||||
if (score < .01f) {
|
||||
deleteEntry(database, stringId);
|
||||
} else {
|
||||
// create the content values
|
||||
ContentValues values = new ContentValues(NUM_WEEKS + 2);
|
||||
values.put(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX, mNumberOfWeeksSinceEpoch);
|
||||
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, score);
|
||||
|
||||
for (int i = 0; i < NUM_WEEKS; i++) {
|
||||
values.put(getColumnNameForWeek(i), playCounts[i]);
|
||||
}
|
||||
|
||||
// update the entry
|
||||
database.update(SongPlayCountColumns.NAME, values, WHERE_ID_EQUALS,
|
||||
new String[]{stringId});
|
||||
}
|
||||
} else if (bumpCount) {
|
||||
// else no shifting, just update the scores
|
||||
ContentValues values = new ContentValues(2);
|
||||
|
||||
// increase the score by a single score amount
|
||||
int scoreIndex = cursor.getColumnIndex(SongPlayCountColumns.PLAY_COUNT_SCORE);
|
||||
float score = cursor.getFloat(scoreIndex) + getScoreMultiplierForWeek(0);
|
||||
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, score);
|
||||
|
||||
// increase the play count by 1
|
||||
values.put(getColumnNameForWeek(0), cursor.getInt(getColumnIndexForWeek(0)) + 1);
|
||||
|
||||
// update the entry
|
||||
database.update(SongPlayCountColumns.NAME, values, WHERE_ID_EQUALS,
|
||||
new String[]{stringId});
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
} else if (bumpCount) {
|
||||
// if we have no existing results, create a new one
|
||||
createNewPlayedEntry(database, id);
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
database.delete(SongPlayCountColumns.NAME, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a cursor containing the top songs played. Note this only returns songs that have been
|
||||
* played at least once in the past NUM_WEEKS
|
||||
*
|
||||
* @param numResults number of results to limit by. If <= 0 it returns all results
|
||||
* @return the top tracks
|
||||
*/
|
||||
public Cursor getTopPlayedResults(int numResults) {
|
||||
updateResults();
|
||||
|
||||
final SQLiteDatabase database = getReadableDatabase();
|
||||
return database.query(SongPlayCountColumns.NAME, new String[]{SongPlayCountColumns.ID},
|
||||
null, null, null, null, SongPlayCountColumns.PLAY_COUNT_SCORE + " DESC",
|
||||
(numResults <= 0 ? null : String.valueOf(numResults)));
|
||||
}
|
||||
|
||||
/**
|
||||
* This updates all the results for the getTopPlayedResults so that we can get an
|
||||
* accurate list of the top played results
|
||||
*/
|
||||
private synchronized void updateResults() {
|
||||
if (mDatabaseUpdated) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
|
||||
database.beginTransaction();
|
||||
|
||||
int oldestWeekWeCareAbout = mNumberOfWeeksSinceEpoch - NUM_WEEKS + 1;
|
||||
// delete rows we don't care about anymore
|
||||
database.delete(SongPlayCountColumns.NAME, SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX
|
||||
+ " < " + oldestWeekWeCareAbout, null);
|
||||
|
||||
// get the remaining rows
|
||||
Cursor cursor = database.query(SongPlayCountColumns.NAME,
|
||||
new String[]{SongPlayCountColumns.ID},
|
||||
null, null, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// for each row, update it
|
||||
do {
|
||||
updateExistingRow(database, cursor.getLong(0), false);
|
||||
} while (cursor.moveToNext());
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
mDatabaseUpdated = true;
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param songId The song Id to remove.
|
||||
*/
|
||||
public void removeItem(final long songId) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
deleteEntry(database, String.valueOf(songId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the entry
|
||||
*
|
||||
* @param database database to use
|
||||
* @param stringId id to delete
|
||||
*/
|
||||
private void deleteEntry(@NonNull final SQLiteDatabase database, final String stringId) {
|
||||
database.delete(SongPlayCountColumns.NAME, WHERE_ID_EQUALS, new String[]{stringId});
|
||||
}
|
||||
|
||||
public interface SongPlayCountColumns {
|
||||
|
||||
String NAME = "song_play_count";
|
||||
|
||||
String ID = "song_id";
|
||||
|
||||
String WEEK_PLAY_COUNT = "week";
|
||||
|
||||
String LAST_UPDATED_WEEK_INDEX = "week_index";
|
||||
|
||||
String PLAY_COUNT_SCORE = "play_count_score";
|
||||
}
|
||||
String PLAY_COUNT_SCORE = "play_count_score";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue