1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
package net.sourceforge.subsonic.androidapp.provider; |
20 |
|
|
21 |
|
import android.app.PendingIntent; |
22 |
|
import android.appwidget.AppWidgetManager; |
23 |
|
import android.appwidget.AppWidgetProvider; |
24 |
|
import android.content.ComponentName; |
25 |
|
import android.content.Context; |
26 |
|
import android.content.Intent; |
27 |
|
import android.content.res.Resources; |
28 |
|
import android.graphics.Bitmap; |
29 |
|
import android.graphics.Bitmap.Config; |
30 |
|
import android.graphics.Canvas; |
31 |
|
import android.graphics.Paint; |
32 |
|
import android.graphics.PorterDuff.Mode; |
33 |
|
import android.graphics.PorterDuffXfermode; |
34 |
|
import android.graphics.Rect; |
35 |
|
import android.graphics.RectF; |
36 |
|
import android.os.Environment; |
37 |
|
import android.util.Log; |
38 |
|
import android.view.KeyEvent; |
39 |
|
import android.widget.RemoteViews; |
40 |
|
import net.sourceforge.subsonic.androidapp.R; |
41 |
|
import net.sourceforge.subsonic.androidapp.activity.DownloadActivity; |
42 |
|
import net.sourceforge.subsonic.androidapp.activity.MainActivity; |
43 |
|
import net.sourceforge.subsonic.androidapp.domain.MusicDirectory; |
44 |
|
import net.sourceforge.subsonic.androidapp.service.DownloadService; |
45 |
|
import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl; |
46 |
|
import net.sourceforge.subsonic.androidapp.util.FileUtil; |
47 |
|
|
48 |
|
|
49 |
|
|
50 |
|
|
51 |
|
|
52 |
|
|
53 |
|
|
54 |
|
@author |
55 |
|
|
|
|
| 10,7% |
Uncovered Elements: 108 (121) |
Complexity: 25 |
Complexity Density: 0,3 |
|
56 |
|
public class SubsonicAppWidgetProvider4x1 extends AppWidgetProvider { |
57 |
|
|
58 |
|
private static SubsonicAppWidgetProvider4x1 instance; |
59 |
|
private static final String TAG = SubsonicAppWidgetProvider4x1.class.getSimpleName(); |
60 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (5) |
Complexity: 2 |
Complexity Density: 0,67 |
|
61 |
47
|
public static synchronized SubsonicAppWidgetProvider4x1 getInstance() {... |
62 |
47
|
if (instance == null) { |
63 |
1
|
instance = new SubsonicAppWidgetProvider4x1(); |
64 |
|
} |
65 |
47
|
return instance; |
66 |
|
} |
67 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
68 |
0
|
@Override... |
69 |
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { |
70 |
0
|
defaultAppWidget(context, appWidgetIds); |
71 |
|
} |
72 |
|
|
73 |
|
|
74 |
|
|
75 |
|
|
76 |
|
|
|
|
| 0% |
Uncovered Elements: 5 (5) |
Complexity: 1 |
Complexity Density: 0,2 |
|
77 |
0
|
private void defaultAppWidget(Context context, int[] appWidgetIds) {... |
78 |
0
|
final Resources res = context.getResources(); |
79 |
0
|
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget4x1); |
80 |
|
|
81 |
0
|
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text)); |
82 |
|
|
83 |
0
|
linkButtons(context, views, false); |
84 |
0
|
pushUpdate(context, appWidgetIds, views); |
85 |
|
} |
86 |
|
|
|
|
| 0% |
Uncovered Elements: 6 (6) |
Complexity: 2 |
Complexity Density: 0,5 |
|
87 |
0
|
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) {... |
88 |
|
|
89 |
0
|
final AppWidgetManager manager = AppWidgetManager.getInstance(context); |
90 |
0
|
if (appWidgetIds != null) { |
91 |
0
|
manager.updateAppWidget(appWidgetIds, views); |
92 |
|
} else { |
93 |
0
|
manager.updateAppWidget(new ComponentName(context, this.getClass()), views); |
94 |
|
} |
95 |
|
} |
96 |
|
|
97 |
|
|
98 |
|
@link |
99 |
|
|
|
|
| 50% |
Uncovered Elements: 2 (4) |
Complexity: 2 |
Complexity Density: 1 |
|
100 |
47
|
public void notifyChange(Context context, DownloadService service, boolean playing) {... |
101 |
47
|
if (hasInstances(context)) { |
102 |
0
|
performUpdate(context, service, null, playing); |
103 |
|
} |
104 |
|
} |
105 |
|
|
106 |
|
|
107 |
|
@link |
108 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0,33 |
|
109 |
47
|
private boolean hasInstances(Context context) {... |
110 |
47
|
AppWidgetManager manager = AppWidgetManager.getInstance(context); |
111 |
47
|
int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass())); |
112 |
47
|
return (appWidgetIds.length > 0); |
113 |
|
} |
114 |
|
|
115 |
|
|
116 |
|
|
117 |
|
|
|
|
| 0% |
Uncovered Elements: 53 (53) |
Complexity: 13 |
Complexity Density: 0,39 |
|
118 |
0
|
private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing) {... |
119 |
0
|
final Resources res = context.getResources(); |
120 |
0
|
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget4x1); |
121 |
|
|
122 |
0
|
MusicDirectory.Entry currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong(); |
123 |
0
|
String title = currentPlaying == null ? null : currentPlaying.getTitle(); |
124 |
0
|
CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist(); |
125 |
0
|
CharSequence errorState = null; |
126 |
|
|
127 |
|
|
128 |
0
|
String status = Environment.getExternalStorageState(); |
129 |
0
|
if (status.equals(Environment.MEDIA_SHARED) || |
130 |
|
status.equals(Environment.MEDIA_UNMOUNTED)) { |
131 |
0
|
errorState = res.getText(R.string.widget_sdcard_busy); |
132 |
0
|
} else if (status.equals(Environment.MEDIA_REMOVED)) { |
133 |
0
|
errorState = res.getText(R.string.widget_sdcard_missing); |
134 |
0
|
} else if (currentPlaying == null) { |
135 |
0
|
errorState = res.getText(R.string.widget_initial_text); |
136 |
|
} |
137 |
|
|
138 |
0
|
if (errorState != null) { |
139 |
|
|
140 |
0
|
views.setTextViewText(R.id.title,null); |
141 |
0
|
views.setTextViewText(R.id.artist, errorState); |
142 |
0
|
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default); |
143 |
|
} else { |
144 |
|
|
145 |
0
|
views.setTextViewText(R.id.title, title); |
146 |
0
|
views.setTextViewText(R.id.artist, artist); |
147 |
|
} |
148 |
|
|
149 |
|
|
150 |
0
|
if (playing) { |
151 |
0
|
views.setImageViewResource(R.id.control_play, R.drawable.ic_appwidget_music_pause); |
152 |
|
} else { |
153 |
0
|
views.setImageViewResource(R.id.control_play, R.drawable.ic_appwidget_music_play); |
154 |
|
} |
155 |
|
|
156 |
|
|
157 |
0
|
try { |
158 |
0
|
int size = context.getResources().getDrawable(R.drawable.appwidget_art_default).getIntrinsicHeight(); |
159 |
0
|
Bitmap bitmap = currentPlaying == null ? null : FileUtil.getAlbumArtBitmap(context, currentPlaying, size); |
160 |
|
|
161 |
0
|
if (bitmap == null) { |
162 |
|
|
163 |
0
|
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default); |
164 |
|
} else { |
165 |
0
|
bitmap = getRoundedCornerBitmap(bitmap); |
166 |
0
|
views.setImageViewBitmap(R.id.appwidget_coverart, bitmap); |
167 |
|
} |
168 |
|
} catch (Exception x) { |
169 |
0
|
Log.e(TAG, "Failed to load cover art", x); |
170 |
0
|
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default); |
171 |
|
} |
172 |
|
|
173 |
|
|
174 |
0
|
linkButtons(context, views, currentPlaying != null); |
175 |
|
|
176 |
0
|
pushUpdate(context, appWidgetIds, views); |
177 |
|
} |
178 |
|
|
179 |
|
|
180 |
|
|
181 |
|
|
|
|
| 0% |
Uncovered Elements: 14 (14) |
Complexity: 1 |
Complexity Density: 0,07 |
|
182 |
0
|
private static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {... |
183 |
0
|
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); |
184 |
0
|
Canvas canvas = new Canvas(output); |
185 |
|
|
186 |
0
|
final int color = 0xff424242; |
187 |
0
|
final Paint paint = new Paint(); |
188 |
0
|
final float roundPx = 10; |
189 |
|
|
190 |
|
|
191 |
0
|
final Rect rect = new Rect(0, 0, bitmap.getWidth() + (int) roundPx, bitmap.getHeight()); |
192 |
0
|
final RectF rectF = new RectF(rect); |
193 |
|
|
194 |
0
|
paint.setAntiAlias(true); |
195 |
0
|
canvas.drawARGB(0, 0, 0, 0); |
196 |
0
|
paint.setColor(color); |
197 |
0
|
canvas.drawRoundRect(rectF, roundPx, roundPx, paint); |
198 |
|
|
199 |
0
|
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); |
200 |
0
|
canvas.drawBitmap(bitmap, rect, rect, paint); |
201 |
|
|
202 |
0
|
return output; |
203 |
|
} |
204 |
|
|
205 |
|
|
206 |
|
@link |
207 |
|
|
208 |
|
@param |
209 |
|
@link |
210 |
|
@link |
211 |
|
|
|
|
| 0% |
Uncovered Elements: 21 (21) |
Complexity: 2 |
Complexity Density: 0,11 |
|
212 |
0
|
private void linkButtons(Context context, RemoteViews views, boolean playerActive) {... |
213 |
|
|
214 |
0
|
Intent intent = new Intent(context, playerActive ? DownloadActivity.class : MainActivity.class); |
215 |
0
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); |
216 |
0
|
views.setOnClickPendingIntent(R.id.appwidget_coverart, pendingIntent); |
217 |
0
|
views.setOnClickPendingIntent(R.id.appwidget_top, pendingIntent); |
218 |
|
|
219 |
|
|
220 |
0
|
intent = new Intent("1"); |
221 |
0
|
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); |
222 |
0
|
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); |
223 |
0
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0); |
224 |
0
|
views.setOnClickPendingIntent(R.id.control_play, pendingIntent); |
225 |
|
|
226 |
0
|
intent = new Intent("2"); |
227 |
0
|
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); |
228 |
0
|
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); |
229 |
0
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0); |
230 |
0
|
views.setOnClickPendingIntent(R.id.control_next, pendingIntent); |
231 |
|
|
232 |
0
|
intent = new Intent("3"); |
233 |
0
|
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); |
234 |
0
|
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); |
235 |
0
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0); |
236 |
0
|
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent); |
237 |
|
} |
238 |
|
} |