1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
package net.sourceforge.subsonic.androidapp.util; |
20 |
|
|
21 |
|
import android.app.Activity; |
22 |
|
import android.app.AlertDialog; |
23 |
|
import android.app.Notification; |
24 |
|
import android.app.NotificationManager; |
25 |
|
import android.app.PendingIntent; |
26 |
|
import android.app.Service; |
27 |
|
import android.appwidget.AppWidgetProvider; |
28 |
|
import android.content.ComponentName; |
29 |
|
import android.content.Context; |
30 |
|
import android.content.DialogInterface; |
31 |
|
import android.content.Intent; |
32 |
|
import android.content.SharedPreferences; |
33 |
|
import android.content.res.Resources; |
34 |
|
import android.graphics.Bitmap; |
35 |
|
import android.graphics.drawable.BitmapDrawable; |
36 |
|
import android.graphics.drawable.Drawable; |
37 |
|
import android.media.AudioManager; |
38 |
|
import android.net.ConnectivityManager; |
39 |
|
import android.net.NetworkInfo; |
40 |
|
import android.os.Environment; |
41 |
|
import android.os.Handler; |
42 |
|
import android.util.Log; |
43 |
|
import android.view.Gravity; |
44 |
|
import android.view.KeyEvent; |
45 |
|
import android.widget.RemoteViews; |
46 |
|
import android.widget.Toast; |
47 |
|
import net.sourceforge.subsonic.androidapp.R; |
48 |
|
import net.sourceforge.subsonic.androidapp.activity.DownloadActivity; |
49 |
|
import net.sourceforge.subsonic.androidapp.activity.MainActivity; |
50 |
|
import net.sourceforge.subsonic.androidapp.domain.MusicDirectory; |
51 |
|
import net.sourceforge.subsonic.androidapp.domain.PlayerState; |
52 |
|
import net.sourceforge.subsonic.androidapp.domain.RepeatMode; |
53 |
|
import net.sourceforge.subsonic.androidapp.domain.Version; |
54 |
|
import net.sourceforge.subsonic.androidapp.provider.SubsonicAppWidgetProvider4x1; |
55 |
|
import net.sourceforge.subsonic.androidapp.receiver.MediaButtonIntentReceiver; |
56 |
|
import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl; |
57 |
|
import org.apache.http.HttpEntity; |
58 |
|
|
59 |
|
import java.io.ByteArrayOutputStream; |
60 |
|
import java.io.Closeable; |
61 |
|
import java.io.File; |
62 |
|
import java.io.FileInputStream; |
63 |
|
import java.io.FileOutputStream; |
64 |
|
import java.io.IOException; |
65 |
|
import java.io.InputStream; |
66 |
|
import java.io.OutputStream; |
67 |
|
import java.io.UnsupportedEncodingException; |
68 |
|
import java.lang.reflect.Constructor; |
69 |
|
import java.lang.reflect.Method; |
70 |
|
import java.security.MessageDigest; |
71 |
|
import java.text.DecimalFormat; |
72 |
|
import java.text.NumberFormat; |
73 |
|
import java.util.Map; |
74 |
|
import java.util.concurrent.ConcurrentHashMap; |
75 |
|
|
76 |
|
|
77 |
|
@author |
78 |
|
@version |
79 |
|
|
|
|
| 84,8% |
Uncovered Elements: 68 (446) |
Complexity: 116 |
Complexity Density: 0,37 |
|
80 |
|
public class Util extends DownloadActivity { |
81 |
|
|
82 |
|
private static final String TAG = Util.class.getSimpleName(); |
83 |
|
|
84 |
|
private static final DecimalFormat GIGA_BYTE_FORMAT = new DecimalFormat("0.00 GB"); |
85 |
|
private static final DecimalFormat MEGA_BYTE_FORMAT = new DecimalFormat("0.00 MB"); |
86 |
|
private static final DecimalFormat KILO_BYTE_FORMAT = new DecimalFormat("0 KB"); |
87 |
|
|
88 |
|
private static DecimalFormat GIGA_BYTE_LOCALIZED_FORMAT = null; |
89 |
|
private static DecimalFormat MEGA_BYTE_LOCALIZED_FORMAT = null; |
90 |
|
private static DecimalFormat KILO_BYTE_LOCALIZED_FORMAT = null; |
91 |
|
private static DecimalFormat BYTE_LOCALIZED_FORMAT = null; |
92 |
|
|
93 |
|
public static final String EVENT_META_CHANGED = "net.sourceforge.subsonic.androidapp.EVENT_META_CHANGED"; |
94 |
|
public static final String EVENT_PLAYSTATE_CHANGED = "net.sourceforge.subsonic.androidapp.EVENT_PLAYSTATE_CHANGED"; |
95 |
|
|
96 |
|
private static final Map<Integer, Version> SERVER_REST_VERSIONS = new ConcurrentHashMap<Integer, Version>(); |
97 |
|
|
98 |
|
|
99 |
|
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
100 |
|
private static Toast toast; |
101 |
|
|
|
|
| - |
Uncovered Elements: 0 (0) |
Complexity: 1 |
Complexity Density: - |
|
102 |
0
|
private Util() {... |
103 |
|
} |
104 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
105 |
282
|
public static boolean isOffline(Context context) {... |
106 |
282
|
return getActiveServer(context) == 0; |
107 |
|
} |
108 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
109 |
21
|
public static boolean isScreenLitOnDownload(Context context) {... |
110 |
21
|
SharedPreferences prefs = getPreferences(context); |
111 |
21
|
return prefs.getBoolean(Constants.PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD, false); |
112 |
|
} |
113 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
114 |
27
|
public static RepeatMode getRepeatMode(Context context) {... |
115 |
27
|
SharedPreferences prefs = getPreferences(context); |
116 |
27
|
return RepeatMode.valueOf(prefs.getString(Constants.PREFERENCES_KEY_REPEAT_MODE, RepeatMode.OFF.name())); |
117 |
|
} |
118 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0,25 |
|
119 |
5
|
public static void setRepeatMode(Context context, RepeatMode repeatMode) {... |
120 |
5
|
SharedPreferences prefs = getPreferences(context); |
121 |
5
|
SharedPreferences.Editor editor = prefs.edit(); |
122 |
5
|
editor.putString(Constants.PREFERENCES_KEY_REPEAT_MODE, repeatMode.name()); |
123 |
5
|
editor.commit(); |
124 |
|
} |
125 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 2 |
Complexity Density: 0,5 |
|
126 |
31
|
public static boolean isScrobblingEnabled(Context context) {... |
127 |
31
|
if (isOffline(context)) { |
128 |
8
|
return false; |
129 |
|
} |
130 |
23
|
SharedPreferences prefs = getPreferences(context); |
131 |
23
|
return prefs.getBoolean(Constants.PREFERENCES_KEY_SCROBBLE, false); |
132 |
|
} |
133 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0,25 |
|
134 |
8
|
public static void setActiveServer(Context context, int instance) {... |
135 |
8
|
SharedPreferences prefs = getPreferences(context); |
136 |
8
|
SharedPreferences.Editor editor = prefs.edit(); |
137 |
8
|
editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, instance); |
138 |
8
|
editor.commit(); |
139 |
|
} |
140 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
141 |
410
|
public static int getActiveServer(Context context) {... |
142 |
410
|
SharedPreferences prefs = getPreferences(context); |
143 |
410
|
return prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); |
144 |
|
} |
145 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 2 |
Complexity Density: 0,5 |
|
146 |
26
|
public static String getServerName(Context context, int instance) {... |
147 |
26
|
if (instance == 0) { |
148 |
6
|
return context.getResources().getString(R.string.main_offline); |
149 |
|
} |
150 |
20
|
SharedPreferences prefs = getPreferences(context); |
151 |
20
|
return prefs.getString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, null); |
152 |
|
} |
153 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
154 |
36
|
public static void setServerRestVersion(Context context, Version version) {... |
155 |
36
|
SERVER_REST_VERSIONS.put(getActiveServer(context), version); |
156 |
|
} |
157 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
158 |
9
|
public static Version getServerRestVersion(Context context) {... |
159 |
9
|
return SERVER_REST_VERSIONS.get(getActiveServer(context)); |
160 |
|
} |
161 |
|
|
|
|
| 0% |
Uncovered Elements: 5 (5) |
Complexity: 1 |
Complexity Density: 0,2 |
|
162 |
0
|
public static void setSelectedMusicFolderId(Context context, String musicFolderId) {... |
163 |
0
|
int instance = getActiveServer(context); |
164 |
0
|
SharedPreferences prefs = getPreferences(context); |
165 |
0
|
SharedPreferences.Editor editor = prefs.edit(); |
166 |
0
|
editor.putString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, musicFolderId); |
167 |
0
|
editor.commit(); |
168 |
|
} |
169 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0,33 |
|
170 |
7
|
public static String getSelectedMusicFolderId(Context context) {... |
171 |
7
|
SharedPreferences prefs = getPreferences(context); |
172 |
7
|
int instance = getActiveServer(context); |
173 |
7
|
return prefs.getString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null); |
174 |
|
} |
175 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
176 |
62
|
public static String getTheme(Context context) {... |
177 |
62
|
SharedPreferences prefs = getPreferences(context); |
178 |
62
|
return prefs.getString(Constants.PREFERENCES_KEY_THEME, null); |
179 |
|
} |
180 |
|
|
|
|
| 72,7% |
Uncovered Elements: 3 (11) |
Complexity: 3 |
Complexity Density: 0,43 |
|
181 |
164
|
public static int getMaxBitrate(Context context) {... |
182 |
164
|
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); |
183 |
164
|
NetworkInfo networkInfo = manager.getActiveNetworkInfo(); |
184 |
164
|
if (networkInfo == null) { |
185 |
0
|
return 0; |
186 |
|
} |
187 |
|
|
188 |
164
|
boolean wifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI; |
189 |
164
|
SharedPreferences prefs = getPreferences(context); |
190 |
164
|
return Integer.parseInt(prefs.getString(wifi ? Constants.PREFERENCES_KEY_MAX_BITRATE_WIFI : Constants.PREFERENCES_KEY_MAX_BITRATE_MOBILE, "0")); |
191 |
|
} |
192 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (5) |
Complexity: 2 |
Complexity Density: 0,67 |
|
193 |
57
|
public static int getPreloadCount(Context context) {... |
194 |
57
|
SharedPreferences prefs = getPreferences(context); |
195 |
57
|
int preloadCount = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PRELOAD_COUNT, "-1")); |
196 |
57
|
return preloadCount == -1 ? Integer.MAX_VALUE : preloadCount; |
197 |
|
} |
198 |
|
|
|
|
| 80% |
Uncovered Elements: 1 (5) |
Complexity: 2 |
Complexity Density: 0,67 |
|
199 |
21
|
public static int getCacheSizeMB(Context context) {... |
200 |
21
|
SharedPreferences prefs = getPreferences(context); |
201 |
21
|
int cacheSize = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_CACHE_SIZE, "-1")); |
202 |
21
|
return cacheSize == -1 ? Integer.MAX_VALUE : cacheSize; |
203 |
|
} |
204 |
|
|
|
|
| 94,4% |
Uncovered Elements: 1 (18) |
Complexity: 2 |
Complexity Density: 0,12 |
|
205 |
121
|
public static String getRestUrl(Context context, String method) {... |
206 |
121
|
StringBuilder builder = new StringBuilder(); |
207 |
|
|
208 |
121
|
SharedPreferences prefs = getPreferences(context); |
209 |
|
|
210 |
121
|
int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); |
211 |
121
|
String serverUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null); |
212 |
121
|
String username = prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null); |
213 |
121
|
String password = prefs.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null); |
214 |
|
|
215 |
|
|
216 |
121
|
password = "enc:" + Util.utf8HexEncode(password); |
217 |
|
|
218 |
121
|
builder.append(serverUrl); |
219 |
121
|
if (builder.charAt(builder.length() - 1) != '/') { |
220 |
121
|
builder.append("/"); |
221 |
|
} |
222 |
121
|
builder.append("rest/").append(method).append(".view"); |
223 |
121
|
builder.append("?u=").append(username); |
224 |
121
|
builder.append("&p=").append(password); |
225 |
121
|
builder.append("&v=").append(Constants.REST_PROTOCOL_VERSION); |
226 |
121
|
builder.append("&c=").append(Constants.REST_CLIENT_ID); |
227 |
|
|
228 |
121
|
return builder.toString(); |
229 |
|
} |
230 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
231 |
1721
|
public static SharedPreferences getPreferences(Context context) {... |
232 |
1721
|
return context.getSharedPreferences(Constants.PREFERENCES_FILE_NAME, 0); |
233 |
|
} |
234 |
|
|
|
|
| 60% |
Uncovered Elements: 2 (5) |
Complexity: 3 |
Complexity Density: 1 |
|
235 |
50
|
public static String getContentType(HttpEntity entity) {... |
236 |
50
|
if (entity == null || entity.getContentType() == null) { |
237 |
0
|
return null; |
238 |
|
} |
239 |
50
|
return entity.getContentType().getValue(); |
240 |
|
} |
241 |
|
|
|
|
| 0% |
Uncovered Elements: 13 (13) |
Complexity: 2 |
Complexity Density: 0,18 |
|
242 |
0
|
public static int getRemainingTrialDays(Context context) {... |
243 |
0
|
SharedPreferences prefs = getPreferences(context); |
244 |
0
|
long installTime = prefs.getLong(Constants.PREFERENCES_KEY_INSTALL_TIME, 0L); |
245 |
|
|
246 |
0
|
if (installTime == 0L) { |
247 |
0
|
installTime = System.currentTimeMillis(); |
248 |
0
|
SharedPreferences.Editor editor = prefs.edit(); |
249 |
0
|
editor.putLong(Constants.PREFERENCES_KEY_INSTALL_TIME, installTime); |
250 |
0
|
editor.commit(); |
251 |
|
} |
252 |
|
|
253 |
0
|
long now = System.currentTimeMillis(); |
254 |
0
|
long millisPerDay = 24L * 60L * 60L * 1000L; |
255 |
0
|
int daysSinceInstall = (int) ((now - installTime) / millisPerDay); |
256 |
0
|
return Math.max(0, Constants.FREE_TRIAL_DAYS - daysSinceInstall); |
257 |
|
} |
258 |
|
|
259 |
|
|
260 |
|
|
261 |
|
|
262 |
|
|
263 |
|
|
264 |
|
|
265 |
|
@param |
266 |
|
@return |
267 |
|
@throws |
268 |
|
@throws |
269 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0,33 |
|
270 |
33
|
public static byte[] toByteArray(InputStream input) throws IOException {... |
271 |
33
|
ByteArrayOutputStream output = new ByteArrayOutputStream(); |
272 |
33
|
copy(input, output); |
273 |
33
|
return output.toByteArray(); |
274 |
|
} |
275 |
|
|
|
|
| 77,8% |
Uncovered Elements: 2 (9) |
Complexity: 2 |
Complexity Density: 0,29 |
|
276 |
33
|
public static long copy(InputStream input, OutputStream output)... |
277 |
|
throws IOException { |
278 |
33
|
byte[] buffer = new byte[1024 * 4]; |
279 |
33
|
long count = 0; |
280 |
33
|
int n; |
281 |
?
|
while (-1 != (n = input.read(buffer))) { |
282 |
193
|
output.write(buffer, 0, n); |
283 |
193
|
count += n; |
284 |
|
} |
285 |
33
|
return count; |
286 |
|
} |
287 |
|
|
|
|
| 75% |
Uncovered Elements: 5 (20) |
Complexity: 3 |
Complexity Density: 0,17 |
|
288 |
6
|
public static void atomicCopy(File from, File to) throws IOException {... |
289 |
6
|
FileInputStream in = null; |
290 |
6
|
FileOutputStream out = null; |
291 |
6
|
File tmp = null; |
292 |
6
|
try { |
293 |
6
|
tmp = new File(to.getPath() + ".tmp"); |
294 |
6
|
in = new FileInputStream(from); |
295 |
6
|
out = new FileOutputStream(tmp); |
296 |
6
|
in.getChannel().transferTo(0, from.length(), out.getChannel()); |
297 |
6
|
out.close(); |
298 |
6
|
if (!tmp.renameTo(to)) { |
299 |
0
|
throw new IOException("Failed to rename " + tmp + " to " + to); |
300 |
|
} |
301 |
6
|
Log.i(TAG, "Copied " + from + " to " + to); |
302 |
|
} catch (IOException x) { |
303 |
0
|
close(out); |
304 |
0
|
delete(to); |
305 |
0
|
throw x; |
306 |
|
} finally { |
307 |
6
|
close(in); |
308 |
6
|
close(out); |
309 |
6
|
delete(tmp); |
310 |
|
} |
311 |
|
} |
312 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (5) |
Complexity: 3 |
Complexity Density: 1 |
|
313 |
218
|
public static void close(Closeable closeable) {... |
314 |
218
|
try { |
315 |
218
|
if (closeable != null) { |
316 |
216
|
closeable.close(); |
317 |
|
} |
318 |
|
} catch (Throwable x) { |
319 |
|
|
320 |
|
} |
321 |
|
} |
322 |
|
|
|
|
| 70% |
Uncovered Elements: 3 (10) |
Complexity: 4 |
Complexity Density: 0,67 |
|
323 |
81
|
public static boolean delete(File file) {... |
324 |
81
|
if (file != null && file.exists()) { |
325 |
31
|
if (!file.delete()) { |
326 |
0
|
Log.w(TAG, "Failed to delete file " + file); |
327 |
0
|
return false; |
328 |
|
} |
329 |
31
|
Log.i(TAG, "Deleted file " + file); |
330 |
|
} |
331 |
81
|
return true; |
332 |
|
} |
333 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
334 |
16
|
public static void toast(Context context, int messageId) {... |
335 |
16
|
toast(context, messageId, true); |
336 |
|
} |
337 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
338 |
25
|
public static void toast(Context context, int messageId, boolean shortDuration) {... |
339 |
25
|
toast(context, context.getString(messageId), shortDuration); |
340 |
|
} |
341 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
342 |
10
|
public static void toast(Context context, String message) {... |
343 |
10
|
toast(context, message, true); |
344 |
|
} |
345 |
|
|
|
|
| 91,7% |
Uncovered Elements: 1 (12) |
Complexity: 4 |
Complexity Density: 0,67 |
|
346 |
95
|
public static void toast(Context context, String message, boolean shortDuration) {... |
347 |
95
|
if (toast == null) { |
348 |
1
|
toast = Toast.makeText(context, message, shortDuration ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG); |
349 |
1
|
toast.setGravity(Gravity.CENTER, 0, 0); |
350 |
|
} else { |
351 |
94
|
toast.setText(message); |
352 |
94
|
toast.setDuration(shortDuration ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG); |
353 |
|
} |
354 |
95
|
toast.show(); |
355 |
|
} |
356 |
|
|
357 |
|
|
358 |
|
|
359 |
|
|
360 |
|
|
361 |
|
|
362 |
|
|
363 |
|
|
364 |
|
|
365 |
|
|
366 |
|
|
367 |
|
|
368 |
|
@param |
369 |
|
@return |
370 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (16) |
Complexity: 4 |
Complexity Density: 0,4 |
|
371 |
195
|
public static synchronized String formatBytes(long byteCount) {... |
372 |
|
|
373 |
|
|
374 |
195
|
if (byteCount >= 1024 * 1024 * 1024) { |
375 |
42
|
NumberFormat gigaByteFormat = GIGA_BYTE_FORMAT; |
376 |
42
|
return gigaByteFormat.format((double) byteCount / (1024 * 1024 * 1024)); |
377 |
|
} |
378 |
|
|
379 |
|
|
380 |
153
|
if (byteCount >= 1024 * 1024) { |
381 |
104
|
NumberFormat megaByteFormat = MEGA_BYTE_FORMAT; |
382 |
104
|
return megaByteFormat.format((double) byteCount / (1024 * 1024)); |
383 |
|
} |
384 |
|
|
385 |
|
|
386 |
49
|
if (byteCount >= 1024) { |
387 |
12
|
NumberFormat kiloByteFormat = KILO_BYTE_FORMAT; |
388 |
12
|
return kiloByteFormat.format((double) byteCount / 1024); |
389 |
|
} |
390 |
|
|
391 |
37
|
return byteCount + " B"; |
392 |
|
} |
393 |
|
|
394 |
|
|
395 |
|
|
396 |
|
|
397 |
|
|
398 |
|
|
399 |
|
|
400 |
|
|
401 |
|
|
402 |
|
|
403 |
|
|
404 |
|
|
405 |
|
@param |
406 |
|
@return |
407 |
|
|
|
|
| 79,3% |
Uncovered Elements: 6 (29) |
Complexity: 8 |
Complexity Density: 0,53 |
|
408 |
89
|
public static synchronized String formatLocalizedBytes(long byteCount, Context context) {... |
409 |
|
|
410 |
|
|
411 |
89
|
if (byteCount >= 1024 * 1024 * 1024) { |
412 |
0
|
if (GIGA_BYTE_LOCALIZED_FORMAT == null) { |
413 |
0
|
GIGA_BYTE_LOCALIZED_FORMAT = new DecimalFormat(context.getResources().getString(R.string.util_bytes_format_gigabyte)); |
414 |
|
} |
415 |
|
|
416 |
0
|
return GIGA_BYTE_LOCALIZED_FORMAT.format((double) byteCount / (1024 * 1024 * 1024)); |
417 |
|
} |
418 |
|
|
419 |
|
|
420 |
89
|
if (byteCount >= 1024 * 1024) { |
421 |
31
|
if (MEGA_BYTE_LOCALIZED_FORMAT == null) { |
422 |
1
|
MEGA_BYTE_LOCALIZED_FORMAT = new DecimalFormat(context.getResources().getString(R.string.util_bytes_format_megabyte)); |
423 |
|
} |
424 |
|
|
425 |
31
|
return MEGA_BYTE_LOCALIZED_FORMAT.format((double) byteCount / (1024 * 1024)); |
426 |
|
} |
427 |
|
|
428 |
|
|
429 |
58
|
if (byteCount >= 1024) { |
430 |
43
|
if (KILO_BYTE_LOCALIZED_FORMAT == null) { |
431 |
1
|
KILO_BYTE_LOCALIZED_FORMAT = new DecimalFormat(context.getResources().getString(R.string.util_bytes_format_kilobyte)); |
432 |
|
} |
433 |
|
|
434 |
43
|
return KILO_BYTE_LOCALIZED_FORMAT.format((double) byteCount / 1024); |
435 |
|
} |
436 |
|
|
437 |
15
|
if (BYTE_LOCALIZED_FORMAT == null) { |
438 |
1
|
BYTE_LOCALIZED_FORMAT = new DecimalFormat(context.getResources().getString(R.string.util_bytes_format_byte)); |
439 |
|
} |
440 |
|
|
441 |
15
|
return BYTE_LOCALIZED_FORMAT.format((double) byteCount); |
442 |
|
} |
443 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (14) |
Complexity: 3 |
Complexity Density: 0,3 |
|
444 |
697
|
public static String formatDuration(Integer seconds) {... |
445 |
697
|
if (seconds == null) { |
446 |
40
|
return null; |
447 |
|
} |
448 |
|
|
449 |
657
|
int minutes = seconds / 60; |
450 |
657
|
int secs = seconds % 60; |
451 |
|
|
452 |
657
|
StringBuilder builder = new StringBuilder(6); |
453 |
657
|
builder.append(minutes).append(":"); |
454 |
657
|
if (secs < 10) { |
455 |
282
|
builder.append("0"); |
456 |
|
} |
457 |
657
|
builder.append(secs); |
458 |
657
|
return builder.toString(); |
459 |
|
} |
460 |
|
|
|
|
| 77,8% |
Uncovered Elements: 2 (9) |
Complexity: 4 |
Complexity Density: 0,8 |
|
461 |
29
|
public static boolean equals(Object object1, Object object2) {... |
462 |
29
|
if (object1 == object2) { |
463 |
0
|
return true; |
464 |
|
} |
465 |
29
|
if (object1 == null || object2 == null) { |
466 |
1
|
return false; |
467 |
|
} |
468 |
28
|
return object1.equals(object2); |
469 |
|
|
470 |
|
} |
471 |
|
|
472 |
|
|
473 |
|
|
474 |
|
|
475 |
|
@param |
476 |
|
@return |
477 |
|
|
|
|
| 66,7% |
Uncovered Elements: 3 (9) |
Complexity: 3 |
Complexity Density: 0,43 |
|
478 |
121
|
public static String utf8HexEncode(String s) {... |
479 |
121
|
if (s == null) { |
480 |
0
|
return null; |
481 |
|
} |
482 |
121
|
byte[] utf8; |
483 |
121
|
try { |
484 |
121
|
utf8 = s.getBytes(Constants.UTF_8); |
485 |
|
} catch (UnsupportedEncodingException x) { |
486 |
0
|
throw new RuntimeException(x); |
487 |
|
} |
488 |
121
|
return hexEncode(utf8); |
489 |
|
} |
490 |
|
|
491 |
|
|
492 |
|
|
493 |
|
|
494 |
|
|
495 |
|
|
496 |
|
@param |
497 |
|
@return |
498 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (8) |
Complexity: 2 |
Complexity Density: 0,33 |
|
499 |
301
|
public static String hexEncode(byte[] data) {... |
500 |
301
|
int length = data.length; |
501 |
301
|
char[] out = new char[length << 1]; |
502 |
|
|
503 |
3786
|
for (int i = 0, j = 0; i < length; i++) { |
504 |
3485
|
out[j++] = HEX_DIGITS[(0xF0 & data[i]) >>> 4]; |
505 |
3485
|
out[j++] = HEX_DIGITS[0x0F & data[i]]; |
506 |
|
} |
507 |
301
|
return new String(out); |
508 |
|
} |
509 |
|
|
510 |
|
|
511 |
|
|
512 |
|
|
513 |
|
@param |
514 |
|
@return |
515 |
|
|
|
|
| 62,5% |
Uncovered Elements: 3 (8) |
Complexity: 3 |
Complexity Density: 0,5 |
|
516 |
180
|
public static String md5Hex(String s) {... |
517 |
180
|
if (s == null) { |
518 |
0
|
return null; |
519 |
|
} |
520 |
|
|
521 |
180
|
try { |
522 |
180
|
MessageDigest md5 = MessageDigest.getInstance("MD5"); |
523 |
180
|
return hexEncode(md5.digest(s.getBytes(Constants.UTF_8))); |
524 |
|
} catch (Exception x) { |
525 |
0
|
throw new RuntimeException(x.getMessage(), x); |
526 |
|
} |
527 |
|
} |
528 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 1 |
Complexity Density: 0,17 |
|
529 |
172
|
public static boolean isNetworkConnected(Context context) {... |
530 |
172
|
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); |
531 |
172
|
NetworkInfo networkInfo = manager.getActiveNetworkInfo(); |
532 |
172
|
boolean connected = networkInfo != null && networkInfo.isConnected(); |
533 |
|
|
534 |
172
|
boolean wifiConnected = connected && networkInfo.getType() == ConnectivityManager.TYPE_WIFI; |
535 |
172
|
boolean wifiRequired = isWifiRequiredForDownload(context); |
536 |
|
|
537 |
172
|
return connected && (!wifiRequired || wifiConnected); |
538 |
|
} |
539 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
540 |
176
|
public static boolean isExternalStoragePresent() {... |
541 |
176
|
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); |
542 |
|
} |
543 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
544 |
172
|
private static boolean isWifiRequiredForDownload(Context context) {... |
545 |
172
|
SharedPreferences prefs = getPreferences(context); |
546 |
172
|
return prefs.getBoolean(Constants.PREFERENCES_KEY_WIFI_REQUIRED_FOR_DOWNLOAD, false); |
547 |
|
} |
548 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
549 |
1
|
public static void info(Context context, int titleId, int messageId) {... |
550 |
1
|
showDialog(context, android.R.drawable.ic_dialog_info, titleId, messageId); |
551 |
|
} |
552 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
553 |
1
|
private static void showDialog(Context context, int icon, int titleId, int messageId) {... |
554 |
1
|
new AlertDialog.Builder(context) |
555 |
|
.setIcon(icon) |
556 |
|
.setTitle(titleId) |
557 |
|
.setMessage(messageId) |
558 |
|
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { |
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
559 |
1
|
@Override... |
560 |
|
public void onClick(DialogInterface dialog, int i) { |
561 |
1
|
dialog.dismiss(); |
562 |
|
} |
563 |
|
}) |
564 |
|
.show(); |
565 |
|
} |
566 |
|
|
|
|
| 92% |
Uncovered Elements: 2 (25) |
Complexity: 3 |
Complexity Density: 0,13 |
|
567 |
29
|
public static void showPlayingNotification(final Context context, final DownloadServiceImpl downloadService, Handler handler, MusicDirectory.Entry song) {... |
568 |
|
|
569 |
|
|
570 |
29
|
String title = song.getTitle(); |
571 |
29
|
String text = song.getArtist(); |
572 |
29
|
String album = song.getAlbum(); |
573 |
|
|
574 |
|
|
575 |
29
|
final Notification notification = new Notification(R.drawable.ic_stat_subsonic, title, System.currentTimeMillis()); |
576 |
29
|
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; |
577 |
|
|
578 |
29
|
RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.notification); |
579 |
|
|
580 |
|
|
581 |
29
|
try { |
582 |
29
|
int size = context.getResources().getDrawable(R.drawable.unknown_album).getIntrinsicHeight(); |
583 |
29
|
Bitmap bitmap = FileUtil.getAlbumArtBitmap(context, song, size); |
584 |
29
|
if (bitmap == null) { |
585 |
|
|
586 |
7
|
contentView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album); |
587 |
|
} else { |
588 |
22
|
contentView.setImageViewBitmap(R.id.notification_image, bitmap); |
589 |
|
} |
590 |
|
} catch (Exception x) { |
591 |
0
|
Log.w(TAG, "Failed to get notification cover art", x); |
592 |
0
|
contentView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album); |
593 |
|
} |
594 |
|
|
595 |
|
|
596 |
29
|
contentView.setTextViewText(R.id.trackname, title); |
597 |
29
|
contentView.setTextViewText(R.id.artist, text); |
598 |
29
|
contentView.setTextViewText(R.id.album, album); |
599 |
|
|
600 |
29
|
notification.contentView = contentView; |
601 |
|
|
602 |
29
|
Intent notificationIntent = new Intent(context, DownloadActivity.class); |
603 |
29
|
notification.contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); |
604 |
|
|
605 |
|
|
606 |
29
|
handler.post(new Runnable() { |
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
607 |
29
|
@Override... |
608 |
|
public void run() { |
609 |
29
|
startForeground(downloadService, Constants.NOTIFICATION_ID_PLAYING, notification); |
610 |
|
} |
611 |
|
}); |
612 |
|
|
613 |
|
|
614 |
29
|
linkButtons(context, contentView, false); |
615 |
29
|
SubsonicAppWidgetProvider4x1.getInstance().notifyChange(context, downloadService, true); |
616 |
|
} |
617 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
618 |
18
|
public static void hidePlayingNotification(final Context context, final DownloadServiceImpl downloadService, Handler handler) {... |
619 |
|
|
620 |
|
|
621 |
18
|
handler.post(new Runnable() { |
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
622 |
18
|
@Override... |
623 |
|
public void run() { |
624 |
18
|
stopForeground(downloadService, true); |
625 |
|
} |
626 |
|
}); |
627 |
|
|
628 |
|
|
629 |
18
|
SubsonicAppWidgetProvider4x1.getInstance().notifyChange(context, downloadService, false); |
630 |
|
} |
631 |
|
|
|
|
| 66,7% |
Uncovered Elements: 1 (3) |
Complexity: 2 |
Complexity Density: 0,67 |
|
632 |
101
|
public static void sleepQuietly(long millis) {... |
633 |
101
|
try { |
634 |
101
|
Thread.sleep(millis); |
635 |
|
} catch (InterruptedException x) { |
636 |
0
|
Log.w(TAG, "Interrupted from sleep.", x); |
637 |
|
} |
638 |
|
} |
639 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
640 |
6
|
public static void startActivityWithoutTransition(Activity currentActivity, Class<? extends Activity> newActivitiy) {... |
641 |
6
|
startActivityWithoutTransition(currentActivity, new Intent(currentActivity, newActivitiy)); |
642 |
|
} |
643 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
644 |
42
|
public static void startActivityWithoutTransition(Activity currentActivity, Intent intent) {... |
645 |
42
|
currentActivity.startActivity(intent); |
646 |
42
|
disablePendingTransition(currentActivity); |
647 |
|
} |
648 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 2 |
Complexity Density: 0,67 |
|
649 |
46
|
public static void disablePendingTransition(Activity activity) {... |
650 |
|
|
651 |
|
|
652 |
|
|
653 |
46
|
try { |
654 |
46
|
Method method = Activity.class.getMethod("overridePendingTransition", int.class, int.class); |
655 |
46
|
method.invoke(activity, 0, 0); |
656 |
|
} catch (Throwable x) { |
657 |
|
|
658 |
|
} |
659 |
|
} |
660 |
|
|
|
|
| 75% |
Uncovered Elements: 1 (4) |
Complexity: 2 |
Complexity Density: 0,5 |
|
661 |
36
|
public static Drawable createDrawableFromBitmap(Context context, Bitmap bitmap) {... |
662 |
|
|
663 |
|
|
664 |
36
|
try { |
665 |
36
|
Constructor<BitmapDrawable> constructor = BitmapDrawable.class.getConstructor(Resources.class, Bitmap.class); |
666 |
36
|
return constructor.newInstance(context.getResources(), bitmap); |
667 |
|
} catch (Throwable x) { |
668 |
0
|
return new BitmapDrawable(bitmap); |
669 |
|
} |
670 |
|
} |
671 |
|
|
|
|
| 90% |
Uncovered Elements: 1 (10) |
Complexity: 3 |
Complexity Density: 0,38 |
|
672 |
52
|
public static void registerMediaButtonEventReceiver(Context context) {... |
673 |
|
|
674 |
|
|
675 |
52
|
SharedPreferences prefs = getPreferences(context); |
676 |
52
|
boolean enabled = prefs.getBoolean(Constants.PREFERENCES_KEY_MEDIA_BUTTONS, true); |
677 |
|
|
678 |
52
|
if (enabled) { |
679 |
|
|
680 |
|
|
681 |
|
|
682 |
52
|
try { |
683 |
52
|
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); |
684 |
52
|
ComponentName componentName = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); |
685 |
52
|
Method method = AudioManager.class.getMethod("registerMediaButtonEventReceiver", ComponentName.class); |
686 |
52
|
method.invoke(audioManager, componentName); |
687 |
|
} catch (Throwable x) { |
688 |
|
|
689 |
|
} |
690 |
|
} |
691 |
|
} |
692 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (5) |
Complexity: 2 |
Complexity Density: 0,4 |
|
693 |
1
|
public static void unregisterMediaButtonEventReceiver(Context context) {... |
694 |
|
|
695 |
|
|
696 |
1
|
try { |
697 |
1
|
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); |
698 |
1
|
ComponentName componentName = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); |
699 |
1
|
Method method = AudioManager.class.getMethod("unregisterMediaButtonEventReceiver", ComponentName.class); |
700 |
1
|
method.invoke(audioManager, componentName); |
701 |
|
} catch (Throwable x) { |
702 |
|
|
703 |
|
} |
704 |
|
} |
705 |
|
|
|
|
| 57,1% |
Uncovered Elements: 3 (7) |
Complexity: 2 |
Complexity Density: 0,29 |
|
706 |
29
|
private static void startForeground(Service service, int notificationId, Notification notification) {... |
707 |
|
|
708 |
|
|
709 |
29
|
try { |
710 |
29
|
Method method = Service.class.getMethod("startForeground", int.class, Notification.class); |
711 |
29
|
method.invoke(service, notificationId, notification); |
712 |
29
|
Log.i(TAG, "Successfully invoked Service.startForeground()"); |
713 |
|
} catch (Throwable x) { |
714 |
0
|
NotificationManager notificationManager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE); |
715 |
0
|
notificationManager.notify(Constants.NOTIFICATION_ID_PLAYING, notification); |
716 |
0
|
Log.i(TAG, "Service.startForeground() not available. Using work-around."); |
717 |
|
} |
718 |
|
} |
719 |
|
|
|
|
| 57,1% |
Uncovered Elements: 3 (7) |
Complexity: 2 |
Complexity Density: 0,29 |
|
720 |
18
|
private static void stopForeground(Service service, boolean removeNotification) {... |
721 |
|
|
722 |
|
|
723 |
18
|
try { |
724 |
18
|
Method method = Service.class.getMethod("stopForeground", boolean.class); |
725 |
18
|
method.invoke(service, removeNotification); |
726 |
18
|
Log.i(TAG, "Successfully invoked Service.stopForeground()"); |
727 |
|
} catch (Throwable x) { |
728 |
0
|
NotificationManager notificationManager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE); |
729 |
0
|
notificationManager.cancel(Constants.NOTIFICATION_ID_PLAYING); |
730 |
0
|
Log.i(TAG, "Service.stopForeground() not available. Using work-around."); |
731 |
|
} |
732 |
|
} |
733 |
|
|
734 |
|
|
735 |
|
|
736 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (14) |
Complexity: 2 |
Complexity Density: 0,17 |
|
737 |
38
|
public static void broadcastNewTrackInfo(Context context, MusicDirectory.Entry song) {... |
738 |
38
|
Intent intent = new Intent(EVENT_META_CHANGED); |
739 |
|
|
740 |
38
|
if (song != null) { |
741 |
26
|
intent.putExtra("title", song.getTitle()); |
742 |
26
|
intent.putExtra("artist", song.getArtist()); |
743 |
26
|
intent.putExtra("album", song.getAlbum()); |
744 |
|
|
745 |
26
|
File albumArtFile = FileUtil.getAlbumArtFile(context, song); |
746 |
26
|
intent.putExtra("coverart", albumArtFile.getAbsolutePath()); |
747 |
|
} else { |
748 |
12
|
intent.putExtra("title", ""); |
749 |
12
|
intent.putExtra("artist", ""); |
750 |
12
|
intent.putExtra("album", ""); |
751 |
12
|
intent.putExtra("coverart", ""); |
752 |
|
} |
753 |
|
|
754 |
38
|
context.sendBroadcast(intent); |
755 |
|
} |
756 |
|
|
757 |
|
|
758 |
|
|
759 |
|
|
|
|
| 82,4% |
Uncovered Elements: 3 (17) |
Complexity: 5 |
Complexity Density: 0,29 |
|
760 |
197
|
public static void broadcastPlaybackStatusChange(Context context, PlayerState state) {... |
761 |
197
|
Intent intent = new Intent(EVENT_PLAYSTATE_CHANGED); |
762 |
|
|
763 |
197
|
switch (state) { |
764 |
27
|
case STARTED: |
765 |
27
|
intent.putExtra("state", "play"); |
766 |
27
|
break; |
767 |
0
|
case STOPPED: |
768 |
0
|
intent.putExtra("state", "stop"); |
769 |
0
|
break; |
770 |
6
|
case PAUSED: |
771 |
6
|
intent.putExtra("state", "pause"); |
772 |
6
|
break; |
773 |
4
|
case COMPLETED: |
774 |
4
|
intent.putExtra("state", "complete"); |
775 |
4
|
break; |
776 |
160
|
default: |
777 |
160
|
return; |
778 |
|
} |
779 |
|
|
780 |
37
|
context.sendBroadcast(intent); |
781 |
|
} |
782 |
|
|
|
|
| 95,2% |
Uncovered Elements: 1 (21) |
Complexity: 2 |
Complexity Density: 0,11 |
|
783 |
29
|
private static void linkButtons(Context context, RemoteViews views, boolean playerActive) {... |
784 |
|
|
785 |
29
|
Intent intent = new Intent(context, playerActive ? DownloadActivity.class : MainActivity.class); |
786 |
29
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); |
787 |
29
|
views.setOnClickPendingIntent(R.id.appwidget_coverart, pendingIntent); |
788 |
29
|
views.setOnClickPendingIntent(R.id.appwidget_top, pendingIntent); |
789 |
|
|
790 |
|
|
791 |
29
|
intent = new Intent("1"); |
792 |
29
|
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); |
793 |
29
|
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); |
794 |
29
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0); |
795 |
29
|
views.setOnClickPendingIntent(R.id.control_play, pendingIntent); |
796 |
|
|
797 |
29
|
intent = new Intent("2"); |
798 |
29
|
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); |
799 |
29
|
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); |
800 |
29
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0); |
801 |
29
|
views.setOnClickPendingIntent(R.id.control_next, pendingIntent); |
802 |
|
|
803 |
29
|
intent = new Intent("3"); |
804 |
29
|
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); |
805 |
29
|
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); |
806 |
29
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0); |
807 |
29
|
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent); |
808 |
|
} |
809 |
|
} |