diff options
16 files changed, 183 insertions, 95 deletions
diff --git a/subsonic-android/AndroidManifest.xml b/subsonic-android/AndroidManifest.xml index 8b6b704d..01bf3a2e 100644 --- a/subsonic-android/AndroidManifest.xml +++ b/subsonic-android/AndroidManifest.xml @@ -2,8 +2,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="github.daneren2005.dsub"
android:installLocation="internalOnly"
- android:versionCode="38"
- android:versionName="3.8.0">
+ android:versionCode="40"
+ android:versionName="3.8.2">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/subsonic-android/res/drawable/notification_stop.png b/subsonic-android/res/drawable/notification_stop.png Binary files differnew file mode 100644 index 00000000..ab98e188 --- /dev/null +++ b/subsonic-android/res/drawable/notification_stop.png diff --git a/subsonic-android/res/values/strings.xml b/subsonic-android/res/values/strings.xml index dd27f426..3ab94f24 100644 --- a/subsonic-android/res/values/strings.xml +++ b/subsonic-android/res/values/strings.xml @@ -261,6 +261,8 @@ <string name="settings.temp_loss_pause_lower">Pause, lower volume when requested</string>
<string name="settings.temp_loss_lower">Always lower volume</string>
<string name="settings.temp_loss_nothing">Do Nothing</string>
+ <string name="settings.persistent_title">Persistent Notification</string>
+ <string name="settings.persistent_summary">Show the notification even after pausing. Press the stop button to clear it away.</string>
<string name="shuffle.startYear">Start Year:</string>
<string name="shuffle.endYear">End Year:</string>
diff --git a/subsonic-android/res/xml/settings.xml b/subsonic-android/res/xml/settings.xml index 30c5bfbc..a2ae7b20 100644 --- a/subsonic-android/res/xml/settings.xml +++ b/subsonic-android/res/xml/settings.xml @@ -182,6 +182,12 @@ android:defaultValue="1" android:entryValues="@array/tempLossValues" android:entries="@array/tempLossNames"/> + + <CheckBoxPreference + android:title="@string/settings.persistent_title" + android:summary="@string/settings.persistent_summary" + android:key="persistentNotification" + android:defaultValue="false"/> </PreferenceCategory> <PreferenceCategory diff --git a/subsonic-android/src/github/daneren2005/dsub/activity/DownloadActivity.java b/subsonic-android/src/github/daneren2005/dsub/activity/DownloadActivity.java index f487b6e6..d93d0817 100644 --- a/subsonic-android/src/github/daneren2005/dsub/activity/DownloadActivity.java +++ b/subsonic-android/src/github/daneren2005/dsub/activity/DownloadActivity.java @@ -489,18 +489,18 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi // Scroll to current playing/downloading. private void scrollToCurrent() { - if (getDownloadService() == null) { + if (getDownloadService() == null || songListAdapter == null) { return; } - for (int i = 0; i < playlistView.getAdapter().getCount(); i++) { + for (int i = 0; i < songListAdapter.getCount(); i++) { if (currentPlaying == playlistView.getItemAtPosition(i)) { playlistView.setSelectionFromTop(i, 40); return; } } DownloadFile currentDownloading = getDownloadService().getCurrentDownloading(); - for (int i = 0; i < playlistView.getAdapter().getCount(); i++) { + for (int i = 0; i < songListAdapter.getCount(); i++) { if (currentDownloading == playlistView.getItemAtPosition(i)) { playlistView.setSelectionFromTop(i, 40); return; @@ -512,7 +512,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi protected void onPause() { super.onPause(); executorService.shutdown(); - if (visualizerView != null) { + if (visualizerView != null && visualizerView.isActive()) { visualizerView.setActive(false); } } @@ -788,7 +788,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi private void start() { DownloadService service = getDownloadService(); PlayerState state = service.getPlayerState(); - if (state == PAUSED || state == COMPLETED) { + if (state == PAUSED || state == COMPLETED || state == STOPPED) { service.start(); } else if (state == STOPPED || state == IDLE) { warnIfNetworkOrStorageUnavailable(); @@ -1012,7 +1012,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi // Top to Bottom swipe else if (e2.getY() - e1.getY() > swipeDistance && Math.abs(velocityY) > swipeVelocity) { warnIfNetworkOrStorageUnavailable(); - downloadService.pause(); + downloadService.seekTo(downloadService.getPlayerPosition() + 30000); onProgressChanged(); return true; } @@ -1020,8 +1020,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi // Bottom to Top swipe else if (e1.getY() - e2.getY() > swipeDistance && Math.abs(velocityY) > swipeVelocity) { warnIfNetworkOrStorageUnavailable(); - start(); - onCurrentChanged(); + downloadService.seekTo(downloadService.getPlayerPosition() - 8000); onProgressChanged(); return true; } diff --git a/subsonic-android/src/github/daneren2005/dsub/domain/Version.java b/subsonic-android/src/github/daneren2005/dsub/domain/Version.java index 65391572..40edf563 100644 --- a/subsonic-android/src/github/daneren2005/dsub/domain/Version.java +++ b/subsonic-android/src/github/daneren2005/dsub/domain/Version.java @@ -55,6 +55,35 @@ public class Version implements Comparable<Version> { public int getMinor() { return minor; } + + public String getVersion() { + switch(major) { + case 1: + switch(minor) { + case 0: + return "3.8"; + case 1: + return "3.9"; + case 2: + return "4.0"; + case 3: + return "4.1"; + case 4: + return "4.2"; + case 5: + return "4.3.1"; + case 6: + return "4.5"; + case 7: + return "4.6"; + case 8: + return "4.7"; + case 9: + return "4.8"; + } + } + return ""; + } /** * Return whether this object is equal to another. diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java index 889d7d2b..6286f906 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java @@ -86,6 +86,8 @@ public interface DownloadService { void next(); void pause(); + + void stop(); void start(); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 4e7bbbb0..dfb827ef 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -120,7 +120,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { private VisualizerController visualizerController; private boolean showVisualization; private boolean jukeboxEnabled; - private ScheduledExecutorService executorService; + private PositionCache positionCache; private StreamProxy proxy; private Timer sleepTimer; @@ -207,7 +207,9 @@ public class DownloadServiceImpl extends Service implements DownloadService { } lifecycleSupport.onDestroy(); mediaPlayer.release(); - nextMediaPlayer.release(); + if(nextMediaPlayer != null) { + nextMediaPlayer.release(); + } shufflePlayBuffer.shutdown(); if (equalizerController != null) { equalizerController.release(); @@ -226,6 +228,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { if(nextPlayingTask != null) { nextPlayingTask.cancel(); } + Util.hidePlayingNotification(this, this, handler); instance = null; } @@ -500,12 +503,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { mRemoteControl.updateMetadata(this, currentPlaying.getSong()); } else { Util.broadcastNewTrackInfo(this, null); - } - - if (currentPlaying != null && showNotification) { - Util.showPlayingNotification(this, this, handler, currentPlaying.getSong()); - } else { - Util.hidePlayingNotification(this, this, handler); + Util.hidePlayingNotification(this, this, handler); } } @@ -636,7 +634,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { /** Plays or resumes the playback, depending on the current player state. */ public synchronized void togglePlayPause() { - if (playerState == PAUSED || playerState == COMPLETED) { + if (playerState == PAUSED || playerState == COMPLETED || playerState == STOPPED) { start(); } else if (playerState == STOPPED || playerState == IDLE) { play(); @@ -716,6 +714,24 @@ public class DownloadServiceImpl extends Service implements DownloadService { handleError(x); } } + + @Override + public synchronized void stop() { + try { + if (playerState == STARTED) { + if (jukeboxEnabled) { + jukeboxService.stop(); + } else { + mediaPlayer.pause(); + } + setPlayerState(STOPPED); + } else if(playerState == PAUSED) { + setPlayerState(STOPPED); + } + } catch(Exception x) { + handleError(x); + } + } @Override public synchronized void start() { @@ -793,8 +809,9 @@ public class DownloadServiceImpl extends Service implements DownloadService { lifecycleSupport.serializeDownloadQueue(); } - boolean show = this.playerState == PAUSED && playerState == PlayerState.STARTED; - boolean hide = this.playerState == STARTED && playerState == PlayerState.PAUSED; + boolean show = playerState == PlayerState.STARTED; + boolean pause = this.playerState == STARTED && playerState == PlayerState.PAUSED; + boolean hide = playerState == PlayerState.STOPPED; Util.broadcastPlaybackStatusChange(this, playerState); this.playerState = playerState; @@ -805,9 +822,16 @@ public class DownloadServiceImpl extends Service implements DownloadService { if (show) { Util.showPlayingNotification(this, this, handler, currentPlaying.getSong()); - } else if (hide) { - Util.hidePlayingNotification(this, this, handler); - } + } else if (pause) { + SharedPreferences prefs = Util.getPreferences(this); + if(prefs.getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) { + Util.showPlayingNotification(this, this, handler, currentPlaying.getSong()); + } else { + Util.hidePlayingNotification(this, this, handler); + } + } else if(hide) { + Util.hidePlayingNotification(this, this, handler); + } mRemoteControl.setPlaybackState(playerState.getRemoteControlClientPlayState()); if (playerState == STARTED) { @@ -816,27 +840,38 @@ public class DownloadServiceImpl extends Service implements DownloadService { scrobbler.scrobble(this, currentPlaying, true); } - if(playerState == STARTED && (executorService == null || executorService.isShutdown())) { - Runnable runnable = new Runnable() { - @Override - public void run() { + if(playerState == STARTED && positionCache == null) { + positionCache = new PositionCache(); + Thread thread = new Thread(positionCache); + thread.start(); + } else if(playerState != STARTED && positionCache != null) { + positionCache.stop(); + positionCache = null; + } + } + + private class PositionCache implements Runnable { + boolean isRunning = true; + + public void stop() { + isRunning = false; + } + + @Override + public void run() { + while(isRunning) { + try { if(mediaPlayer != null && playerState == STARTED) { - try { - cachedPosition = mediaPlayer.getCurrentPosition(); - } catch(Exception e) { - executorService.shutdown(); - } + cachedPosition = mediaPlayer.getCurrentPosition(); } + Thread.sleep(200L); + } + catch(Exception e) { + isRunning = false; } - }; - executorService = Executors.newSingleThreadScheduledExecutor(); - executorService.scheduleWithFixedDelay(runnable, 200L, 200L, TimeUnit.MILLISECONDS); - } else if(playerState != STARTED) { - if(executorService != null && !executorService.isShutdown()) { - executorService.shutdownNow(); } } - } + } private synchronized void setPlayerStateCompleted() { Log.i(TAG, this.playerState.name() + " -> " + PlayerState.COMPLETED + " (" + currentPlaying + ")"); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java index 765e216b..de3c7d39 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java @@ -233,7 +233,7 @@ public class DownloadServiceLifecycleSupport { break; case RemoteControlClient.FLAG_KEY_MEDIA_STOP: case KeyEvent.KEYCODE_MEDIA_STOP: - downloadService.reset(); + downloadService.stop(); break; case RemoteControlClient.FLAG_KEY_MEDIA_PLAY: case KeyEvent.KEYCODE_MEDIA_PLAY: diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java index 4fbbaf2d..5f9aaf96 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -179,14 +179,11 @@ public class OfflineMusicService extends RESTMusicService { @Override public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, int saveSize, ProgressListener progressListener) throws Exception { - InputStream in = new FileInputStream(entry.getCoverArt()); - try { - byte[] bytes = Util.toByteArray(in); - Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); - return Bitmap.createScaledBitmap(bitmap, size, size, true); - } finally { - Util.close(in); - } + try { + return FileUtil.getAlbumArtBitmap(context, entry, size); + } catch(Exception e) { + return null; + } } @Override diff --git a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java index e1f694e6..24dcbabd 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -812,8 +812,16 @@ public class RESTMusicService implements MusicService { task.setOnCancelListener(new CancellableTask.OnCancelListener() { @Override public void onCancel() { - cancelled.set(true); - request.abort(); + new Thread(new Runnable() { + public void run() { + try { + cancelled.set(true); + request.abort(); + } catch(Exception e) { + Log.e(TAG, "Failed to stop http task"); + } + } + }).start(); } }); } diff --git a/subsonic-android/src/github/daneren2005/dsub/service/ServerTooOldException.java b/subsonic-android/src/github/daneren2005/dsub/service/ServerTooOldException.java index 874b8053..e4a951de 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/ServerTooOldException.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/ServerTooOldException.java @@ -45,7 +45,16 @@ public class ServerTooOldException extends Exception { builder.append(text).append(" "); } builder.append("Server API version too old. "); - builder.append("Requires ").append(requiredVersion).append(" but is ").append(serverVersion).append("."); + builder.append("Requires server version ") + .append(requiredVersion.getVersion()) + .append(", but it is version ") + .append(serverVersion.getVersion()) + .append("."); return builder.toString(); } + + @Override + public String getMessage() { + return this.toString(); + } } diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index 1b422d5a..13dbf479 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -62,16 +62,10 @@ public class StreamProxy implements Runnable { public void stop() {
isRunning = false;
thread.interrupt();
- try {
- thread.join(5000);
- } catch (InterruptedException e) {
- Log.e(TAG, "Exception stopping server", e);
- }
}
@Override
public void run() {
- Looper.prepare();
isRunning = true;
while (isRunning) {
try {
@@ -79,11 +73,11 @@ public class StreamProxy implements Runnable { if (client == null) {
continue;
}
- Log.d(TAG, "client connected");
+ Log.i(TAG, "client connected");
StreamToMediaPlayerTask task = new StreamToMediaPlayerTask(client);
if (task.processRequest()) {
- task.execute();
+ new Thread(task).start();
}
} catch (SocketTimeoutException e) {
@@ -92,10 +86,10 @@ public class StreamProxy implements Runnable { Log.e(TAG, "Error connecting to client", e);
}
}
- Log.d(TAG, "Proxy interrupted. Shutting down.");
+ Log.i(TAG, "Proxy interrupted. Shutting down.");
}
- private class StreamToMediaPlayerTask extends AsyncTask<String, Void, Integer> {
+ private class StreamToMediaPlayerTask implements Runnable {
String localPath;
Socket client;
@@ -148,6 +142,7 @@ public class StreamProxy implements Runnable { return false;
}
+ Log.i(TAG, "Processing request for file " + localPath);
File file = new File(localPath);
if (!file.exists()) {
Log.e(TAG, "File " + localPath + " does not exist");
@@ -158,10 +153,11 @@ public class StreamProxy implements Runnable { }
@Override
- protected Integer doInBackground(String... params) {
+ public void run() {
+ Log.i(TAG, "Streaming song in background");
DownloadFile downloadFile = downloadService.getCurrentPlaying();
MusicDirectory.Entry song = downloadFile.getSong();
- long fileSize = downloadFile.getBitRate() * song.getDuration() * 1000 / 8;
+ long fileSize = downloadFile.getBitRate() * ((song.getDuration() != null) ? song.getDuration() : 0) * 1000 / 8;
Log.i(TAG, "Streaming fileSize: " + fileSize);
// Create HTTP header
@@ -239,8 +235,6 @@ public class StreamProxy implements Runnable { Log.e(TAG, "IOException while cleaning up streaming task:");
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
}
-
- return 1;
}
}
-}
\ No newline at end of file +}
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/Constants.java b/subsonic-android/src/github/daneren2005/dsub/util/Constants.java index 3ee7d7e8..ae88a2ef 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/Constants.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/Constants.java @@ -90,6 +90,7 @@ public final class Constants { public static final String PREFERENCES_KEY_BUFFER_LENGTH = "bufferLength"; public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn"; public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings"; + public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification"; // Name of the preferences file. public static final String PREFERENCES_FILE_NAME = "github.daneren2005.dsub_preferences"; diff --git a/subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java b/subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java index 8873b62c..a81b9246 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java @@ -101,7 +101,11 @@ public abstract class ModalBackgroundTask<T> extends BackgroundTask<T> { getHandler().post(new Runnable() { @Override public void run() { - progressDialog.dismiss(); + try { + progressDialog.dismiss(); + } catch(Exception e) { + Log.w(TAG, "Failed to dismiss dialog"); + } error(t); } }); diff --git a/subsonic-android/src/github/daneren2005/dsub/util/Util.java b/subsonic-android/src/github/daneren2005/dsub/util/Util.java index bbbb0573..034ab1d7 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/Util.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/Util.java @@ -42,6 +42,7 @@ import android.net.wifi.WifiManager; import android.os.Build; import android.os.Environment; import android.os.Handler; +import android.support.v4.app.NotificationCompat; import android.util.Log; import android.view.Gravity; import android.view.ViewGroup; @@ -84,7 +85,6 @@ import java.util.concurrent.ConcurrentHashMap; * @version $Id$ */ public final class Util { - private static final String TAG = Util.class.getSimpleName(); private static final DecimalFormat GIGA_BYTE_FORMAT = new DecimalFormat("0.00 GB"); @@ -113,6 +113,7 @@ public final class Util { private final static Pair<Integer, Integer> NOTIFICATION_TEXT_COLORS = new Pair<Integer, Integer>(); private static Toast toast; + private static int notificationID = 123512383; private Util() { } @@ -644,37 +645,31 @@ public final class Util { } public static void showPlayingNotification(final Context context, final DownloadServiceImpl downloadService, Handler handler, MusicDirectory.Entry song) { - // Set the icon, scrolling text and timestamp final Notification notification = new Notification(R.drawable.stat_notify_playing, song.getTitle(), System.currentTimeMillis()); notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; + boolean playing = downloadService.getPlayerState() == PlayerState.STARTED; if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.JELLY_BEAN){ - RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded); - setupViews(expandedContentView,context,song); + RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded); + setupViews(expandedContentView,context,song, playing); notification.bigContentView = expandedContentView; } RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification); - setupViews(smallContentView, context, song); + setupViews(smallContentView, context, song, playing); notification.contentView = smallContentView; Intent notificationIntent = new Intent(context, DownloadActivity.class); notification.contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); - - // Send the notification and put the service in the foreground. - handler.post(new Runnable() { - @Override - public void run() { - downloadService.startForeground(Constants.NOTIFICATION_ID_PLAYING, notification); - } - }); + NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + manager.notify(notificationID, notification); // Update widget DSubWidgetProvider.getInstance().notifyChange(context, downloadService, true); } - private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song){ + private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean playing){ // Use the same text for the ticker and the expanded notification String title = song.getTitle(); @@ -708,14 +703,27 @@ public final class Util { if (colors.getSecond() != null) { rv.setTextColor(R.id.notification_artist, colors.getSecond()); } + + if(!playing) { + rv.setImageViewResource(R.id.control_pause, R.drawable.notification_play); + rv.setImageViewResource(R.id.control_previous, R.drawable.notification_stop); + } // Create actions for media buttons PendingIntent pendingIntent; - Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS"); - prevIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); - prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); - pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0); - rv.setOnClickPendingIntent(R.id.control_previous, pendingIntent); + if(playing) { + Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS"); + prevIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); + pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0); + rv.setOnClickPendingIntent(R.id.control_previous, pendingIntent); + } else { + Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP"); + prevIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_STOP)); + pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0); + rv.setOnClickPendingIntent(R.id.control_previous, pendingIntent); + } Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE"); pauseIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); @@ -731,14 +739,8 @@ public final class Util { } public static void hidePlayingNotification(final Context context, final DownloadServiceImpl downloadService, Handler handler) { - - // Remove notification and remove the service from the foreground - handler.post(new Runnable() { - @Override - public void run() { - downloadService.stopForeground(true); - } - }); + NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + manager.cancelAll(); // Update widget DSubWidgetProvider.getInstance().notifyChange(context, downloadService, false); |