2 * Copyright (C) 2012 Andrew Neal Licensed under the Apache License, Version 2.0
3 * (the "License"); you may not use this file except in compliance with the
4 * License. You may obtain a copy of the License at
5 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
6 * or agreed to in writing, software distributed under the License is
7 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8 * KIND, either express or implied. See the License for the specific language
9 * governing permissions and limitations under the License.
12 package com.andrew.apollo.appwidgets;
14 import android.annotation.SuppressLint;
15 import android.app.PendingIntent;
16 import android.appwidget.AppWidgetManager;
17 import android.content.ComponentName;
18 import android.content.Context;
19 import android.content.Intent;
20 import android.graphics.Bitmap;
21 import android.widget.RemoteViews;
23 import com.andrew.apollo.MusicPlaybackService;
24 import com.andrew.apollo.R;
25 import com.andrew.apollo.ui.activities.AudioPlayerActivity;
26 import com.andrew.apollo.ui.activities.HomeActivity;
27 import com.andrew.apollo.utils.ApolloUtils;
32 * @author Andrew Neal (andrewdneal@gmail.com)
34 @SuppressLint("NewApi")
35 public class AppWidgetLarge extends AppWidgetBase {
37 public static final String CMDAPPWIDGETUPDATE = "app_widget_large_update";
39 private static AppWidgetLarge mInstance;
41 public static synchronized AppWidgetLarge getInstance() {
42 if (mInstance == null) {
43 mInstance = new AppWidgetLarge();
52 public void onUpdate(final Context context, final AppWidgetManager appWidgetManager,
53 final int[] appWidgetIds) {
54 defaultAppWidget(context, appWidgetIds);
55 final Intent updateIntent = new Intent(MusicPlaybackService.SERVICECMD);
56 updateIntent.putExtra(MusicPlaybackService.CMDNAME, AppWidgetLarge.CMDAPPWIDGETUPDATE);
57 updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
58 updateIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
59 context.sendBroadcast(updateIntent);
63 * Initialize given widgets to default state, where we launch Music on
64 * default click and hide actions if service not running.
66 private void defaultAppWidget(final Context context, final int[] appWidgetIds) {
67 final RemoteViews appWidgetViews = new RemoteViews(context.getPackageName(),
68 R.layout.app_widget_large);
69 linkButtons(context, appWidgetViews, false);
70 pushUpdate(context, appWidgetIds, appWidgetViews);
73 private void pushUpdate(final Context context, final int[] appWidgetIds, final RemoteViews views) {
74 final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
75 if (appWidgetIds != null) {
76 appWidgetManager.updateAppWidget(appWidgetIds, views);
78 appWidgetManager.updateAppWidget(new ComponentName(context, getClass()), views);
83 * Check against {@link AppWidgetManager} if there are any instances of this
86 private boolean hasInstances(final Context context) {
87 final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
88 final int[] mAppWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context,
90 return mAppWidgetIds.length > 0;
94 * Handle a change notification coming over from
95 * {@link MusicPlaybackService}
97 public void notifyChange(final MusicPlaybackService service, final String what) {
98 if (hasInstances(service)) {
99 if (MusicPlaybackService.META_CHANGED.equals(what)
100 || MusicPlaybackService.PLAYSTATE_CHANGED.equals(what)) {
101 performUpdate(service, null);
107 * Update all active widget instances by pushing changes
109 public void performUpdate(final MusicPlaybackService service, final int[] appWidgetIds) {
110 final RemoteViews appWidgetView = new RemoteViews(service.getPackageName(),
111 R.layout.app_widget_large);
113 final CharSequence trackName = service.getTrackName();
114 final CharSequence artistName = service.getArtistName();
115 final CharSequence albumName = service.getAlbumName();
116 final Bitmap bitmap = service.getAlbumArt();
118 // Set the titles and artwork
119 appWidgetView.setTextViewText(R.id.app_widget_large_line_one, trackName);
120 appWidgetView.setTextViewText(R.id.app_widget_large_line_two, artistName);
121 appWidgetView.setTextViewText(R.id.app_widget_large_line_three, albumName);
122 appWidgetView.setImageViewBitmap(R.id.app_widget_large_image, bitmap);
124 // Set correct drawable for pause state
125 final boolean isPlaying = service.isPlaying();
127 appWidgetView.setImageViewResource(R.id.app_widget_large_play,
128 R.drawable.btn_playback_pause);
129 if (ApolloUtils.hasJellyBean()) {
130 appWidgetView.setContentDescription(R.id.app_widget_large_play,
131 service.getString(R.string.accessibility_pause));
134 appWidgetView.setImageViewResource(R.id.app_widget_large_play,
135 R.drawable.btn_playback_play);
136 if (ApolloUtils.hasJellyBean()) {
137 appWidgetView.setContentDescription(R.id.app_widget_large_play,
138 service.getString(R.string.accessibility_play));
142 // Link actions buttons to intents
143 linkButtons(service, appWidgetView, isPlaying);
145 // Update the app-widget
146 pushUpdate(service, appWidgetIds, appWidgetView);
150 * Link up various button actions using {@link PendingIntents}.
152 * @param playerActive True if player is active in background, which means
153 * widget click will launch {@link AudioPlayerActivity},
154 * otherwise we launch {@link MusicBrowserActivity}.
156 private void linkButtons(final Context context, final RemoteViews views,
157 final boolean playerActive) {
159 PendingIntent pendingIntent;
161 final ComponentName serviceName = new ComponentName(context, MusicPlaybackService.class);
165 action = new Intent(context, AudioPlayerActivity.class);
166 pendingIntent = PendingIntent.getActivity(context, 0, action, 0);
167 views.setOnClickPendingIntent(R.id.app_widget_large_info_container, pendingIntent);
168 views.setOnClickPendingIntent(R.id.app_widget_large_image, pendingIntent);
171 action = new Intent(context, HomeActivity.class);
172 pendingIntent = PendingIntent.getActivity(context, 0, action, 0);
173 views.setOnClickPendingIntent(R.id.app_widget_large_info_container, pendingIntent);
174 views.setOnClickPendingIntent(R.id.app_widget_large_image, pendingIntent);
178 pendingIntent = buildPendingIntent(context, MusicPlaybackService.PREVIOUS_ACTION, serviceName);
179 views.setOnClickPendingIntent(R.id.app_widget_large_previous, pendingIntent);
182 pendingIntent = buildPendingIntent(context, MusicPlaybackService.TOGGLEPAUSE_ACTION, serviceName);
183 views.setOnClickPendingIntent(R.id.app_widget_large_play, pendingIntent);
186 pendingIntent = buildPendingIntent(context, MusicPlaybackService.NEXT_ACTION, serviceName);
187 views.setOnClickPendingIntent(R.id.app_widget_large_next, pendingIntent);