smart mark as played: media player activity, player widget, when media is changed

This commit is contained in:
Martin Fietz 2015-04-05 19:53:21 +02:00
parent fbf1d8373c
commit b2a50983ef
3 changed files with 82 additions and 56 deletions

View File

@ -226,11 +226,18 @@ public abstract class MediaplayerActivity extends ActionBarActivity
// delete if auto delete is enabled and less than 3% of episode is left // delete if auto delete is enabled and less than 3% of episode is left
Playable playable = controller.getMedia(); Playable playable = controller.getMedia();
if(playable instanceof FeedMedia) { if(playable != null && playable instanceof FeedMedia) {
FeedMedia media = (FeedMedia) playable; FeedMedia media = (FeedMedia) playable;
if(UserPreferences.isAutoDelete() && media.hasAlmostEnded()) { if(media.hasAlmostEnded()) {
Log.d(TAG, "Delete " + media.toString()); Log.d(TAG, "smart mark as read");
DBWriter.deleteFeedMediaOfItem(this, media.getId()); FeedItem item = media.getItem();
DBWriter.markItemRead(this, item, true, false);
DBWriter.removeQueueItem(this, item, false);
DBWriter.addItemToPlaybackHistory(this, media);
if (UserPreferences.isAutoDelete()) {
Log.d(TAG, "Delete " + media.toString());
DBWriter.deleteFeedMediaOfItem(this, media.getId());
}
} }
} }

View File

