MediaAppWidgetProvider.java revision 41e07cccfd86ce203f31a201446c6afff5fc632b
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.music; 18 19import android.app.PendingIntent; 20import android.appwidget.AppWidgetManager; 21import android.appwidget.AppWidgetProvider; 22import android.content.ComponentName; 23import android.content.Context; 24import android.content.Intent; 25import android.content.res.Resources; 26import android.os.Environment; 27import android.widget.RemoteViews; 28 29/** 30 * Simple widget to show currently playing album art along 31 * with play/pause and next track buttons. 32 */ 33public class MediaAppWidgetProvider extends AppWidgetProvider { 34 static final String TAG = "MusicAppWidgetProvider"; 35 36 public static final String CMDAPPWIDGETUPDATE = "appwidgetupdate"; 37 38 static final ComponentName THIS_APPWIDGET = 39 new ComponentName("com.android.music", 40 "com.android.music.MediaAppWidgetProvider"); 41 42 private static MediaAppWidgetProvider sInstance; 43 44 static synchronized MediaAppWidgetProvider getInstance() { 45 if (sInstance == null) { 46 sInstance = new MediaAppWidgetProvider(); 47 } 48 return sInstance; 49 } 50 51 @Override 52 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 53 defaultAppWidget(context, appWidgetIds); 54 55 // Send broadcast intent to any running MediaPlaybackService so it can 56 // wrap around with an immediate update. 57 Intent updateIntent = new Intent(MediaPlaybackService.SERVICECMD); 58 updateIntent.putExtra(MediaPlaybackService.CMDNAME, 59 MediaAppWidgetProvider.CMDAPPWIDGETUPDATE); 60 updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); 61 updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 62 context.sendBroadcast(updateIntent); 63 } 64 65 /** 66 * Initialize given widgets to default state, where we launch Music on default click 67 * and hide actions if service not running. 68 */ 69 private void defaultAppWidget(Context context, int[] appWidgetIds) { 70 final Resources res = context.getResources(); 71 final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.album_appwidget); 72 73 views.setTextViewText(R.id.title, res.getText(R.string.emptyplaylist)); 74 views.setTextViewText(R.id.artist, null); 75 76 linkButtons(context, views, false /* not playing */); 77 pushUpdate(context, appWidgetIds, views); 78 } 79 80 private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) { 81 // Update specific list of appWidgetIds if given, otherwise default to all 82 final AppWidgetManager gm = AppWidgetManager.getInstance(context); 83 if (appWidgetIds != null) { 84 gm.updateAppWidget(appWidgetIds, views); 85 } else { 86 gm.updateAppWidget(THIS_APPWIDGET, views); 87 } 88 } 89 90 /** 91 * Check against {@link AppWidgetManager} if there are any instances of this widget. 92 */ 93 private boolean hasInstances(Context context) { 94 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 95 int[] appWidgetIds = appWidgetManager.getAppWidgetIds(THIS_APPWIDGET); 96 return (appWidgetIds.length > 0); 97 } 98 99 /** 100 * Handle a change notification coming over from {@link MediaPlaybackService} 101 */ 102 void notifyChange(MediaPlaybackService service, String what) { 103 if (hasInstances(service)) { 104 if (MediaPlaybackService.PLAYBACK_COMPLETE.equals(what) || 105 MediaPlaybackService.META_CHANGED.equals(what) || 106 MediaPlaybackService.PLAYSTATE_CHANGED.equals(what)) { 107 performUpdate(service, null); 108 } 109 } 110 } 111 112 /** 113 * Update all active widget instances by pushing changes 114 */ 115 void performUpdate(MediaPlaybackService service, int[] appWidgetIds) { 116 final Resources res = service.getResources(); 117 final RemoteViews views = new RemoteViews(service.getPackageName(), R.layout.album_appwidget); 118 119 final int track = service.getQueuePosition() + 1; 120 CharSequence titleName = service.getTrackName(); 121 CharSequence artistName = service.getArtistName(); 122 123 // Format title string with track number, or show SD card message 124 String status = Environment.getExternalStorageState(); 125 if (status.equals(Environment.MEDIA_SHARED) || 126 status.equals(Environment.MEDIA_UNMOUNTED)) { 127 titleName = res.getText(R.string.sdcard_busy_title); 128 } else if (status.equals(Environment.MEDIA_REMOVED)) { 129 titleName = res.getText(R.string.sdcard_missing_title); 130 } else if (titleName == null) { 131 titleName = res.getText(R.string.emptyplaylist); 132 } 133 134 views.setTextViewText(R.id.title, titleName); 135 views.setTextViewText(R.id.artist, artistName); 136 137 // Set correct drawable for pause state 138 final boolean playing = service.isPlaying(); 139 if (playing) { 140 views.setImageViewResource(R.id.control_play, R.drawable.appwidget_pause); 141 } else { 142 views.setImageViewResource(R.id.control_play, R.drawable.appwidget_play); 143 } 144 145 // Link actions buttons to intents 146 linkButtons(service, views, playing); 147 148 pushUpdate(service, appWidgetIds, views); 149 } 150 151 /** 152 * Link up various button actions using {@link PendingIntents}. 153 * 154 * @param playerActive True if player is active in background, which means 155 * widget click will launch {@link MediaPlaybackActivity}, 156 * otherwise we launch {@link MusicBrowserActivity}. 157 */ 158 private void linkButtons(Context context, RemoteViews views, boolean playerActive) { 159 // Connect up various buttons and touch events 160 Intent intent; 161 PendingIntent pendingIntent; 162 163 final ComponentName serviceName = new ComponentName(context, MediaPlaybackService.class); 164 165 if (playerActive) { 166 intent = new Intent(context, MediaPlaybackActivity.class); 167 pendingIntent = PendingIntent.getActivity(context, 168 0 /* no requestCode */, intent, 0 /* no flags */); 169 views.setOnClickPendingIntent(R.id.album_appwidget, pendingIntent); 170 } else { 171 intent = new Intent(context, MusicBrowserActivity.class); 172 pendingIntent = PendingIntent.getActivity(context, 173 0 /* no requestCode */, intent, 0 /* no flags */); 174 views.setOnClickPendingIntent(R.id.album_appwidget, pendingIntent); 175 } 176 177 intent = new Intent(MediaPlaybackService.TOGGLEPAUSE_ACTION); 178 intent.setComponent(serviceName); 179 pendingIntent = PendingIntent.getService(context, 180 0 /* no requestCode */, intent, 0 /* no flags */); 181 views.setOnClickPendingIntent(R.id.control_play, pendingIntent); 182 183 intent = new Intent(MediaPlaybackService.NEXT_ACTION); 184 intent.setComponent(serviceName); 185 pendingIntent = PendingIntent.getService(context, 186 0 /* no requestCode */, intent, 0 /* no flags */); 187 views.setOnClickPendingIntent(R.id.control_next, pendingIntent); 188 } 189} 190