mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
chore: formatting
This commit is contained in:
parent
35af1f9038
commit
45793c343a
5 changed files with 486 additions and 469 deletions
|
|
@ -15,47 +15,48 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public final class WidgetActions {
|
||||
public static void dispatchToMediaSession(Context ctx, String action) {
|
||||
Log.d("TempoWidget", "dispatch action=" + action);
|
||||
Context appCtx = ctx.getApplicationContext();
|
||||
SessionToken token = new SessionToken(appCtx, new ComponentName(appCtx, MediaService.class));
|
||||
ListenableFuture<MediaController> future = new MediaController.Builder(appCtx, token).buildAsync();
|
||||
future.addListener(() -> {
|
||||
try {
|
||||
if (!future.isDone()) return;
|
||||
MediaController c = future.get();
|
||||
Log.d("TempoWidget", "controller connected, isPlaying=" + c.isPlaying());
|
||||
switch (action) {
|
||||
case WidgetProvider.ACT_PLAY_PAUSE:
|
||||
if (c.isPlaying()) c.pause(); else c.play();
|
||||
break;
|
||||
case WidgetProvider.ACT_NEXT:
|
||||
c.seekToNext();
|
||||
break;
|
||||
case WidgetProvider.ACT_PREV:
|
||||
c.seekToPrevious();
|
||||
break;
|
||||
case WidgetProvider.ACT_TOGGLE_SHUFFLE:
|
||||
c.setShuffleModeEnabled(!c.getShuffleModeEnabled());
|
||||
break;
|
||||
case WidgetProvider.ACT_CYCLE_REPEAT:
|
||||
int repeatMode = c.getRepeatMode();
|
||||
int nextMode;
|
||||
if (repeatMode == Player.REPEAT_MODE_OFF) {
|
||||
nextMode = Player.REPEAT_MODE_ALL;
|
||||
} else if (repeatMode == Player.REPEAT_MODE_ALL) {
|
||||
nextMode = Player.REPEAT_MODE_ONE;
|
||||
} else {
|
||||
nextMode = Player.REPEAT_MODE_OFF;
|
||||
public static void dispatchToMediaSession(Context ctx, String action) {
|
||||
Log.d("TempoWidget", "dispatch action=" + action);
|
||||
Context appCtx = ctx.getApplicationContext();
|
||||
SessionToken token = new SessionToken(appCtx, new ComponentName(appCtx, MediaService.class));
|
||||
ListenableFuture<MediaController> future = new MediaController.Builder(appCtx, token).buildAsync();
|
||||
future.addListener(() -> {
|
||||
try {
|
||||
if (!future.isDone()) return;
|
||||
MediaController c = future.get();
|
||||
Log.d("TempoWidget", "controller connected, isPlaying=" + c.isPlaying());
|
||||
switch (action) {
|
||||
case WidgetProvider.ACT_PLAY_PAUSE:
|
||||
if (c.isPlaying()) c.pause();
|
||||
else c.play();
|
||||
break;
|
||||
case WidgetProvider.ACT_NEXT:
|
||||
c.seekToNext();
|
||||
break;
|
||||
case WidgetProvider.ACT_PREV:
|
||||
c.seekToPrevious();
|
||||
break;
|
||||
case WidgetProvider.ACT_TOGGLE_SHUFFLE:
|
||||
c.setShuffleModeEnabled(!c.getShuffleModeEnabled());
|
||||
break;
|
||||
case WidgetProvider.ACT_CYCLE_REPEAT:
|
||||
int repeatMode = c.getRepeatMode();
|
||||
int nextMode;
|
||||
if (repeatMode == Player.REPEAT_MODE_OFF) {
|
||||
nextMode = Player.REPEAT_MODE_ALL;
|
||||
} else if (repeatMode == Player.REPEAT_MODE_ALL) {
|
||||
nextMode = Player.REPEAT_MODE_ONE;
|
||||
} else {
|
||||
nextMode = Player.REPEAT_MODE_OFF;
|
||||
}
|
||||
c.setRepeatMode(nextMode);
|
||||
break;
|
||||
}
|
||||
WidgetUpdateManager.refreshFromController(ctx);
|
||||
c.release();
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e("TempoWidget", "dispatch failed", e);
|
||||
}
|
||||
c.setRepeatMode(nextMode);
|
||||
break;
|
||||
}
|
||||
WidgetUpdateManager.refreshFromController(ctx);
|
||||
c.release();
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e("TempoWidget", "dispatch failed", e);
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ import android.content.Intent;
|
|||
import android.widget.RemoteViews;
|
||||
|
||||
import com.cappielloantonio.tempo.R;
|
||||
|
||||
import android.app.TaskStackBuilder;
|
||||
import android.app.PendingIntent;
|
||||
|
||||
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class WidgetProvider extends AppWidgetProvider {
|
||||
|
|
@ -21,7 +24,8 @@ public class WidgetProvider extends AppWidgetProvider {
|
|||
public static final String ACT_TOGGLE_SHUFFLE = "tempo.widget.SHUFFLE";
|
||||
public static final String ACT_CYCLE_REPEAT = "tempo.widget.REPEAT";
|
||||
|
||||
@Override public void onUpdate(Context ctx, AppWidgetManager mgr, int[] ids) {
|
||||
@Override
|
||||
public void onUpdate(Context ctx, AppWidgetManager mgr, int[] ids) {
|
||||
for (int id : ids) {
|
||||
RemoteViews rv = WidgetUpdateManager.chooseBuild(ctx, id);
|
||||
attachIntents(ctx, rv, id);
|
||||
|
|
@ -29,7 +33,8 @@ public class WidgetProvider extends AppWidgetProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@Override public void onReceive(Context ctx, Intent intent) {
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent intent) {
|
||||
super.onReceive(ctx, intent);
|
||||
String a = intent.getAction();
|
||||
Log.d(TAG, "onReceive action=" + a);
|
||||
|
|
@ -41,7 +46,8 @@ public class WidgetProvider extends AppWidgetProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@Override public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, android.os.Bundle newOptions) {
|
||||
@Override
|
||||
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, android.os.Bundle newOptions) {
|
||||
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
|
||||
RemoteViews rv = WidgetUpdateManager.chooseBuild(context, appWidgetId);
|
||||
attachIntents(context, rv, appWidgetId);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,6 @@ package com.cappielloantonio.tempo.widget;
|
|||
* AppWidget provider entry for the 4x1 widget card. Inherits all behavior
|
||||
* from {@link WidgetProvider}.
|
||||
*/
|
||||
public class WidgetProvider4x1 extends WidgetProvider {}
|
||||
public class WidgetProvider4x1 extends WidgetProvider {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,263 +6,271 @@ import android.content.Context;
|
|||
import android.graphics.Bitmap;
|
||||
import android.text.TextUtils;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.tempo.R;
|
||||
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.session.MediaController;
|
||||
import androidx.media3.session.SessionToken;
|
||||
|
||||
import com.cappielloantonio.tempo.service.MediaService;
|
||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public final class WidgetUpdateManager {
|
||||
|
||||
public static void updateFromState(Context ctx,
|
||||
String title,
|
||||
String artist,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode,
|
||||
long positionMs,
|
||||
long durationMs) {
|
||||
if (TextUtils.isEmpty(title)) title = ctx.getString(R.string.widget_not_playing);
|
||||
if (TextUtils.isEmpty(artist)) artist = ctx.getString(R.string.widget_placeholder_subtitle);
|
||||
if (TextUtils.isEmpty(album)) album = "";
|
||||
public static void updateFromState(Context ctx,
|
||||
String title,
|
||||
String artist,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode,
|
||||
long positionMs,
|
||||
long durationMs) {
|
||||
if (TextUtils.isEmpty(title)) title = ctx.getString(R.string.widget_not_playing);
|
||||
if (TextUtils.isEmpty(artist)) artist = ctx.getString(R.string.widget_placeholder_subtitle);
|
||||
if (TextUtils.isEmpty(album)) album = "";
|
||||
|
||||
final TimingInfo timing = createTimingInfo(positionMs, durationMs);
|
||||
final TimingInfo timing = createTimingInfo(positionMs, durationMs);
|
||||
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(ctx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(ctx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(ctx, title, artist, album, art, playing,
|
||||
timing.elapsedText, timing.totalText, timing.progress, shuffleEnabled, repeatMode, id);
|
||||
WidgetProvider.attachIntents(ctx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
|
||||
public static void pushNow(Context ctx) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(ctx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(ctx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = chooseBuild(ctx, id);
|
||||
WidgetProvider.attachIntents(ctx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateFromState(Context ctx,
|
||||
String title,
|
||||
String artist,
|
||||
String album,
|
||||
String coverArtId,
|
||||
boolean playing,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode,
|
||||
long positionMs,
|
||||
long durationMs) {
|
||||
final Context appCtx = ctx.getApplicationContext();
|
||||
final String t = TextUtils.isEmpty(title) ? appCtx.getString(R.string.widget_not_playing) : title;
|
||||
final String a = TextUtils.isEmpty(artist) ? appCtx.getString(R.string.widget_placeholder_subtitle) : artist;
|
||||
final String alb = !TextUtils.isEmpty(album) ? album : "";
|
||||
final boolean p = playing;
|
||||
final boolean sh = shuffleEnabled;
|
||||
final int rep = repeatMode;
|
||||
final TimingInfo timing = createTimingInfo(positionMs, durationMs);
|
||||
|
||||
if (!TextUtils.isEmpty(coverArtId)) {
|
||||
CustomGlideRequest.loadAlbumArtBitmap(
|
||||
appCtx,
|
||||
coverArtId,
|
||||
com.cappielloantonio.tempo.util.Preferences.getImageSize(),
|
||||
new CustomTarget<Bitmap>() {
|
||||
@Override public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(appCtx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(appCtx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(appCtx, t, a, alb, resource, p,
|
||||
timing.elapsedText, timing.totalText, timing.progress, sh, rep, id);
|
||||
WidgetProvider.attachIntents(appCtx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onLoadCleared(Drawable placeholder) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(appCtx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(appCtx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(appCtx, t, a, alb, null, p,
|
||||
timing.elapsedText, timing.totalText, timing.progress, sh, rep, id);
|
||||
WidgetProvider.attachIntents(appCtx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(appCtx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(appCtx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(appCtx, t, a, alb, null, p,
|
||||
timing.elapsedText, timing.totalText, timing.progress, sh, rep, id);
|
||||
WidgetProvider.attachIntents(appCtx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshFromController(Context ctx) {
|
||||
final Context appCtx = ctx.getApplicationContext();
|
||||
SessionToken token = new SessionToken(appCtx, new ComponentName(appCtx, MediaService.class));
|
||||
ListenableFuture<MediaController> future = new MediaController.Builder(appCtx, token).buildAsync();
|
||||
future.addListener(() -> {
|
||||
try {
|
||||
if (!future.isDone()) return;
|
||||
MediaController c = future.get();
|
||||
androidx.media3.common.MediaItem mi = c.getCurrentMediaItem();
|
||||
String title = null, artist = null, album = null, coverId = null;
|
||||
if (mi != null && mi.mediaMetadata != null) {
|
||||
if (mi.mediaMetadata.title != null) title = mi.mediaMetadata.title.toString();
|
||||
if (mi.mediaMetadata.artist != null) artist = mi.mediaMetadata.artist.toString();
|
||||
if (mi.mediaMetadata.albumTitle != null) album = mi.mediaMetadata.albumTitle.toString();
|
||||
if (mi.mediaMetadata.extras != null) {
|
||||
if (title == null) title = mi.mediaMetadata.extras.getString("title");
|
||||
if (artist == null) artist = mi.mediaMetadata.extras.getString("artist");
|
||||
if (album == null) album = mi.mediaMetadata.extras.getString("album");
|
||||
coverId = mi.mediaMetadata.extras.getString("coverArtId");
|
||||
}
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(ctx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(ctx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(ctx, title, artist, album, art, playing,
|
||||
timing.elapsedText, timing.totalText, timing.progress, shuffleEnabled, repeatMode, id);
|
||||
WidgetProvider.attachIntents(ctx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
long position = c.getCurrentPosition();
|
||||
long duration = c.getDuration();
|
||||
if (position == C.TIME_UNSET) position = 0;
|
||||
if (duration == C.TIME_UNSET) duration = 0;
|
||||
updateFromState(appCtx,
|
||||
title != null ? title : appCtx.getString(R.string.widget_not_playing),
|
||||
artist != null ? artist : appCtx.getString(R.string.widget_placeholder_subtitle),
|
||||
album,
|
||||
coverId,
|
||||
c.isPlaying(),
|
||||
c.getShuffleModeEnabled(),
|
||||
c.getRepeatMode(),
|
||||
position,
|
||||
duration);
|
||||
c.release();
|
||||
} catch (ExecutionException | InterruptedException ignored) {
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
private static TimingInfo createTimingInfo(long positionMs, long durationMs) {
|
||||
long safePosition = Math.max(0L, positionMs);
|
||||
long safeDuration = durationMs > 0 ? durationMs : 0L;
|
||||
if (safeDuration > 0 && safePosition > safeDuration) {
|
||||
safePosition = safeDuration;
|
||||
}
|
||||
|
||||
String elapsed = (safeDuration > 0 || safePosition > 0)
|
||||
? MusicUtil.getReadableDurationString(safePosition, true)
|
||||
: null;
|
||||
String total = safeDuration > 0
|
||||
? MusicUtil.getReadableDurationString(safeDuration, true)
|
||||
: null;
|
||||
|
||||
int progress = 0;
|
||||
if (safeDuration > 0) {
|
||||
long scaled = safePosition * WidgetViewsFactory.PROGRESS_MAX;
|
||||
long progressLong = scaled / safeDuration;
|
||||
if (progressLong < 0) {
|
||||
progress = 0;
|
||||
} else if (progressLong > WidgetViewsFactory.PROGRESS_MAX) {
|
||||
progress = WidgetViewsFactory.PROGRESS_MAX;
|
||||
} else {
|
||||
progress = (int) progressLong;
|
||||
}
|
||||
public static void pushNow(Context ctx) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(ctx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(ctx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = chooseBuild(ctx, id);
|
||||
WidgetProvider.attachIntents(ctx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return new TimingInfo(elapsed, total, progress);
|
||||
}
|
||||
public static void updateFromState(Context ctx,
|
||||
String title,
|
||||
String artist,
|
||||
String album,
|
||||
String coverArtId,
|
||||
boolean playing,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode,
|
||||
long positionMs,
|
||||
long durationMs) {
|
||||
final Context appCtx = ctx.getApplicationContext();
|
||||
final String t = TextUtils.isEmpty(title) ? appCtx.getString(R.string.widget_not_playing) : title;
|
||||
final String a = TextUtils.isEmpty(artist) ? appCtx.getString(R.string.widget_placeholder_subtitle) : artist;
|
||||
final String alb = !TextUtils.isEmpty(album) ? album : "";
|
||||
final boolean p = playing;
|
||||
final boolean sh = shuffleEnabled;
|
||||
final int rep = repeatMode;
|
||||
final TimingInfo timing = createTimingInfo(positionMs, durationMs);
|
||||
|
||||
public static android.widget.RemoteViews chooseBuild(Context ctx, int appWidgetId) {
|
||||
LayoutSize size = resolveLayoutSize(ctx, appWidgetId);
|
||||
switch (size) {
|
||||
case MEDIUM:
|
||||
return WidgetViewsFactory.buildMedium(ctx);
|
||||
case LARGE:
|
||||
return WidgetViewsFactory.buildLarge(ctx);
|
||||
case EXPANDED:
|
||||
return WidgetViewsFactory.buildExpanded(ctx);
|
||||
case COMPACT:
|
||||
default:
|
||||
return WidgetViewsFactory.buildCompact(ctx);
|
||||
if (!TextUtils.isEmpty(coverArtId)) {
|
||||
CustomGlideRequest.loadAlbumArtBitmap(
|
||||
appCtx,
|
||||
coverArtId,
|
||||
com.cappielloantonio.tempo.util.Preferences.getImageSize(),
|
||||
new CustomTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(appCtx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(appCtx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(appCtx, t, a, alb, resource, p,
|
||||
timing.elapsedText, timing.totalText, timing.progress, sh, rep, id);
|
||||
WidgetProvider.attachIntents(appCtx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(appCtx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(appCtx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(appCtx, t, a, alb, null, p,
|
||||
timing.elapsedText, timing.totalText, timing.progress, sh, rep, id);
|
||||
WidgetProvider.attachIntents(appCtx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(appCtx);
|
||||
int[] ids = mgr.getAppWidgetIds(new ComponentName(appCtx, WidgetProvider4x1.class));
|
||||
for (int id : ids) {
|
||||
android.widget.RemoteViews rv = choosePopulate(appCtx, t, a, alb, null, p,
|
||||
timing.elapsedText, timing.totalText, timing.progress, sh, rep, id);
|
||||
WidgetProvider.attachIntents(appCtx, rv, id);
|
||||
mgr.updateAppWidget(id, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static android.widget.RemoteViews choosePopulate(Context ctx,
|
||||
String title,
|
||||
String artist,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode,
|
||||
int appWidgetId) {
|
||||
LayoutSize size = resolveLayoutSize(ctx, appWidgetId);
|
||||
switch (size) {
|
||||
case MEDIUM:
|
||||
return WidgetViewsFactory.populateMedium(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
case LARGE:
|
||||
return WidgetViewsFactory.populateLarge(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
case EXPANDED:
|
||||
return WidgetViewsFactory.populateExpanded(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
case COMPACT:
|
||||
default:
|
||||
return WidgetViewsFactory.populateCompact(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
public static void refreshFromController(Context ctx) {
|
||||
final Context appCtx = ctx.getApplicationContext();
|
||||
SessionToken token = new SessionToken(appCtx, new ComponentName(appCtx, MediaService.class));
|
||||
ListenableFuture<MediaController> future = new MediaController.Builder(appCtx, token).buildAsync();
|
||||
future.addListener(() -> {
|
||||
try {
|
||||
if (!future.isDone()) return;
|
||||
MediaController c = future.get();
|
||||
androidx.media3.common.MediaItem mi = c.getCurrentMediaItem();
|
||||
String title = null, artist = null, album = null, coverId = null;
|
||||
if (mi != null && mi.mediaMetadata != null) {
|
||||
if (mi.mediaMetadata.title != null) title = mi.mediaMetadata.title.toString();
|
||||
if (mi.mediaMetadata.artist != null)
|
||||
artist = mi.mediaMetadata.artist.toString();
|
||||
if (mi.mediaMetadata.albumTitle != null)
|
||||
album = mi.mediaMetadata.albumTitle.toString();
|
||||
if (mi.mediaMetadata.extras != null) {
|
||||
if (title == null) title = mi.mediaMetadata.extras.getString("title");
|
||||
if (artist == null) artist = mi.mediaMetadata.extras.getString("artist");
|
||||
if (album == null) album = mi.mediaMetadata.extras.getString("album");
|
||||
coverId = mi.mediaMetadata.extras.getString("coverArtId");
|
||||
}
|
||||
}
|
||||
long position = c.getCurrentPosition();
|
||||
long duration = c.getDuration();
|
||||
if (position == C.TIME_UNSET) position = 0;
|
||||
if (duration == C.TIME_UNSET) duration = 0;
|
||||
updateFromState(appCtx,
|
||||
title != null ? title : appCtx.getString(R.string.widget_not_playing),
|
||||
artist != null ? artist : appCtx.getString(R.string.widget_placeholder_subtitle),
|
||||
album,
|
||||
coverId,
|
||||
c.isPlaying(),
|
||||
c.getShuffleModeEnabled(),
|
||||
c.getRepeatMode(),
|
||||
position,
|
||||
duration);
|
||||
c.release();
|
||||
} catch (ExecutionException | InterruptedException ignored) {
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
private static LayoutSize resolveLayoutSize(Context ctx, int appWidgetId) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(ctx);
|
||||
android.os.Bundle opts = mgr.getAppWidgetOptions(appWidgetId);
|
||||
int minH = opts != null ? opts.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) : 0;
|
||||
int expandedThreshold = ctx.getResources().getInteger(R.integer.widget_expanded_min_height_dp);
|
||||
int largeThreshold = ctx.getResources().getInteger(R.integer.widget_large_min_height_dp);
|
||||
int mediumThreshold = ctx.getResources().getInteger(R.integer.widget_medium_min_height_dp);
|
||||
if (minH >= expandedThreshold) return LayoutSize.EXPANDED;
|
||||
if (minH >= largeThreshold) return LayoutSize.LARGE;
|
||||
if (minH >= mediumThreshold) return LayoutSize.MEDIUM;
|
||||
return LayoutSize.COMPACT;
|
||||
}
|
||||
private static TimingInfo createTimingInfo(long positionMs, long durationMs) {
|
||||
long safePosition = Math.max(0L, positionMs);
|
||||
long safeDuration = durationMs > 0 ? durationMs : 0L;
|
||||
if (safeDuration > 0 && safePosition > safeDuration) {
|
||||
safePosition = safeDuration;
|
||||
}
|
||||
|
||||
private enum LayoutSize {
|
||||
COMPACT,
|
||||
MEDIUM,
|
||||
LARGE,
|
||||
EXPANDED
|
||||
}
|
||||
String elapsed = (safeDuration > 0 || safePosition > 0)
|
||||
? MusicUtil.getReadableDurationString(safePosition, true)
|
||||
: null;
|
||||
String total = safeDuration > 0
|
||||
? MusicUtil.getReadableDurationString(safeDuration, true)
|
||||
: null;
|
||||
|
||||
private static final class TimingInfo {
|
||||
final String elapsedText;
|
||||
final String totalText;
|
||||
final int progress;
|
||||
int progress = 0;
|
||||
if (safeDuration > 0) {
|
||||
long scaled = safePosition * WidgetViewsFactory.PROGRESS_MAX;
|
||||
long progressLong = scaled / safeDuration;
|
||||
if (progressLong < 0) {
|
||||
progress = 0;
|
||||
} else if (progressLong > WidgetViewsFactory.PROGRESS_MAX) {
|
||||
progress = WidgetViewsFactory.PROGRESS_MAX;
|
||||
} else {
|
||||
progress = (int) progressLong;
|
||||
}
|
||||
}
|
||||
|
||||
TimingInfo(String elapsedText, String totalText, int progress) {
|
||||
this.elapsedText = elapsedText;
|
||||
this.totalText = totalText;
|
||||
this.progress = progress;
|
||||
return new TimingInfo(elapsed, total, progress);
|
||||
}
|
||||
|
||||
public static android.widget.RemoteViews chooseBuild(Context ctx, int appWidgetId) {
|
||||
LayoutSize size = resolveLayoutSize(ctx, appWidgetId);
|
||||
switch (size) {
|
||||
case MEDIUM:
|
||||
return WidgetViewsFactory.buildMedium(ctx);
|
||||
case LARGE:
|
||||
return WidgetViewsFactory.buildLarge(ctx);
|
||||
case EXPANDED:
|
||||
return WidgetViewsFactory.buildExpanded(ctx);
|
||||
case COMPACT:
|
||||
default:
|
||||
return WidgetViewsFactory.buildCompact(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private static android.widget.RemoteViews choosePopulate(Context ctx,
|
||||
String title,
|
||||
String artist,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode,
|
||||
int appWidgetId) {
|
||||
LayoutSize size = resolveLayoutSize(ctx, appWidgetId);
|
||||
switch (size) {
|
||||
case MEDIUM:
|
||||
return WidgetViewsFactory.populateMedium(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
case LARGE:
|
||||
return WidgetViewsFactory.populateLarge(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
case EXPANDED:
|
||||
return WidgetViewsFactory.populateExpanded(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
case COMPACT:
|
||||
default:
|
||||
return WidgetViewsFactory.populateCompact(ctx, title, artist, album, art, playing,
|
||||
elapsedText, totalText, progress, shuffleEnabled, repeatMode);
|
||||
}
|
||||
}
|
||||
|
||||
private static LayoutSize resolveLayoutSize(Context ctx, int appWidgetId) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(ctx);
|
||||
android.os.Bundle opts = mgr.getAppWidgetOptions(appWidgetId);
|
||||
int minH = opts != null ? opts.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) : 0;
|
||||
int expandedThreshold = ctx.getResources().getInteger(R.integer.widget_expanded_min_height_dp);
|
||||
int largeThreshold = ctx.getResources().getInteger(R.integer.widget_large_min_height_dp);
|
||||
int mediumThreshold = ctx.getResources().getInteger(R.integer.widget_medium_min_height_dp);
|
||||
if (minH >= expandedThreshold) return LayoutSize.EXPANDED;
|
||||
if (minH >= largeThreshold) return LayoutSize.LARGE;
|
||||
if (minH >= mediumThreshold) return LayoutSize.MEDIUM;
|
||||
return LayoutSize.COMPACT;
|
||||
}
|
||||
|
||||
private enum LayoutSize {
|
||||
COMPACT,
|
||||
MEDIUM,
|
||||
LARGE,
|
||||
EXPANDED
|
||||
}
|
||||
|
||||
private static final class TimingInfo {
|
||||
final String elapsedText;
|
||||
final String totalText;
|
||||
final int progress;
|
||||
|
||||
TimingInfo(String elapsedText, String totalText, int progress) {
|
||||
this.elapsedText = elapsedText;
|
||||
this.totalText = totalText;
|
||||
this.progress = progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,62 +19,93 @@ import com.cappielloantonio.tempo.R;
|
|||
|
||||
public final class WidgetViewsFactory {
|
||||
|
||||
static final int PROGRESS_MAX = 1000;
|
||||
private static final float ALBUM_ART_CORNER_RADIUS_DP = 6f;
|
||||
static final int PROGRESS_MAX = 1000;
|
||||
private static final float ALBUM_ART_CORNER_RADIUS_DP = 6f;
|
||||
|
||||
private WidgetViewsFactory() {}
|
||||
|
||||
public static RemoteViews buildCompact(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_compact, false, false);
|
||||
}
|
||||
|
||||
public static RemoteViews buildMedium(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_medium, false, false);
|
||||
}
|
||||
|
||||
public static RemoteViews buildLarge(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_large_short, true, true);
|
||||
}
|
||||
|
||||
public static RemoteViews buildExpanded(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_large, true, true);
|
||||
}
|
||||
|
||||
private static RemoteViews build(Context ctx,
|
||||
int layoutRes,
|
||||
boolean showAlbum,
|
||||
boolean showSecondaryControls) {
|
||||
RemoteViews rv = new RemoteViews(ctx.getPackageName(), layoutRes);
|
||||
rv.setTextViewText(R.id.title, ctx.getString(R.string.widget_not_playing));
|
||||
rv.setTextViewText(R.id.subtitle, ctx.getString(R.string.widget_placeholder_subtitle));
|
||||
rv.setTextViewText(R.id.album, "");
|
||||
rv.setViewVisibility(R.id.album, showAlbum ? View.INVISIBLE : View.GONE);
|
||||
rv.setTextViewText(R.id.time_elapsed, ctx.getString(R.string.widget_time_elapsed_placeholder));
|
||||
rv.setTextViewText(R.id.time_total, ctx.getString(R.string.widget_time_duration_placeholder));
|
||||
rv.setProgressBar(R.id.progress, PROGRESS_MAX, 0, false);
|
||||
rv.setImageViewResource(R.id.btn_play_pause, R.drawable.ic_play);
|
||||
rv.setImageViewResource(R.id.album_art, R.drawable.ic_splash_logo);
|
||||
applySecondaryControlsDefaults(ctx, rv, showSecondaryControls);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private static void applySecondaryControlsDefaults(Context ctx,
|
||||
RemoteViews rv,
|
||||
boolean show) {
|
||||
int visibility = show ? View.VISIBLE : View.GONE;
|
||||
rv.setViewVisibility(R.id.controls_secondary, visibility);
|
||||
rv.setViewVisibility(R.id.btn_shuffle, visibility);
|
||||
rv.setViewVisibility(R.id.btn_repeat, visibility);
|
||||
if (show) {
|
||||
int defaultColor = ContextCompat.getColor(ctx, R.color.widget_icon_tint);
|
||||
rv.setImageViewResource(R.id.btn_shuffle, R.drawable.ic_shuffle);
|
||||
rv.setImageViewResource(R.id.btn_repeat, R.drawable.ic_repeat);
|
||||
rv.setInt(R.id.btn_shuffle, "setColorFilter", defaultColor);
|
||||
rv.setInt(R.id.btn_repeat, "setColorFilter", defaultColor);
|
||||
private WidgetViewsFactory() {
|
||||
}
|
||||
}
|
||||
|
||||
public static RemoteViews populateCompact(Context ctx,
|
||||
public static RemoteViews buildCompact(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_compact, false, false);
|
||||
}
|
||||
|
||||
public static RemoteViews buildMedium(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_medium, false, false);
|
||||
}
|
||||
|
||||
public static RemoteViews buildLarge(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_large_short, true, true);
|
||||
}
|
||||
|
||||
public static RemoteViews buildExpanded(Context ctx) {
|
||||
return build(ctx, R.layout.widget_layout_large, true, true);
|
||||
}
|
||||
|
||||
private static RemoteViews build(Context ctx,
|
||||
int layoutRes,
|
||||
boolean showAlbum,
|
||||
boolean showSecondaryControls) {
|
||||
RemoteViews rv = new RemoteViews(ctx.getPackageName(), layoutRes);
|
||||
rv.setTextViewText(R.id.title, ctx.getString(R.string.widget_not_playing));
|
||||
rv.setTextViewText(R.id.subtitle, ctx.getString(R.string.widget_placeholder_subtitle));
|
||||
rv.setTextViewText(R.id.album, "");
|
||||
rv.setViewVisibility(R.id.album, showAlbum ? View.INVISIBLE : View.GONE);
|
||||
rv.setTextViewText(R.id.time_elapsed, ctx.getString(R.string.widget_time_elapsed_placeholder));
|
||||
rv.setTextViewText(R.id.time_total, ctx.getString(R.string.widget_time_duration_placeholder));
|
||||
rv.setProgressBar(R.id.progress, PROGRESS_MAX, 0, false);
|
||||
rv.setImageViewResource(R.id.btn_play_pause, R.drawable.ic_play);
|
||||
rv.setImageViewResource(R.id.album_art, R.drawable.ic_splash_logo);
|
||||
applySecondaryControlsDefaults(ctx, rv, showSecondaryControls);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private static void applySecondaryControlsDefaults(Context ctx,
|
||||
RemoteViews rv,
|
||||
boolean show) {
|
||||
int visibility = show ? View.VISIBLE : View.GONE;
|
||||
rv.setViewVisibility(R.id.controls_secondary, visibility);
|
||||
rv.setViewVisibility(R.id.btn_shuffle, visibility);
|
||||
rv.setViewVisibility(R.id.btn_repeat, visibility);
|
||||
if (show) {
|
||||
int defaultColor = ContextCompat.getColor(ctx, R.color.widget_icon_tint);
|
||||
rv.setImageViewResource(R.id.btn_shuffle, R.drawable.ic_shuffle);
|
||||
rv.setImageViewResource(R.id.btn_repeat, R.drawable.ic_repeat);
|
||||
rv.setInt(R.id.btn_shuffle, "setColorFilter", defaultColor);
|
||||
rv.setInt(R.id.btn_repeat, "setColorFilter", defaultColor);
|
||||
}
|
||||
}
|
||||
|
||||
public static RemoteViews populateCompact(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_compact, false, false, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
public static RemoteViews populateMedium(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_medium, true, true, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
public static RemoteViews populateLarge(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
|
|
@ -85,167 +116,137 @@ public final class WidgetViewsFactory {
|
|||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_compact, false, false, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
public static RemoteViews populateMedium(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_medium, true, true, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
public static RemoteViews populateLarge(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_large_short, true, true, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
public static RemoteViews populateExpanded(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_large, true, true, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
private static RemoteViews populateWithLayout(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
int layoutRes,
|
||||
boolean showAlbum,
|
||||
boolean showSecondaryControls,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
RemoteViews rv = new RemoteViews(ctx.getPackageName(), layoutRes);
|
||||
rv.setTextViewText(R.id.title, title);
|
||||
rv.setTextViewText(R.id.subtitle, subtitle);
|
||||
|
||||
if (showAlbum && !TextUtils.isEmpty(album)) {
|
||||
rv.setTextViewText(R.id.album, album);
|
||||
rv.setViewVisibility(R.id.album, View.VISIBLE);
|
||||
} else {
|
||||
rv.setTextViewText(R.id.album, "");
|
||||
rv.setViewVisibility(R.id.album, View.GONE);
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_large_short, true, true, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
if (art != null) {
|
||||
Bitmap rounded = maybeRoundBitmap(ctx, art);
|
||||
rv.setImageViewBitmap(R.id.album_art, rounded != null ? rounded : art);
|
||||
} else {
|
||||
rv.setImageViewResource(R.id.album_art, R.drawable.ic_splash_logo);
|
||||
public static RemoteViews populateExpanded(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
return populateWithLayout(ctx, title, subtitle, album, art, playing, elapsedText, totalText,
|
||||
progress, R.layout.widget_layout_large, true, true, shuffleEnabled, repeatMode);
|
||||
}
|
||||
|
||||
rv.setImageViewResource(R.id.btn_play_pause,
|
||||
playing ? R.drawable.ic_pause : R.drawable.ic_play);
|
||||
private static RemoteViews populateWithLayout(Context ctx,
|
||||
String title,
|
||||
String subtitle,
|
||||
String album,
|
||||
Bitmap art,
|
||||
boolean playing,
|
||||
String elapsedText,
|
||||
String totalText,
|
||||
int progress,
|
||||
int layoutRes,
|
||||
boolean showAlbum,
|
||||
boolean showSecondaryControls,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
RemoteViews rv = new RemoteViews(ctx.getPackageName(), layoutRes);
|
||||
rv.setTextViewText(R.id.title, title);
|
||||
rv.setTextViewText(R.id.subtitle, subtitle);
|
||||
|
||||
String elapsed = !TextUtils.isEmpty(elapsedText)
|
||||
? elapsedText
|
||||
: ctx.getString(R.string.widget_time_elapsed_placeholder);
|
||||
String total = !TextUtils.isEmpty(totalText)
|
||||
? totalText
|
||||
: ctx.getString(R.string.widget_time_duration_placeholder);
|
||||
if (showAlbum && !TextUtils.isEmpty(album)) {
|
||||
rv.setTextViewText(R.id.album, album);
|
||||
rv.setViewVisibility(R.id.album, View.VISIBLE);
|
||||
} else {
|
||||
rv.setTextViewText(R.id.album, "");
|
||||
rv.setViewVisibility(R.id.album, View.GONE);
|
||||
}
|
||||
|
||||
int safeProgress = progress;
|
||||
if (safeProgress < 0) safeProgress = 0;
|
||||
if (safeProgress > PROGRESS_MAX) safeProgress = PROGRESS_MAX;
|
||||
if (art != null) {
|
||||
Bitmap rounded = maybeRoundBitmap(ctx, art);
|
||||
rv.setImageViewBitmap(R.id.album_art, rounded != null ? rounded : art);
|
||||
} else {
|
||||
rv.setImageViewResource(R.id.album_art, R.drawable.ic_splash_logo);
|
||||
}
|
||||
|
||||
rv.setTextViewText(R.id.time_elapsed, elapsed);
|
||||
rv.setTextViewText(R.id.time_total, total);
|
||||
rv.setProgressBar(R.id.progress, PROGRESS_MAX, safeProgress, false);
|
||||
rv.setImageViewResource(R.id.btn_play_pause,
|
||||
playing ? R.drawable.ic_pause : R.drawable.ic_play);
|
||||
|
||||
applySecondaryControls(ctx, rv, showSecondaryControls, shuffleEnabled, repeatMode);
|
||||
String elapsed = !TextUtils.isEmpty(elapsedText)
|
||||
? elapsedText
|
||||
: ctx.getString(R.string.widget_time_elapsed_placeholder);
|
||||
String total = !TextUtils.isEmpty(totalText)
|
||||
? totalText
|
||||
: ctx.getString(R.string.widget_time_duration_placeholder);
|
||||
|
||||
return rv;
|
||||
}
|
||||
int safeProgress = progress;
|
||||
if (safeProgress < 0) safeProgress = 0;
|
||||
if (safeProgress > PROGRESS_MAX) safeProgress = PROGRESS_MAX;
|
||||
|
||||
private static Bitmap maybeRoundBitmap(Context ctx, Bitmap source) {
|
||||
if (source == null || source.isRecycled()) {
|
||||
return null;
|
||||
rv.setTextViewText(R.id.time_elapsed, elapsed);
|
||||
rv.setTextViewText(R.id.time_total, total);
|
||||
rv.setProgressBar(R.id.progress, PROGRESS_MAX, safeProgress, false);
|
||||
|
||||
applySecondaryControls(ctx, rv, showSecondaryControls, shuffleEnabled, repeatMode);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
try {
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
if (width <= 0 || height <= 0) {
|
||||
return null;
|
||||
}
|
||||
private static Bitmap maybeRoundBitmap(Context ctx, Bitmap source) {
|
||||
if (source == null || source.isRecycled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(output);
|
||||
try {
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
if (width <= 0 || height <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
|
||||
Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(output);
|
||||
|
||||
float radiusPx = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
ALBUM_ART_CORNER_RADIUS_DP,
|
||||
ctx.getResources().getDisplayMetrics());
|
||||
float maxRadius = Math.min(width, height) / 2f;
|
||||
float safeRadius = Math.min(radiusPx, maxRadius);
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
|
||||
|
||||
canvas.drawRoundRect(new RectF(0f, 0f, width, height), safeRadius, safeRadius, paint);
|
||||
return output;
|
||||
} catch (RuntimeException | OutOfMemoryError e) {
|
||||
android.util.Log.w("TempoWidget", "Failed to round album art", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
float radiusPx = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
ALBUM_ART_CORNER_RADIUS_DP,
|
||||
ctx.getResources().getDisplayMetrics());
|
||||
float maxRadius = Math.min(width, height) / 2f;
|
||||
float safeRadius = Math.min(radiusPx, maxRadius);
|
||||
|
||||
private static void applySecondaryControls(Context ctx,
|
||||
RemoteViews rv,
|
||||
boolean show,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
if (!show) {
|
||||
rv.setViewVisibility(R.id.controls_secondary, View.GONE);
|
||||
rv.setViewVisibility(R.id.btn_shuffle, View.GONE);
|
||||
rv.setViewVisibility(R.id.btn_repeat, View.GONE);
|
||||
return;
|
||||
canvas.drawRoundRect(new RectF(0f, 0f, width, height), safeRadius, safeRadius, paint);
|
||||
return output;
|
||||
} catch (RuntimeException | OutOfMemoryError e) {
|
||||
android.util.Log.w("TempoWidget", "Failed to round album art", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
int inactiveColor = ContextCompat.getColor(ctx, R.color.widget_icon_tint);
|
||||
int activeColor = ContextCompat.getColor(ctx, R.color.widget_icon_tint_active);
|
||||
private static void applySecondaryControls(Context ctx,
|
||||
RemoteViews rv,
|
||||
boolean show,
|
||||
boolean shuffleEnabled,
|
||||
int repeatMode) {
|
||||
if (!show) {
|
||||
rv.setViewVisibility(R.id.controls_secondary, View.GONE);
|
||||
rv.setViewVisibility(R.id.btn_shuffle, View.GONE);
|
||||
rv.setViewVisibility(R.id.btn_repeat, View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
rv.setViewVisibility(R.id.controls_secondary, View.VISIBLE);
|
||||
rv.setViewVisibility(R.id.btn_shuffle, View.VISIBLE);
|
||||
rv.setViewVisibility(R.id.btn_repeat, View.VISIBLE);
|
||||
rv.setImageViewResource(R.id.btn_shuffle, R.drawable.ic_shuffle);
|
||||
rv.setImageViewResource(R.id.btn_repeat,
|
||||
repeatMode == Player.REPEAT_MODE_ONE ? R.drawable.ic_repeat_one : R.drawable.ic_repeat);
|
||||
rv.setInt(R.id.btn_shuffle, "setColorFilter", shuffleEnabled ? activeColor : inactiveColor);
|
||||
rv.setInt(R.id.btn_repeat, "setColorFilter",
|
||||
repeatMode == Player.REPEAT_MODE_OFF ? inactiveColor : activeColor);
|
||||
}
|
||||
int inactiveColor = ContextCompat.getColor(ctx, R.color.widget_icon_tint);
|
||||
int activeColor = ContextCompat.getColor(ctx, R.color.widget_icon_tint_active);
|
||||
|
||||
rv.setViewVisibility(R.id.controls_secondary, View.VISIBLE);
|
||||
rv.setViewVisibility(R.id.btn_shuffle, View.VISIBLE);
|
||||
rv.setViewVisibility(R.id.btn_repeat, View.VISIBLE);
|
||||
rv.setImageViewResource(R.id.btn_shuffle, R.drawable.ic_shuffle);
|
||||
rv.setImageViewResource(R.id.btn_repeat,
|
||||
repeatMode == Player.REPEAT_MODE_ONE ? R.drawable.ic_repeat_one : R.drawable.ic_repeat);
|
||||
rv.setInt(R.id.btn_shuffle, "setColorFilter", shuffleEnabled ? activeColor : inactiveColor);
|
||||
rv.setInt(R.id.btn_repeat, "setColorFilter",
|
||||
repeatMode == Player.REPEAT_MODE_OFF ? inactiveColor : activeColor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue