From 8d32bcf2ae5b97dc1a01af47329d62000a2e60a3 Mon Sep 17 00:00:00 2001 From: Christopher Eby Date: Sat, 18 Feb 2012 01:46:38 -0600 Subject: [PATCH] Controls in notification --- generate-pngs.sh | 10 +-- orig/notification_close.svgz | Bin 0 -> 1069 bytes res/drawable-hdpi/notification_close.png | Bin 0 -> 251 bytes res/drawable-mdpi/notification_close.png | Bin 0 -> 166 bytes res/drawable-xhdpi/notification_close.png | Bin 0 -> 305 bytes res/layout-v11/notification.xml | 88 +++++++++++++++++++++ res/layout/notification.xml | 4 +- src/org/kreed/vanilla/PlaybackService.java | 78 ++++++++++++++---- 8 files changed, 156 insertions(+), 24 deletions(-) create mode 100644 orig/notification_close.svgz create mode 100644 res/drawable-hdpi/notification_close.png create mode 100644 res/drawable-mdpi/notification_close.png create mode 100644 res/drawable-xhdpi/notification_close.png create mode 100644 res/layout-v11/notification.xml diff --git a/generate-pngs.sh b/generate-pngs.sh index e2750502..6caa5c92 100755 --- a/generate-pngs.sh +++ b/generate-pngs.sh @@ -1,14 +1,12 @@ #!/bin/sh -force=$1 - gen() { name=`basename "$1" .svgz` png="res/drawable-$2/$name.png" - if [[ "$1" -nt "$png" || $force ]]; then - inkscape --without-gui --export-area-page --export-dpi=$3 --export-png="$png.out" $1 - pngcrush -q -brute "$png.out" "$png" - rm "$png.out" + if [ "$1" -nt "$png" -o ! -e "$png" ]; then + inkscape --without-gui --export-area-page --export-dpi=$3 --export-png="$png" $1 + convert -strip "$png" "$png" + optipng -quiet -o7 "$png" echo fi } diff --git a/orig/notification_close.svgz b/orig/notification_close.svgz new file mode 100644 index 0000000000000000000000000000000000000000..019439047733405c1f91cef2ed7c04841e691a83 GIT binary patch literal 1069 zcmV+|1k(E-iwFP!000000G(D@kJ~m7e)q3XwJ*Eq>Y^=M(%KH%EH((xz9cF7OpCNl ztV9YVO=~NcZfl9>$U%8PVx(?;JAdK%;?ms`?yu@{s z#+=|naJq82a6hdl%ilcD`79~clsHGG_s&=Tu5w&a=W(xfl?B1^c=TDj=?l3Fo*d6x zPbN!s*i9VA0lQpfBwx9$Kvm1a5=kD=f|itP6-0g%xC1>O=((}Z4m1~KDY&wdTs@4) zl5Bgn@#Z+Sq$o|(AVdK|9xyz0<{F>8OHuIgo+t{#FaT^|{u(P&kkAVLJ-yrTm8fM- zw;)G-PId75UCmH`AwrAJ2n{0oPxZ1P)t{qY9-q12=>cUoCU<%DX^)+e=lpGj64%N89ine+y zyrXS~AGY>tfsK%a$_|>_>jE0`?RT%UFIc0s$M2$QkBK-!S6+i3LX;~v_G9RlFuF$b z)5@J9e~~6=F}nf5mZ030#(rB}aBO7XUf=qn&hzYFA>T)R0R+5(id?z`1mlKIKwc7DF1fmemsp(9LCSl)SoAd*oo~eG&{2fbRsw}<2j0-Q8|l3?zm1T2})ptpJ}8*Z(lEfB*h7XU<%`diD10 z+ZQih1Tya4y?gK8Js|hSjT`sx-}h=>$_>=TR}$nG%)rRR!pg?ZEhi_htgg|U5XB0V zDe`o24AGdFoFJjoAb3omfqSL2L&h_u9gAL>aVRHS$ILu_l11RC*>cu(6LZg*2u$Ui z*vMeOuGP4P$5pUH`asvBjz-24>|Kj?nSHu4Yh{L9LTt5m!v=w6ZaT-3t(dxl4Q*SF n-k#Cetjl4@EEQeCW5U1?ctbzC*Il6rXgheZ{aZrytD z;DOf~`&^(DYe|q_FaxWQrskW+ZBjr1M^6{W5Q*^Qgau3j41zrZW{U+oLc|(AgosE; z%$T#_lmpKM1|Kdx#z{^d3`+%sR>+8?o?u%b(VL^Ws(6B|mm~wjk~^%wJN+5rfQB)6 My85}Sb4q9e0QtK!7XSbN literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/notification_close.png b/res/drawable-xhdpi/notification_close.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca4ed12003746f9420136f386cee50a87fa934e GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sW&u7SuK$t1{{8#UoH=v#>eU-J zZUD*Kw{PFQd-vYGd-w0(2Z{jMK=S6zn?Ui03l~iTnjlmXb<}ahn4a2 zQ{H7=^xOVp-po@PhTnVt-eixqIKg)QtML~DKg03~y_YRaCMiijKNHA#SI_xUER z9S!>(l>W7F{$w_BJN2IL`H?@*JUq{7r^ZB0d(tzdoj1el#nOxEuJ(Moyjy-;_~a(d pksDaSaUhvZF6GCHKVQ? + + + + + + + + + + + diff --git a/res/layout/notification.xml b/res/layout/notification.xml index 586e70d1..5af9e558 100644 --- a/res/layout/notification.xml +++ b/res/layout/notification.xml @@ -26,7 +26,7 @@ THE SOFTWARE. android:layout_gravity="center_vertical" android:orientation="horizontal"> - \ No newline at end of file + diff --git a/src/org/kreed/vanilla/PlaybackService.java b/src/org/kreed/vanilla/PlaybackService.java index 1265765f..50b6c29a 100644 --- a/src/org/kreed/vanilla/PlaybackService.java +++ b/src/org/kreed/vanilla/PlaybackService.java @@ -28,12 +28,12 @@ import android.app.PendingIntent; import android.app.Service; import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.res.TypedArray; import android.database.ContentObserver; import android.database.Cursor; import android.graphics.Bitmap; @@ -113,6 +113,13 @@ public final class PlaybackService extends Service * instead. */ public static final String ACTION_TOGGLE_PLAYBACK_DELAYED = "org.kreed.vanilla.action.TOGGLE_PLAYBACK_DELAYED"; + /** + * Action for startService: toggle playback on/off. + * + * This works the same way as ACTION_PLAY_PAUSE but prevents the notification + * from being hidden regardless of notification visibility settings. + */ + public static final String ACTION_TOGGLE_PLAYBACK_NOTIFICATION = "org.kreed.vanilla.action.TOGGLE_PLAYBACK_NOTIFICATION"; /** * Action for startService: advance to the next song. */ @@ -144,16 +151,18 @@ public final class PlaybackService extends Service * when this is called. */ public static final String ACTION_PREVIOUS_SONG_AUTOPLAY = "org.kreed.vanilla.action.PREVIOUS_SONG_AUTOPLAY"; - /** * Change the shuffle mode. */ public static final String ACTION_CYCLE_SHUFFLE = "org.kreed.vanilla.CYCLE_SHUFFLE"; - /** * Change the repeat mode. */ public static final String ACTION_CYCLE_REPEAT = "org.kreed.vanilla.CYCLE_REPEAT"; + /** + * Pause music and hide the notifcation. + */ + public static final String ACTION_CLOSE_NOTIFICATION = "org.kreed.vanilla.CLOSE_NOTIFICATION"; public static final int NEVER = 0; public static final int WHEN_PLAYING = 1; @@ -353,6 +362,11 @@ public final class PlaybackService extends Service * What to do when an accelerometer shake is detected. */ private Action mShakeAction; + /** + * If true, the notification should not be hidden when pausing regardless + * of user settings. + */ + private boolean mForceNotificationVisible; @Override public void onCreate() @@ -453,6 +467,14 @@ public final class PlaybackService extends Service if (ACTION_TOGGLE_PLAYBACK.equals(action)) { playPause(); + } else if (ACTION_TOGGLE_PLAYBACK_NOTIFICATION.equals(action)) { + mForceNotificationVisible = true; + synchronized (mStateLock) { + if ((mState & FLAG_PLAYING) != 0) + pause(); + else + play(); + } } else if (ACTION_TOGGLE_PLAYBACK_DELAYED.equals(action)) { if (mHandler.hasMessages(CALL_GO, Integer.valueOf(0))) { mHandler.removeMessages(CALL_GO, Integer.valueOf(0)); @@ -493,6 +515,11 @@ public final class PlaybackService extends Service cycleFinishAction(); } else if (ACTION_CYCLE_SHUFFLE.equals(action)) { cycleShuffle(); + } else if (ACTION_CLOSE_NOTIFICATION.equals(action)) { + mForceNotificationVisible = false; + pause(); + stopForeground(true); // sometimes required to clear notification + mNotificationManager.cancel(NOTIFICATION_ID); } MediaButtonReceiver.registerMediaButton(this); @@ -708,7 +735,7 @@ public final class PlaybackService extends Service if (mMediaPlayerInitialized) mMediaPlayer.pause(); - if (mNotificationMode == ALWAYS) { + if (mNotificationMode == ALWAYS || mForceNotificationVisible) { stopForeground(false); mNotificationManager.notify(NOTIFICATION_ID, createNotification(mCurrentSong, mState)); } else { @@ -818,7 +845,7 @@ public final class PlaybackService extends Service private void updateNotification() { - if ((mNotificationMode == ALWAYS || mNotificationMode == WHEN_PLAYING && (mState & FLAG_PLAYING) != 0) && mCurrentSong != null) + if ((mForceNotificationVisible || mNotificationMode == ALWAYS || mNotificationMode == WHEN_PLAYING && (mState & FLAG_PLAYING) != 0) && mCurrentSong != null) mNotificationManager.notify(NOTIFICATION_ID, createNotification(mCurrentSong, mState)); else mNotificationManager.cancel(NOTIFICATION_ID); @@ -865,6 +892,7 @@ public final class PlaybackService extends Service */ public int playPause() { + mForceNotificationVisible = false; synchronized (mStateLock) { if ((mState & FLAG_PLAYING) != 0) return pause(); @@ -1621,23 +1649,40 @@ public final class PlaybackService extends Service Bitmap cover = song.getCover(this); if (cover == null) { - views.setImageViewResource(R.id.icon, R.drawable.icon); + views.setImageViewResource(R.id.cover, R.drawable.albumart_mp_unknown_list); } else { - views.setImageViewBitmap(R.id.icon, cover); + views.setImageViewBitmap(R.id.cover, cover); } - if (playing) { - views.setTextViewText(R.id.title, song.title); - } else { - views.setTextViewText(R.id.title, getResources().getString(R.string.notification_title_paused, song.title)); + + String title = song.title; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + int playButton = playing ? R.drawable.pause_normal : R.drawable.play_normal; + views.setImageViewResource(R.id.play_pause, playButton); + + ComponentName service = new ComponentName(this, PlaybackService.class); + + Intent playPause = new Intent(PlaybackService.ACTION_TOGGLE_PLAYBACK_NOTIFICATION); + playPause.setComponent(service); + views.setOnClickPendingIntent(R.id.play_pause, PendingIntent.getService(this, 0, playPause, 0)); + + Intent next = new Intent(PlaybackService.ACTION_NEXT_SONG); + next.setComponent(service); + views.setOnClickPendingIntent(R.id.next, PendingIntent.getService(this, 0, next, 0)); + + Intent close = new Intent(PlaybackService.ACTION_CLOSE_NOTIFICATION); + close.setComponent(service); + views.setOnClickPendingIntent(R.id.close, PendingIntent.getService(this, 0, close, 0)); + } else if (!playing) { + title = getResources().getString(R.string.notification_title_paused, song.title); } + + views.setTextViewText(R.id.title, title); views.setTextViewText(R.id.artist, song.artist); if (mInvertNotification) { - TypedArray array = getTheme().obtainStyledAttributes(new int[] { android.R.attr.textColorPrimary }); - int color = array.getColor(0, 0xFF00FF); - array.recycle(); - views.setTextColor(R.id.title, color); - views.setTextColor(R.id.artist, color); + views.setTextColor(R.id.title, 0xffffffff); + views.setTextColor(R.id.artist, 0xffffffff); } Notification notification = new Notification(); @@ -1659,6 +1704,7 @@ public final class PlaybackService extends Service case AudioManager.AUDIOFOCUS_LOSS: case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: mDuckedLoss = false; + mForceNotificationVisible = true; unsetFlag(FLAG_PLAYING); break; case AudioManager.AUDIOFOCUS_GAIN: