From dc0639784e34c4e98631918eca478fb34bae08c6 Mon Sep 17 00:00:00 2001 From: Christopher Eby Date: Fri, 26 Feb 2010 23:21:46 -0600 Subject: [PATCH] Add a 1x1 cell widget Larger sizes are to come --- AndroidManifest.xml | 6 + res/drawable/empty.png | Bin 0 -> 163 bytes res/drawable/hidden_next.xml | 10 + res/drawable/hidden_play_pause.xml | 10 + res/layout/default_widget.xml | 8 + res/layout/one_cell_widget.xml | 27 +++ res/xml/one_cell_widget.xml | 6 + src/org/kreed/vanilla/CoverView.java | 226 +++++++++++++-------- src/org/kreed/vanilla/OneCellWidget.java | 41 ++++ src/org/kreed/vanilla/PlaybackService.java | 54 +++++ 10 files changed, 301 insertions(+), 87 deletions(-) create mode 100644 res/drawable/empty.png create mode 100644 res/drawable/hidden_next.xml create mode 100644 res/drawable/hidden_play_pause.xml create mode 100644 res/layout/default_widget.xml create mode 100644 res/layout/one_cell_widget.xml create mode 100644 res/xml/one_cell_widget.xml create mode 100644 src/org/kreed/vanilla/OneCellWidget.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 4b08c87f..67509bed 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -15,6 +15,12 @@ + + + + + + 9iWz}IJf1F&Asp9}6A}`DJQfB + + + + + \ No newline at end of file diff --git a/res/drawable/hidden_play_pause.xml b/res/drawable/hidden_play_pause.xml new file mode 100644 index 00000000..1493033e --- /dev/null +++ b/res/drawable/hidden_play_pause.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/default_widget.xml b/res/layout/default_widget.xml new file mode 100644 index 00000000..adb3b044 --- /dev/null +++ b/res/layout/default_widget.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/res/layout/one_cell_widget.xml b/res/layout/one_cell_widget.xml new file mode 100644 index 00000000..2a6f3eb6 --- /dev/null +++ b/res/layout/one_cell_widget.xml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/res/xml/one_cell_widget.xml b/res/xml/one_cell_widget.xml new file mode 100644 index 00000000..6a7990b0 --- /dev/null +++ b/res/xml/one_cell_widget.xml @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/src/org/kreed/vanilla/CoverView.java b/src/org/kreed/vanilla/CoverView.java index 4bd18b62..a1ae833a 100644 --- a/src/org/kreed/vanilla/CoverView.java +++ b/src/org/kreed/vanilla/CoverView.java @@ -72,14 +72,14 @@ public class CoverView extends View { } } - private void drawText(Canvas canvas, String text, float left, float top, float width, float maxWidth, Paint paint) + private static void drawText(Canvas canvas, String text, float left, float top, float width, float maxWidth, Paint paint) { float offset = Math.max(0, maxWidth - width) / 2; canvas.clipRect(left, top, left + maxWidth, top + paint.getTextSize() * 2, Region.Op.REPLACE); canvas.drawText(text, left + offset, top - paint.ascent(), paint); } - private RectF centerRect(float maxWidth, float maxHeight, float width, float height) + private static RectF centerRect(float maxWidth, float maxHeight, float width, float height) { RectF rect = new RectF(); rect.left = (maxWidth - width) / 2; @@ -89,94 +89,146 @@ public class CoverView extends View { return rect; } + private static RectF bottomStretchRect(float maxWidth, float maxHeight, float width, float height) + { + RectF rect = new RectF(); + rect.left = 0; + rect.top = maxHeight - height; + rect.right = maxWidth; + rect.bottom = maxHeight; + return rect; + } + + public static Bitmap createMiniBitmap(Song song, int width, int height) + { + if (song == null || width < 1 || height < 1) + return null; + + Paint paint = new Paint(); + paint.setAntiAlias(true); + + String title = song.title == null ? "" : song.title; + Bitmap cover = song.coverPath == null ? null : BitmapFactory.decodeFile(song.coverPath); + + float titleSize = 12; + float padding = 2; + + paint.setTextSize(titleSize); + float titleWidth = paint.measureText(title); + + float boxWidth = width; + float boxHeight = Math.min(height, titleSize + padding * 2); + + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + Canvas canvas = new Canvas(bitmap); + + if (cover != null) { + canvas.drawBitmap(cover, null, new Rect(0, 0, width, height), paint); + cover.recycle(); + cover = null; + } + + RectF boxRect = bottomStretchRect(width, height, boxWidth, boxHeight); + + paint.setARGB(150, 0, 0, 0); + canvas.drawRect(boxRect, paint); + + float maxWidth = boxWidth - padding * 2; + paint.setARGB(255, 255, 255, 255); + boxRect.top += padding; + boxRect.left += padding; + + paint.setTextSize(titleSize); + drawText(canvas, title, boxRect.left, boxRect.top, titleWidth, maxWidth, paint); + + return bitmap; + } + + public static Bitmap createBitmap(Song song, int width, int height) + { + if (song == null || width < 1 || height < 1) + return null; + + Paint paint = new Paint(); + paint.setAntiAlias(true); + + String title = song.title == null ? "" : song.title; + String album = song.album == null ? "" : song.album; + String artist = song.artist == null ? "" : song.artist; + Bitmap cover = song.coverPath == null ? null : BitmapFactory.decodeFile(song.coverPath); + + float titleSize = 20; + float subSize = 14; + float padding = 10; + + paint.setTextSize(titleSize); + float titleWidth = paint.measureText(title); + paint.setTextSize(subSize); + float albumWidth = paint.measureText(album); + float artistWidth = paint.measureText(artist); + + float boxWidth = Math.min(width, Math.max(titleWidth, Math.max(artistWidth, albumWidth)) + padding * 2); + float boxHeight = Math.min(height, titleSize + subSize * 2 + padding * 4); + + float coverWidth; + float coverHeight; + + if (cover == null) { + coverWidth = 0; + coverHeight = 0; + } else { + coverWidth = cover.getWidth(); + coverHeight = cover.getHeight(); + + float drawableAspectRatio = coverHeight / coverWidth; + float viewAspectRatio = (float) height / width; + float scale = drawableAspectRatio > viewAspectRatio ? height / coverWidth + : width / coverHeight; + + coverWidth *= scale; + coverHeight *= scale; + } + + int bitmapWidth = (int)Math.max(coverWidth, boxWidth); + int bitmapHeight = (int)Math.max(coverHeight, boxHeight); + + Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.RGB_565); + Canvas canvas = new Canvas(bitmap); + + if (cover != null) { + RectF rect = centerRect(bitmapWidth, bitmapHeight, coverWidth, coverHeight); + canvas.drawBitmap(cover, null, rect, paint); + cover.recycle(); + cover = null; + } + + RectF boxRect = centerRect(bitmapWidth, bitmapHeight, boxWidth, boxHeight); + + paint.setARGB(150, 0, 0, 0); + canvas.drawRect(boxRect, paint); + + float maxWidth = boxWidth - padding * 2; + paint.setARGB(255, 255, 255, 255); + boxRect.top += padding; + boxRect.left += padding; + + paint.setTextSize(titleSize); + drawText(canvas, title, boxRect.left, boxRect.top, titleWidth, maxWidth, paint); + boxRect.top += titleSize + padding; + + paint.setTextSize(subSize); + drawText(canvas, album, boxRect.left, boxRect.top, albumWidth, maxWidth, paint); + boxRect.top += subSize + padding; + + drawText(canvas, artist, boxRect.left, boxRect.top, artistWidth, maxWidth, paint); + + return bitmap; + } + private void createBitmap(int i) { - Song song = mSongs[i]; - Bitmap bitmap = null; - - if (song != null) { - int width = getWidth(); - int height = getHeight(); - - if (width == 0 || height == 0) - return; - - Paint paint = new Paint(); - paint.setAntiAlias(true); - - String title = song.title == null ? "" : song.title; - String album = song.album == null ? "" : song.album; - String artist = song.artist == null ? "" : song.artist; - Bitmap cover = song.coverPath == null ? null : BitmapFactory.decodeFile(song.coverPath); - - float titleSize = 20; - float subSize = 14; - float padding = 10; - - paint.setTextSize(titleSize); - float titleWidth = paint.measureText(title); - paint.setTextSize(subSize); - float albumWidth = paint.measureText(album); - float artistWidth = paint.measureText(artist); - - float boxWidth = Math.min(width, Math.max(titleWidth, Math.max(artistWidth, albumWidth)) + padding * 2); - float boxHeight = Math.min(height, titleSize + subSize * 2 + padding * 4); - - float coverWidth; - float coverHeight; - - if (cover == null) { - coverWidth = 0; - coverHeight = 0; - } else { - coverWidth = cover.getWidth(); - coverHeight = cover.getHeight(); - - float drawableAspectRatio = coverHeight / coverWidth; - float viewAspectRatio = (float) height / width; - float scale = drawableAspectRatio > viewAspectRatio ? height / coverWidth - : width / coverHeight; - - coverWidth *= scale; - coverHeight *= scale; - } - - int bitmapWidth = (int)Math.max(coverWidth, boxWidth); - int bitmapHeight = (int)Math.max(coverHeight, boxHeight); - - bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.RGB_565); - Canvas canvas = new Canvas(bitmap); - - if (cover != null) { - RectF rect = centerRect(bitmapWidth, bitmapHeight, coverWidth, coverHeight); - canvas.drawBitmap(cover, null, rect, paint); - cover.recycle(); - cover = null; - } - - RectF boxRect = centerRect(bitmapWidth, bitmapHeight, boxWidth, boxHeight); - - paint.setARGB(150, 0, 0, 0); - canvas.drawRect(boxRect, paint); - - float maxWidth = boxWidth - padding * 2; - paint.setARGB(255, 255, 255, 255); - boxRect.top += padding; - boxRect.left += padding; - - paint.setTextSize(titleSize); - drawText(canvas, title, boxRect.left, boxRect.top, titleWidth, maxWidth, paint); - boxRect.top += titleSize + padding; - - paint.setTextSize(subSize); - drawText(canvas, album, boxRect.left, boxRect.top, albumWidth, maxWidth, paint); - boxRect.top += subSize + padding; - - drawText(canvas, artist, boxRect.left, boxRect.top, artistWidth, maxWidth, paint); - } - Bitmap oldBitmap = mBitmaps[i]; - mBitmaps[i] = bitmap; + mBitmaps[i] = createBitmap(mSongs[i], getWidth(), getHeight()); if (oldBitmap != null) oldBitmap.recycle(); } diff --git a/src/org/kreed/vanilla/OneCellWidget.java b/src/org/kreed/vanilla/OneCellWidget.java new file mode 100644 index 00000000..a249ad97 --- /dev/null +++ b/src/org/kreed/vanilla/OneCellWidget.java @@ -0,0 +1,41 @@ +package org.kreed.vanilla; + +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.widget.RemoteViews; + +public class OneCellWidget extends AppWidgetProvider { + @Override + public void onUpdate(Context context, AppWidgetManager manager, int[] ids) + { + context.sendBroadcast(new Intent(PlaybackService.APPWIDGET_SMALL_UPDATE)); + } + + private static void sendUpdate(Context context, RemoteViews views) + { + AppWidgetManager manager = AppWidgetManager.getInstance(context); + ComponentName widget = new ComponentName(context, OneCellWidget.class); + manager.updateAppWidget(widget, views); + } + + public static void update(Context context, Song song) + { + RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.one_cell_widget); + views.setOnClickPendingIntent(R.id.play_pause, PendingIntent.getBroadcast(context, 0, new Intent(PlaybackService.TOGGLE_PLAYBACK), 0)); + views.setOnClickPendingIntent(R.id.next, PendingIntent.getBroadcast(context, 0, new Intent(PlaybackService.NEXT_SONG), 0)); + if (song != null) + views.setImageViewBitmap(R.id.cover_view, CoverView.createMiniBitmap(song, 72, 72)); + + sendUpdate(context, views); + } + + public static void reset(Context context) + { + RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.default_widget); + sendUpdate(context, views); + } +} \ No newline at end of file diff --git a/src/org/kreed/vanilla/PlaybackService.java b/src/org/kreed/vanilla/PlaybackService.java index 5e369ff1..a6af4ce5 100644 --- a/src/org/kreed/vanilla/PlaybackService.java +++ b/src/org/kreed/vanilla/PlaybackService.java @@ -56,6 +56,10 @@ import android.widget.Toast; public class PlaybackService extends Service implements Runnable, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, SharedPreferences.OnSharedPreferenceChangeListener { private static final int NOTIFICATION_ID = 2; + public static final String APPWIDGET_SMALL_UPDATE = "org.kreed.vanilla.action.APPWIDGET_SMALL_UPDATE"; + public static final String TOGGLE_PLAYBACK = "org.kreed.vanilla.action.TOGGLE_PLAYBACK"; + public static final String NEXT_SONG = "org.kreed.vanilla.action.NEXT_SONG"; + public static final int STATE_NORMAL = 0; public static final int STATE_NO_MEDIA = 1; public static final int STATE_PLAYING = 2; @@ -187,6 +191,8 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On unregisterReceiver(mReceiver); mNotificationManager.cancel(NOTIFICATION_ID); + resetWidgets(); + if (mWakeLock != null && mWakeLock.isHeld()) mWakeLock.release(); } @@ -235,6 +241,27 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On } else if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals(action) || Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)) { mHandler.sendEmptyMessage(RETRIEVE_SONGS); + } else if (TOGGLE_PLAYBACK.equals(action)) { + if (mHandler.hasMessages(DO)) { + mHandler.removeMessages(DO); + Intent launcher = new Intent(PlaybackService.this, NowPlayingActivity.class); + launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(launcher); + } else { + mHandler.sendMessageDelayed(mHandler.obtainMessage(DO, PLAY_PAUSE, 0), 250); + } + } else if (NEXT_SONG.equals(action)) { + if (mHandler.hasMessages(DO)) { + mHandler.removeMessages(DO); + Intent launcher = new Intent(PlaybackService.this, NowPlayingActivity.class); + launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(launcher); + } else { + mHandler.sendMessageDelayed(mHandler.obtainMessage(DO, SET_SONG, 1), 250); + } + } else if (APPWIDGET_SMALL_UPDATE.equals(intent.getAction())) { + OneCellWidget.update(PlaybackService.this, getSong(0)); + return; } } }; @@ -297,6 +324,7 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On private static final int HANDLE_PAUSE = 8; private static final int RETRIEVE_SONGS = 9; private static final int CALL = 10; + private static final int DO = 11; public void run() { @@ -376,6 +404,16 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On } } break; + case DO: + if (message.arg1 == DO) { + Log.w("VanillaMusic", "handleMessage.DO should not be called with arg1 = DO"); + return; + } + + message.what = message.arg1; + message.arg1 = message.arg2; + handleMessage(message); + break; } } }; @@ -384,6 +422,9 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On filter.addAction(Intent.ACTION_HEADSET_PLUG); filter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); filter.addAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + filter.addAction(TOGGLE_PLAYBACK); + filter.addAction(NEXT_SONG); + filter.addAction(APPWIDGET_SMALL_UPDATE); registerReceiver(mReceiver, filter); PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE); @@ -554,6 +595,8 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On mSongTimeline.remove(0); --mCurrentSong; } + + updateWidgets(); } public void onCompletion(MediaPlayer player) @@ -598,4 +641,15 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On return mSongTimeline.get(pos); } + + private void updateWidgets() + { + Song song = getSong(0); + OneCellWidget.update(this, song); + } + + private void resetWidgets() + { + OneCellWidget.reset(this); + } } \ No newline at end of file