diff options
6 files changed, 153 insertions, 18 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java index 6d25bc0b..d824a236 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java @@ -77,6 +77,7 @@ import github.daneren2005.dsub.util.MenuUtil; import github.daneren2005.dsub.util.ProgressListener; import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.LoadingTask; +import github.daneren2005.dsub.util.SongDBHandler; import github.daneren2005.dsub.util.UpdateHelper; import github.daneren2005.dsub.util.UserUtil; import github.daneren2005.dsub.util.Util; @@ -1293,6 +1294,16 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR headers.add(R.string.details_starred); details.add(Util.formatBoolean(context, song.isStarred())); + try { + Long[] dates = SongDBHandler.getHandler(context).getLastPlayed(song.getId()); + if(dates != null) { + headers.add(R.string.details_last_played); + details.add(Util.formatDate(dates[0])); + } + } catch(Exception e) { + Log.e(TAG, "Failed to get last played", e); + } + if(song instanceof PodcastEpisode) { headers.add(R.string.details_description); details.add(song.getAlbum()); diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java index 505e4a6d..cd36c56c 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java @@ -206,6 +206,9 @@ public class DownloadFile implements BufferFile { return saveFile; } + public File getSaveFile() { + return saveFile; + } public File getPartialFile() { return partialFile; diff --git a/app/src/main/java/github/daneren2005/dsub/service/Scrobbler.java b/app/src/main/java/github/daneren2005/dsub/service/Scrobbler.java index 1f8538c9..17a3a90d 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/Scrobbler.java +++ b/app/src/main/java/github/daneren2005/dsub/service/Scrobbler.java @@ -5,6 +5,7 @@ import android.util.Log; import github.daneren2005.dsub.domain.PodcastEpisode; import github.daneren2005.dsub.util.SilentBackgroundTask; +import github.daneren2005.dsub.util.SongDBHandler; import github.daneren2005.dsub.util.Util; /** @@ -32,28 +33,11 @@ public class Scrobbler { } public void scrobble(final Context context, final DownloadFile song, final boolean submission) { - if (song == null || !Util.isScrobblingEnabled(context)) { - return; - } - - // Ignore if online with no network access - if(!Util.isOffline(context) && !Util.isNetworkConnected(context)) { - return; - } - - // Ignore podcasts - if(song.getSong() instanceof PodcastEpisode) { - return; - } - - // Ignore songs which are under 30 seconds per Last.FM guidelines - Integer duration = song.getSong().getDuration(); - if(duration != null && duration > 0 && duration < 30) { + if(song == null) { return; } final String id = song.getSong().getId(); - // Avoid duplicate registrations. if (submission && id.equals(lastSubmission)) { return; @@ -71,6 +55,30 @@ public class Scrobbler { new SilentBackgroundTask<Void>(context) { @Override protected Void doInBackground() { + // TODO: Need to move to register plays of offline songs as well + if(!Util.isOffline(context)) { + SongDBHandler.getHandler(context).setSongPlayed(song, submission); + } + + // Scrobbling disabled + if (!Util.isScrobblingEnabled(context)) { + return null; + } + // Ignore if online with no network access + else if(!Util.isOffline(context) && !Util.isNetworkConnected(context)) { + return null; + } + // Ignore podcasts + else if(song.getSong() instanceof PodcastEpisode) { + return null; + } + + // Ignore songs which are under 30 seconds per Last.FM guidelines + Integer duration = song.getSong().getDuration(); + if(duration != null && duration > 0 && duration < 30) { + return null; + } + MusicService service = MusicServiceFactory.getMusicService(context); try { service.scrobble(id, submission, context, null); diff --git a/app/src/main/java/github/daneren2005/dsub/util/SongDBHandler.java b/app/src/main/java/github/daneren2005/dsub/util/SongDBHandler.java new file mode 100644 index 00000000..f123521f --- /dev/null +++ b/app/src/main/java/github/daneren2005/dsub/util/SongDBHandler.java @@ -0,0 +1,109 @@ +/* + This file is part of Subsonic. + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see <http://www.gnu.org/licenses/>. + Copyright 2015 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.util; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import java.util.Date; + +import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.service.DownloadFile; + +public class SongDBHandler extends SQLiteOpenHelper { + private static final String TAG = SongDBHandler.class.getSimpleName(); + private static SongDBHandler dbHandler; + + private static final int DATABASE_VERSION = 1; + public static final String DATABASE_NAME = "SongsDB"; + + public static final String TABLE_SONGS = "RegisteredSongs"; + public static final String SONGS_ID = "id"; + public static final String SONGS_SERVER_ID = "serverId"; + public static final String SONGS_COMPLETE_PATH = "completePath"; + public static final String SONGS_LAST_PLAYED = "lastPlayed"; + public static final String SONGS_LAST_COMPLETED = "lastCompleted"; + + private SongDBHandler(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + TABLE_SONGS + " ( " + SONGS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + SONGS_SERVER_ID + " TEXT NOT NULL UNIQUE, " + SONGS_COMPLETE_PATH + " TEXT NOT NULL, " + SONGS_LAST_PLAYED + " INTEGER, " + SONGS_LAST_COMPLETED + " INTEGER )"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + TABLE_SONGS); + this.onCreate(db); + } + + public synchronized void addSong(DownloadFile downloadFile) { + SQLiteDatabase db = this.getWritableDatabase(); + addSong(db, downloadFile); + db.close(); + } + protected synchronized void addSong(SQLiteDatabase db, DownloadFile downloadFile) { + ContentValues values = new ContentValues(); + values.put(SONGS_SERVER_ID, downloadFile.getSong().getId()); + values.put(SONGS_COMPLETE_PATH, downloadFile.getSaveFile().getAbsolutePath()); + + db.insertWithOnConflict(TABLE_SONGS, null, values, SQLiteDatabase.CONFLICT_REPLACE); + } + + public synchronized void setSongPlayed(DownloadFile downloadFile, boolean submission) { + // Open and make sure song is in db + SQLiteDatabase db = this.getWritableDatabase(); + addSong(db, downloadFile); + + // Update song's last played + ContentValues values = new ContentValues(); + values.put(submission ? SONGS_LAST_COMPLETED : SONGS_LAST_PLAYED, System.currentTimeMillis()); + db.update(TABLE_SONGS, values, SONGS_SERVER_ID + " = ?", new String[]{downloadFile.getSong().getId()}); + db.close(); + } + + public Long[] getLastPlayed(String id) { + SQLiteDatabase db = this.getReadableDatabase(); + + String[] columns = {SONGS_LAST_PLAYED, SONGS_LAST_COMPLETED}; + Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_SERVER_ID + " = ?", new String[] { id }, null, null, null, null); + + try { + cursor.moveToFirst(); + + Long[] dates = new Long[2]; + dates[0] = cursor.getLong(0); + dates[1] = cursor.getLong(1); + return dates; + } catch(Exception e) {} + + return null; + } + + public static SongDBHandler getHandler(Context context) { + if(dbHandler == null) { + dbHandler = new SongDBHandler(context); + } + + return dbHandler; + } +} diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java index 490e922b..df5e512e 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Util.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java @@ -908,6 +908,9 @@ public final class Util { } } } + public static String formatDate(long millis) { + return formatDate(new Date(millis)); + } public static String formatBoolean(Context context, boolean value) { return context.getResources().getString(value ? R.string.common_true : R.string.common_false); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 303a8e0e..3acbff3e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -642,6 +642,7 @@ <string name="details.position">Position</string> <string name="details.updated">Updated</string> <string name="details.starred">Starred</string> + <string name="details.last_played">Last Played</string> <plurals name="select_album_n_songs"> <item quantity="zero">No songs</item> |