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.cyngn.eleven.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.text.TextUtils;
22 import android.view.View;
23 import android.widget.RemoteViews;
25 import com.cyngn.eleven.MusicPlaybackService;
26 import com.cyngn.eleven.R;
27 import com.cyngn.eleven.ui.activities.AudioPlayerActivity;
28 import com.cyngn.eleven.ui.activities.HomeActivity;
29 import com.cyngn.eleven.utils.ApolloUtils;
34 * @author Andrew Neal (andrewdneal@gmail.com)
36 @SuppressLint("NewApi")
37 public class AppWidgetSmall extends AppWidgetBase {
39 public static final String CMDAPPWIDGETUPDATE = "app_widget_small_update";
41 private static AppWidgetSmall mInstance;
43 public static synchronized AppWidgetSmall getInstance() {
44 if (mInstance == null) {
45 mInstance = new AppWidgetSmall();
54 public void onUpdate(final Context context, final AppWidgetManager appWidgetManager,
55 final int[] appWidgetIds) {
56 defaultAppWidget(context, appWidgetIds);
57 final Intent updateIntent = new Intent(MusicPlaybackService.SERVICECMD);
58 updateIntent.putExtra(MusicPlaybackService.CMDNAME, AppWidgetSmall.CMDAPPWIDGETUPDATE);
59 updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
60 updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
61 context.sendBroadcast(updateIntent);
65 * Initialize given widgets to default state, where we launch Music on
66 * default click and hide actions if service not running.
68 private void defaultAppWidget(final Context context, final int[] appWidgetIds) {
69 final RemoteViews appWidgetViews = new RemoteViews(context.getPackageName(),
70 R.layout.app_widget_small);
71 appWidgetViews.setViewVisibility(R.id.app_widget_small_info_container, View.INVISIBLE);
72 linkButtons(context, appWidgetViews, false);
73 pushUpdate(context, appWidgetIds, appWidgetViews);
76 private void pushUpdate(final Context context, final int[] appWidgetIds, final RemoteViews views) {
77 final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
78 if (appWidgetIds != null) {
79 appWidgetManager.updateAppWidget(appWidgetIds, views);
81 appWidgetManager.updateAppWidget(new ComponentName(context, getClass()), views);
86 * Check against {@link AppWidgetManager} if there are any instances of this
89 private boolean hasInstances(final Context context) {
90 final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
91 final int[] mAppWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context,
93 return mAppWidgetIds.length > 0;
97 * Handle a change notification coming over from
98 * {@link MusicPlaybackService}
100 public void notifyChange(final MusicPlaybackService service, final String what) {
101 if (hasInstances(service)) {
102 if (MusicPlaybackService.META_CHANGED.equals(what)
103 || MusicPlaybackService.PLAYSTATE_CHANGED.equals(what)) {
104 performUpdate(service, null);
110 * Update all active widget instances by pushing changes
112 public void performUpdate(final MusicPlaybackService service, final int[] appWidgetIds) {
113 final RemoteViews appWidgetView = new RemoteViews(service.getPackageName(),
114 R.layout.app_widget_small);
116 final CharSequence trackName = service.getTrackName();
117 final CharSequence artistName = service.getArtistName();
118 final Bitmap bitmap = service.getAlbumArt();
120 // Set the titles and artwork
121 if (TextUtils.isEmpty(trackName) && TextUtils.isEmpty(artistName)) {
122 appWidgetView.setViewVisibility(R.id.app_widget_small_info_container, View.INVISIBLE);
124 appWidgetView.setViewVisibility(R.id.app_widget_small_info_container, View.VISIBLE);
125 appWidgetView.setTextViewText(R.id.app_widget_small_line_one, trackName);
126 appWidgetView.setTextViewText(R.id.app_widget_small_line_two, artistName);
128 appWidgetView.setImageViewBitmap(R.id.app_widget_small_image, bitmap);
130 // Set correct drawable for pause state
131 final boolean isPlaying = service.isPlaying();
133 appWidgetView.setImageViewResource(R.id.app_widget_small_play,
134 R.drawable.btn_playback_pause);
135 if (ApolloUtils.hasJellyBean()) {
136 appWidgetView.setContentDescription(R.id.app_widget_small_play,
137 service.getString(R.string.accessibility_pause));
140 appWidgetView.setImageViewResource(R.id.app_widget_small_play,
141 R.drawable.btn_playback_play);
142 if (ApolloUtils.hasJellyBean()) {
143 appWidgetView.setContentDescription(R.id.app_widget_small_play,
144 service.getString(R.string.accessibility_play));
148 // Link actions buttons to intents
149 linkButtons(service, appWidgetView, isPlaying);
151 // Update the app-widget
152 pushUpdate(service, appWidgetIds, appWidgetView);
156 * Link up various button actions using {@link PendingIntents}.
158 * @param playerActive True if player is active in background, which means
159 * widget click will launch {@link AudioPlayerActivity},
160 * otherwise we launch {@link MusicBrowserActivity}.
162 private void linkButtons(final Context context, final RemoteViews views,
163 final boolean playerActive) {
165 PendingIntent pendingIntent;
167 final ComponentName serviceName = new ComponentName(context, MusicPlaybackService.class);
171 action = new Intent(context, AudioPlayerActivity.class);
172 pendingIntent = PendingIntent.getActivity(context, 0, action, 0);
173 views.setOnClickPendingIntent(R.id.app_widget_small_info_container, pendingIntent);
174 views.setOnClickPendingIntent(R.id.app_widget_small_image, pendingIntent);
177 action = new Intent(context, HomeActivity.class);
178 pendingIntent = PendingIntent.getActivity(context, 0, action, 0);
179 views.setOnClickPendingIntent(R.id.app_widget_small_info_container, pendingIntent);
180 views.setOnClickPendingIntent(R.id.app_widget_small_image, pendingIntent);
184 pendingIntent = buildPendingIntent(context, MusicPlaybackService.PREVIOUS_ACTION, serviceName);
185 views.setOnClickPendingIntent(R.id.app_widget_small_previous, pendingIntent);
188 pendingIntent = buildPendingIntent(context, MusicPlaybackService.TOGGLEPAUSE_ACTION, serviceName);
189 views.setOnClickPendingIntent(R.id.app_widget_small_play, pendingIntent);
192 pendingIntent = buildPendingIntent(context, MusicPlaybackService.NEXT_ACTION, serviceName);
193 views.setOnClickPendingIntent(R.id.app_widget_small_next, pendingIntent);