diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ee756d26..40f993f2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,13 +9,13 @@
@@ -23,21 +23,21 @@
-
+
-
+
+ android:name=".ui.activities.MusicControllerActivity"
+ android:parentActivityName=".ui.activities.MainActivity" >
-
+
@@ -48,18 +48,28 @@
android:value="b23725bd3d266aa65c5a3dd1816b2f801524a189" />
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/kabouzeid/gramophone/widget/MusicPlayerWidget.java b/app/src/main/java/com/kabouzeid/gramophone/widget/MusicPlayerWidget.java
new file mode 100644
index 00000000..f4782176
--- /dev/null
+++ b/app/src/main/java/com/kabouzeid/gramophone/widget/MusicPlayerWidget.java
@@ -0,0 +1,104 @@
+package com.kabouzeid.gramophone.widget;
+
+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.graphics.Bitmap;
+import android.net.Uri;
+import android.widget.RemoteViews;
+
+import com.kabouzeid.gramophone.App;
+import com.kabouzeid.gramophone.R;
+import com.kabouzeid.gramophone.model.Song;
+import com.kabouzeid.gramophone.service.MusicService;
+import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
+import com.kabouzeid.gramophone.util.MusicUtil;
+import com.nostra13.universalimageloader.core.ImageLoader;
+
+/**
+ * Implementation of App Widget functionality.
+ */
+public class MusicPlayerWidget extends AppWidgetProvider {
+ private static MusicPlayerWidget instance;
+
+ public static synchronized MusicPlayerWidget getInstance() {
+ if (instance == null) {
+ instance = new MusicPlayerWidget();
+ }
+ return instance;
+ }
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.music_player_widget);
+
+ appWidgetManager.updateAppWidget(appWidgetIds, views);
+ }
+
+
+ @Override
+ public void onEnabled(Context context) {
+ // Enter relevant functionality for when the first widget is created
+ }
+
+ @Override
+ public void onDisabled(Context context) {
+ // Enter relevant functionality for when the last widget is disabled
+ }
+
+ private void linkButtons(final Context context, final RemoteViews views) {
+ views.setOnClickPendingIntent(R.id.album_art, retrievePlaybackActions(context, 0));
+ views.setOnClickPendingIntent(R.id.button_toggle_play_pause, retrievePlaybackActions(context, 1));
+ views.setOnClickPendingIntent(R.id.button_next, retrievePlaybackActions(context, 2));
+ views.setOnClickPendingIntent(R.id.button_prev, retrievePlaybackActions(context, 3));
+ }
+
+ private PendingIntent retrievePlaybackActions(final Context context, final int which) {
+ Intent action;
+ PendingIntent pendingIntent;
+ final ComponentName serviceName = new ComponentName(context, MusicService.class);
+ switch (which) {
+ case 0:
+ action = new Intent(context, MusicControllerActivity.class);
+ pendingIntent = PendingIntent.getActivity(context, 0, action, 0);
+ return pendingIntent;
+ case 1:
+ action = new Intent(MusicService.ACTION_TOGGLE_PLAYBACK);
+ action.setComponent(serviceName);
+ pendingIntent = PendingIntent.getService(context, 1, action, 0);
+ return pendingIntent;
+ case 2:
+ action = new Intent(MusicService.ACTION_SKIP);
+ action.setComponent(serviceName);
+ pendingIntent = PendingIntent.getService(context, 2, action, 0);
+ return pendingIntent;
+ case 3:
+ action = new Intent(MusicService.ACTION_REWIND);
+ action.setComponent(serviceName);
+ pendingIntent = PendingIntent.getService(context, 3, action, 0);
+ return pendingIntent;
+ }
+ return null;
+ }
+
+ public void performUpdate(final MusicService service, final Song song){
+ final RemoteViews views = new RemoteViews(service.getPackageName(), R.layout.music_player_widget);
+ linkButtons(service, views);
+ loadAlbumArt(views, MusicUtil.getAlbumArtUri(song.albumId).toString());
+ views.setTextViewText(R.id.song_title, song.title);
+ }
+
+ private static void loadAlbumArt(RemoteViews widgetView, String albumArtUri) {
+ Bitmap albumArtBitmap = ImageLoader.getInstance().loadImageSync(albumArtUri);
+ if (albumArtBitmap == null) {
+ widgetView.setImageViewResource(R.id.album_art, R.drawable.default_album_art);
+ } else {
+ widgetView.setImageViewBitmap(R.id.album_art, albumArtBitmap);
+ }
+ }
+}
+
+
diff --git a/app/src/main/res/drawable-hdpi/ic_pause_black_36dp.png b/app/src/main/res/drawable-hdpi/ic_pause_black_36dp.png
new file mode 100644
index 00000000..8d1f8e76
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_pause_black_36dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.png b/app/src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.png
new file mode 100644
index 00000000..a39ac1cc
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_skip_next_black_36dp.png b/app/src/main/res/drawable-hdpi/ic_skip_next_black_36dp.png
new file mode 100644
index 00000000..cce0a322
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_skip_next_black_36dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_skip_previous_black_36dp.png b/app/src/main/res/drawable-hdpi/ic_skip_previous_black_36dp.png
new file mode 100644
index 00000000..27ebe3e5
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_skip_previous_black_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_pause_black_36dp.png b/app/src/main/res/drawable-mdpi/ic_pause_black_36dp.png
new file mode 100644
index 00000000..2403aa5e
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_pause_black_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.png b/app/src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.png
new file mode 100644
index 00000000..f8803e54
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_skip_next_black_36dp.png b/app/src/main/res/drawable-mdpi/ic_skip_next_black_36dp.png
new file mode 100644
index 00000000..dbf4f541
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_skip_next_black_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_skip_previous_black_36dp.png b/app/src/main/res/drawable-mdpi/ic_skip_previous_black_36dp.png
new file mode 100644
index 00000000..c7e1dc89
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_skip_previous_black_36dp.png differ
diff --git a/app/src/main/res/drawable-nodpi/example_appwidget_preview.png b/app/src/main/res/drawable-nodpi/example_appwidget_preview.png
new file mode 100644
index 00000000..894b069a
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/example_appwidget_preview.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png b/app/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png
new file mode 100644
index 00000000..1b3371da
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.png b/app/src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.png
new file mode 100644
index 00000000..902760bc
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_skip_next_black_36dp.png b/app/src/main/res/drawable-xhdpi/ic_skip_next_black_36dp.png
new file mode 100644
index 00000000..59623648
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_skip_next_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_skip_previous_black_36dp.png b/app/src/main/res/drawable-xhdpi/ic_skip_previous_black_36dp.png
new file mode 100644
index 00000000..f4040ad6
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_skip_previous_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png
new file mode 100644
index 00000000..cfb2bcb9
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.png
new file mode 100644
index 00000000..2f8c6504
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_skip_next_black_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_skip_next_black_36dp.png
new file mode 100644
index 00000000..0adad311
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_skip_next_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_skip_previous_black_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_skip_previous_black_36dp.png
new file mode 100644
index 00000000..36b017b0
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_skip_previous_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_pause_black_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_pause_black_36dp.png
new file mode 100644
index 00000000..59cdb01f
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_pause_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_black_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_black_36dp.png
new file mode 100644
index 00000000..371a01f9
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_skip_next_black_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_skip_next_black_36dp.png
new file mode 100644
index 00000000..51540520
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_skip_next_black_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_skip_previous_black_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_skip_previous_black_36dp.png
new file mode 100644
index 00000000..311229d3
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_skip_previous_black_36dp.png differ
diff --git a/app/src/main/res/layout/music_player_widget.xml b/app/src/main/res/layout/music_player_widget.xml
new file mode 100644
index 00000000..6d3b0ac2
--- /dev/null
+++ b/app/src/main/res/layout/music_player_widget.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-v14/dimens.xml b/app/src/main/res/values-v14/dimens.xml
new file mode 100644
index 00000000..4db8c590
--- /dev/null
+++ b/app/src/main/res/values-v14/dimens.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ 0dp
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index b048dab6..9c3b917f 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -36,4 +36,11 @@
48dp
100dp
+
+
+ 8dp
+ 64dp
diff --git a/app/src/main/res/xml/music_player_widget_info.xml b/app/src/main/res/xml/music_player_widget_info.xml
new file mode 100644
index 00000000..2f44fa79
--- /dev/null
+++ b/app/src/main/res/xml/music_player_widget_info.xml
@@ -0,0 +1,11 @@
+
+
+
\ No newline at end of file