@ -12,14 +12,18 @@ import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.receiver.PlayerWidget;
import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlayerStatus; import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.receiver.PlayerWidget;
/** Updates the state of the player widget */ /** Updates the state of the player widget */
public class PlayerWidgetService extends Service { public class PlayerWidgetService extends Service {
@ -39,8 +43,7 @@ public class PlayerWidgetService extends Service {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
if (BuildConfig.DEBUG) Log.d(TAG, "Service created");
Log.d(TAG, "Service created");
isUpdating = false; isUpdating = false;
psLock = new Object(); psLock = new Object();
} }
@ -48,8 +51,24 @@ public class PlayerWidgetService extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
if (BuildConfig.DEBUG) Log.d(TAG, "Service is about to be destroyed");
Log.d(TAG, "Service is about to be destroyed");
Playable playable = playbackService.getPlayable();
if(playable != null && playable instanceof FeedMedia) {
FeedMedia media = (FeedMedia) playable;
if(media.hasAlmostEnded()) {
Log.d(TAG, "smart mark as read");
FeedItem item = media.getItem();
DBWriter.markItemRead(this, item, true, false);
DBWriter.removeQueueItem(this, item, false);
DBWriter.addItemToPlaybackHistory(this, media);
if (UserPreferences.isAutoDelete()) {
Log.d(TAG, "Delete " + media.toString());
DBWriter.deleteFeedMediaOfItem(this, media.getId());
}
}
}
try { try {
unbindService(mConnection); unbindService(mConnection);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@ -72,9 +91,7 @@ public class PlayerWidgetService extends Service {
startViewUpdaterIfNotRunning(); startViewUpdaterIfNotRunning();
} }
} else { } else {
if (BuildConfig.DEBUG) Log.d(TAG, "Service was called while updating. Ignoring update request");
Log.d(TAG,
"Service was called while updating. Ignoring update request");
} }
return Service.START_NOT_STICKY; return Service.START_NOT_STICKY;
} }
@ -153,8 +170,7 @@ public class PlayerWidgetService extends Service {
private ServiceConnection mConnection = new ServiceConnection() { private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) { public void onServiceConnected(ComponentName className, IBinder service) {
if (BuildConfig.DEBUG) Log.d(TAG, "Connection to service established");
Log.d(TAG, "Connection to service established");
synchronized (psLock) { synchronized (psLock) {
playbackService = ((PlaybackService.LocalBinder) service) playbackService = ((PlaybackService.LocalBinder) service)
.getService(); .getService();
@ -166,8 +182,7 @@ public class PlayerWidgetService extends Service {
public void onServiceDisconnected(ComponentName name) { public void onServiceDisconnected(ComponentName name) {
synchronized (psLock) { synchronized (psLock) {
playbackService = null; playbackService = null;
if (BuildConfig.DEBUG) Log.d(TAG, "Disconnected from service");
Log.d(TAG, "Disconnected from service");
} }
} }

View File

@ -24,11 +24,13 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.playback.AudioPlayer; import de.danoeh.antennapod.core.util.playback.AudioPlayer;
import de.danoeh.antennapod.core.util.playback.IPlayer; import de.danoeh.antennapod.core.util.playback.IPlayer;
import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.Playable;
@ -91,7 +93,7 @@ public class PlaybackServiceMediaPlayer {
new RejectedExecutionHandler() { new RejectedExecutionHandler() {
@Override @Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (BuildConfig.DEBUG) Log.d(TAG, "Rejected execution of runnable"); Log.d(TAG, "Rejected execution of runnable");
} }
} }
); );
@ -137,7 +139,7 @@ public class PlaybackServiceMediaPlayer {
public void playMediaObject(final Playable playable, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) { public void playMediaObject(final Playable playable, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
Validate.notNull(playable); Validate.notNull(playable);
if (BuildConfig.DEBUG) Log.d(TAG, "Play media object."); Log.d(TAG, "playMediaObject(...)");
executor.submit(new Runnable() { executor.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -164,16 +166,16 @@ public class PlaybackServiceMediaPlayer {
*/ */
private void playMediaObject(final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) { private void playMediaObject(final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
Validate.notNull(playable); Validate.notNull(playable);
if (!playerLock.isHeldByCurrentThread()) if (!playerLock.isHeldByCurrentThread()) {
throw new IllegalStateException("method requires playerLock"); throw new IllegalStateException("method requires playerLock");
}
if (media != null) { if (media != null) {
if (!forceReset && media.getIdentifier().equals(playable.getIdentifier()) if (!forceReset && media.getIdentifier().equals(playable.getIdentifier())
&& playerStatus == PlayerStatus.PLAYING) { && playerStatus == PlayerStatus.PLAYING) {
// episode is already playing -> ignore method call // episode is already playing -> ignore method call
if (BuildConfig.DEBUG) Log.d(TAG, "Method call to playMediaObject was ignored: media file already playing.");
Log.d(TAG, "Method call to playMediaObject was ignored: media file already playing.");
return; return;
} else { } else {
// stop playback of this episode // stop playback of this episode
@ -184,6 +186,23 @@ public class PlaybackServiceMediaPlayer {
if (playerStatus == PlayerStatus.PLAYING) { if (playerStatus == PlayerStatus.PLAYING) {
setPlayerStatus(PlayerStatus.PAUSED, media); setPlayerStatus(PlayerStatus.PAUSED, media);
} }
// smart mark as played
if(media != null && media instanceof FeedMedia) {
FeedMedia oldMedia = (FeedMedia) media;
if(oldMedia.hasAlmostEnded()) {
Log.d(TAG, "smart mark as read");
FeedItem item = oldMedia.getItem();
DBWriter.markItemRead(context, item, true, false);
DBWriter.removeQueueItem(context, item, false);
DBWriter.addItemToPlaybackHistory(context, oldMedia);
if (UserPreferences.isAutoDelete()) {
Log.d(TAG, "Delete " + oldMedia.toString());
DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId());
}
}
}
setPlayerStatus(PlayerStatus.INDETERMINATE, null); setPlayerStatus(PlayerStatus.INDETERMINATE, null);
} }
} }
@ -281,11 +300,10 @@ public class PlaybackServiceMediaPlayer {
media.onPlaybackStart(); media.onPlaybackStart();
} else { } else {
if (BuildConfig.DEBUG) Log.e(TAG, "Failed to request audio focus"); Log.e(TAG, "Failed to request audio focus");
} }
} else { } else {
if (BuildConfig.DEBUG) Log.d(TAG, "Call to resume() was ignored because current state of PSMP object is " + playerStatus);
Log.d(TAG, "Call to resume() was ignored because current state of PSMP object is " + playerStatus);
} }
} }
@ -307,8 +325,7 @@ public class PlaybackServiceMediaPlayer {
playerLock.lock(); playerLock.lock();
releaseWifiLockIfNecessary(); releaseWifiLockIfNecessary();
if (playerStatus == PlayerStatus.PLAYING) { if (playerStatus == PlayerStatus.PLAYING) {
if (BuildConfig.DEBUG) Log.d(TAG, "Pausing playback.");
Log.d(TAG, "Pausing playback.");
mediaPlayer.pause(); mediaPlayer.pause();
setPlayerStatus(PlayerStatus.PAUSED, media); setPlayerStatus(PlayerStatus.PAUSED, media);
@ -320,8 +337,7 @@ public class PlaybackServiceMediaPlayer {
reinit(); reinit();
} }
} else { } else {
if (BuildConfig.DEBUG) Log.d(TAG, "Ignoring call to pause: Player is in " + playerStatus + " state");
Log.d(TAG, "Ignoring call to pause: Player is in " + playerStatus + " state");
} }
playerLock.unlock(); playerLock.unlock();
@ -342,8 +358,7 @@ public class PlaybackServiceMediaPlayer {
playerLock.lock(); playerLock.lock();
if (playerStatus == PlayerStatus.INITIALIZED) { if (playerStatus == PlayerStatus.INITIALIZED) {
if (BuildConfig.DEBUG) Log.d(TAG, "Preparing media player");
Log.d(TAG, "Preparing media player");
setPlayerStatus(PlayerStatus.PREPARING, media); setPlayerStatus(PlayerStatus.PREPARING, media);
try { try {
mediaPlayer.prepare(); mediaPlayer.prepare();
@ -370,8 +385,7 @@ public class PlaybackServiceMediaPlayer {
throw new IllegalStateException("Player is not in PREPARING state"); throw new IllegalStateException("Player is not in PREPARING state");
} }
if (BuildConfig.DEBUG) Log.d(TAG, "Resource prepared");
Log.d(TAG, "Resource prepared");
if (mediaType == MediaType.VIDEO) { if (mediaType == MediaType.VIDEO) {
VideoPlayer vp = (VideoPlayer) mediaPlayer; VideoPlayer vp = (VideoPlayer) mediaPlayer;
@ -383,8 +397,7 @@ public class PlaybackServiceMediaPlayer {
} }
if (media.getDuration() == 0) { if (media.getDuration() == 0) {
if (BuildConfig.DEBUG) Log.d(TAG, "Setting duration of media");
Log.d(TAG, "Setting duration of media");
media.setDuration(mediaPlayer.getDuration()); media.setDuration(mediaPlayer.getDuration());
} }
setPlayerStatus(PlayerStatus.PREPARED, media); setPlayerStatus(PlayerStatus.PREPARED, media);
@ -412,8 +425,7 @@ public class PlaybackServiceMediaPlayer {
} else if (mediaPlayer != null) { } else if (mediaPlayer != null) {
mediaPlayer.reset(); mediaPlayer.reset();
} else { } else {
if (BuildConfig.DEBUG) Log.d(TAG, "Call to reinit was ignored: media and mediaPlayer were null");
Log.d(TAG, "Call to reinit was ignored: media and mediaPlayer were null");
} }
playerLock.unlock(); playerLock.unlock();
} }
@ -567,8 +579,7 @@ public class PlaybackServiceMediaPlayer {
if (media != null && media.getMediaType() == MediaType.AUDIO) { if (media != null && media.getMediaType() == MediaType.AUDIO) {
if (mediaPlayer.canSetSpeed()) { if (mediaPlayer.canSetSpeed()) {
mediaPlayer.setPlaybackSpeed((float) speed); mediaPlayer.setPlaybackSpeed((float) speed);
if (BuildConfig.DEBUG) Log.d(TAG, "Playback speed was set to " + speed);
Log.d(TAG, "Playback speed was set to " + speed);
callback.playbackSpeedChanged(speed); callback.playbackSpeedChanged(speed);
} }
} }
@ -651,8 +662,7 @@ public class PlaybackServiceMediaPlayer {
@Override @Override
public void run() { public void run() {
playerLock.lock(); playerLock.lock();
if (BuildConfig.DEBUG) Log.d(TAG, "Resetting video surface");
Log.d(TAG, "Resetting video surface");
mediaPlayer.setDisplay(null); mediaPlayer.setDisplay(null);
reinit(); reinit();
playerLock.unlock(); playerLock.unlock();
@ -716,7 +726,7 @@ public class PlaybackServiceMediaPlayer {
private synchronized void setPlayerStatus(PlayerStatus newStatus, Playable newMedia) { private synchronized void setPlayerStatus(PlayerStatus newStatus, Playable newMedia) {
Validate.notNull(newStatus); Validate.notNull(newStatus);
if (BuildConfig.DEBUG) Log.d(TAG, "Setting player status to " + newStatus); Log.d(TAG, "Setting player status to " + newStatus);
this.playerStatus = newStatus; this.playerStatus = newStatus;
this.media = newMedia; this.media = newMedia;
@ -788,17 +798,15 @@ public class PlaybackServiceMediaPlayer {
// If there is an incoming call, playback should be paused permanently // If there is an incoming call, playback should be paused permanently
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final int callState = (tm != null) ? tm.getCallState() : 0; final int callState = (tm != null) ? tm.getCallState() : 0;
if (BuildConfig.DEBUG) Log.d(TAG, "Call state: " + callState); Log.d(TAG, "Call state: " + callState);
Log.i(TAG, "Call state:" + callState); Log.i(TAG, "Call state:" + callState);
if (focusChange == AudioManager.AUDIOFOCUS_LOSS || callState != TelephonyManager.CALL_STATE_IDLE) { if (focusChange == AudioManager.AUDIOFOCUS_LOSS || callState != TelephonyManager.CALL_STATE_IDLE) {
if (BuildConfig.DEBUG) Log.d(TAG, "Lost audio focus");
Log.d(TAG, "Lost audio focus");
pause(true, false); pause(true, false);
callback.shouldStop(); callback.shouldStop();
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
if (BuildConfig.DEBUG) Log.d(TAG, "Gained audio focus");
Log.d(TAG, "Gained audio focus");
if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now
resume(); resume();
} else { // we ducked => raise audio level back } else { // we ducked => raise audio level back
@ -808,22 +816,19 @@ public class PlaybackServiceMediaPlayer {
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
if (playerStatus == PlayerStatus.PLAYING) { if (playerStatus == PlayerStatus.PLAYING) {
if (!UserPreferences.shouldPauseForFocusLoss()) { if (!UserPreferences.shouldPauseForFocusLoss()) {
if (BuildConfig.DEBUG) Log.d(TAG, "Lost audio focus temporarily. Ducking...");
Log.d(TAG, "Lost audio focus temporarily. Ducking...");
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER, 0); AudioManager.ADJUST_LOWER, 0);
pausedBecauseOfTransientAudiofocusLoss = false; pausedBecauseOfTransientAudiofocusLoss = false;
} else { } else {
if (BuildConfig.DEBUG) Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing...");
Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing...");
pause(false, false); pause(false, false);
pausedBecauseOfTransientAudiofocusLoss = true; pausedBecauseOfTransientAudiofocusLoss = true;
} }
} }
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
if (playerStatus == PlayerStatus.PLAYING) { if (playerStatus == PlayerStatus.PLAYING) {
if (BuildConfig.DEBUG) Log.d(TAG, "Lost audio focus temporarily. Pausing...");
Log.d(TAG, "Lost audio focus temporarily. Pausing...");
pause(false, false); pause(false, false);
pausedBecauseOfTransientAudiofocusLoss = true; pausedBecauseOfTransientAudiofocusLoss = true;
} }
@ -873,8 +878,7 @@ public class PlaybackServiceMediaPlayer {
if (playerStatus == PlayerStatus.INDETERMINATE) { if (playerStatus == PlayerStatus.INDETERMINATE) {
setPlayerStatus(PlayerStatus.STOPPED, null); setPlayerStatus(PlayerStatus.STOPPED, null);
} else { } else {
if (BuildConfig.DEBUG) Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus);
Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus);
} }
playerLock.unlock(); playerLock.unlock();