Update how now playing notification is shown.

Move all logic to the DownloadServiceImpl as it is not a responsibility of SubsonicTabActivity to do it.
Also NotificationCompat.Builder to build notification as now it is a standard way to do it.

Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
Yahor Berdnikau 2017-02-10 23:05:52 +01:00
parent 5fee79c652
commit c80d92b459
No known key found for this signature in database
GPG Key ID: 07509DAF2D048E85
4 changed files with 148 additions and 217 deletions

View File

@ -18,10 +18,8 @@
*/
package org.moire.ultrasonic.activity;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
@ -30,11 +28,9 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.ActionBar;
import android.util.Log;
import android.view.KeyEvent;
@ -113,10 +109,7 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
View bookmarksMenuItem;
View sharesMenuItem;
public static boolean nowPlayingHidden;
public static Entry currentSong;
public Bitmap nowPlayingImage;
boolean licenseValid;
NotificationManager notificationManager;
private EditText shareDescription;
TimeSpanPicker timeSpanPicker;
CheckBox hideDialogCheckBox;
@ -167,8 +160,6 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
{
menuDrawer.setActiveView(activeView);
}
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
@ -341,129 +332,6 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
}
}
public void showNotification(final Handler handler, final Entry song, final DownloadServiceImpl downloadService, final Notification notification, final PlayerState playerState)
{
if (!Util.isNotificationEnabled(this))
{
return;
}
new AsyncTask<Void, Void, String[]>()
{
@SuppressLint("NewApi")
@Override
protected String[] doInBackground(Void... params)
{
Thread.currentThread().setName("showNotification");
RemoteViews notificationView = notification.contentView;
RemoteViews bigNotificationView = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
bigNotificationView = notification.bigContentView;
}
if (playerState == PlayerState.PAUSED)
{
setImageViewResourceOnUiThread(notificationView, R.id.control_play, R.drawable.media_start_normal_dark);
if (bigNotificationView != null)
{
setImageViewResourceOnUiThread(bigNotificationView, R.id.control_play, R.drawable.media_start_normal_dark);
}
}
else if (playerState == PlayerState.STARTED)
{
setImageViewResourceOnUiThread(notificationView, R.id.control_play, R.drawable.media_pause_normal_dark);
if (bigNotificationView != null)
{
setImageViewResourceOnUiThread(bigNotificationView, R.id.control_play, R.drawable.media_pause_normal_dark);
}
}
if (currentSong != song)
{
currentSong = song;
String title = song.getTitle();
String text = song.getArtist();
String album = song.getAlbum();
try
{
if (nowPlayingImage == null)
{
setImageViewResourceOnUiThread(notificationView, R.id.notification_image, R.drawable.unknown_album);
if (bigNotificationView != null)
{
setImageViewResourceOnUiThread(bigNotificationView, R.id.notification_image, R.drawable.unknown_album);
}
}
else
{
setImageViewBitmapOnUiThread(notificationView, R.id.notification_image, nowPlayingImage);
if (bigNotificationView != null)
{
setImageViewBitmapOnUiThread(bigNotificationView, R.id.notification_image, nowPlayingImage);
}
}
}
catch (Exception x)
{
Log.w(TAG, "Failed to get notification cover art", x);
setImageViewResourceOnUiThread(notificationView, R.id.notification_image, R.drawable.unknown_album);
if (bigNotificationView != null)
{
setImageViewResourceOnUiThread(bigNotificationView, R.id.notification_image, R.drawable.unknown_album);
}
}
setTextViewTextOnUiThread(notificationView, R.id.trackname, title);
setTextViewTextOnUiThread(notificationView, R.id.artist, text);
setTextViewTextOnUiThread(notificationView, R.id.album, album);
if (bigNotificationView != null)
{
setTextViewTextOnUiThread(bigNotificationView, R.id.trackname, title);
setTextViewTextOnUiThread(bigNotificationView, R.id.artist, text);
setTextViewTextOnUiThread(bigNotificationView, R.id.album, album);
}
}
// Send the notification and put the service in the foreground.
handler.post(new Runnable()
{
@Override
public void run()
{
downloadService.startForeground(Constants.NOTIFICATION_ID_PLAYING, notification);
}
});
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void hidePlayingNotification(final Handler handler, final DownloadServiceImpl downloadService)
{
currentSong = null;
// Remove notification and remove the service from the foreground
handler.post(new Runnable()
{
@Override
public void run()
{
downloadService.stopForeground(true);
}
});
}
private void showNowPlaying(final Context context, final DownloadService downloadService, final Entry song, final PlayerState playerState)
{
if (context == null || downloadService == null || song == null || playerState == null)

View File

@ -36,6 +36,8 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.SeekBar;
@ -95,6 +97,8 @@ public class DownloadServiceImpl extends Service implements DownloadService
public static final String CMD_PREVIOUS = "org.moire.ultrasonic.CMD_PREVIOUS";
public static final String CMD_NEXT = "org.moire.ultrasonic.CMD_NEXT";
private static final int NOTIFICATION_ID = 3033;
private final IBinder binder = new SimpleServiceBinder<DownloadService>(this);
private Looper mediaPlayerLooper;
private MediaPlayer mediaPlayer;
@ -111,7 +115,6 @@ public class DownloadServiceImpl extends Service implements DownloadService
private final List<DownloadFile> cleanupCandidates = new ArrayList<DownloadFile>();
private final Scrobbler scrobbler = new Scrobbler();
private final JukeboxService jukeboxService = new JukeboxService(this);
private Notification notification = new Notification(R.drawable.ic_stat_ultrasonic, null, System.currentTimeMillis());
private DownloadFile currentPlaying;
private DownloadFile nextPlaying;
@ -222,19 +225,6 @@ public class DownloadServiceImpl extends Service implements DownloadService
audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
setUpRemoteControlClient();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
notification.contentView = new RemoteViews(this.getPackageName(), R.layout.notification);
Util.linkButtons(this, notification.contentView, false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
notification.bigContentView = new RemoteViews(this.getPackageName(), R.layout.notification_large);
Util.linkButtons(this, notification.bigContentView, false);
}
Intent notificationIntent = new Intent(this, DownloadActivity.class);
notification.contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
if (equalizerAvailable)
{
equalizerController = new EqualizerController(this, mediaPlayer);
@ -311,8 +301,6 @@ public class DownloadServiceImpl extends Service implements DownloadService
nextPlayingTask.cancel();
}
notification = null;
Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mediaPlayer.getAudioSessionId());
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
@ -724,12 +712,10 @@ public class DownloadServiceImpl extends Service implements DownloadService
if (currentPlaying != null)
{
if (tabInstance != null)
{
int size = Util.getNotificationImageSize(this);
tabInstance.nowPlayingImage = FileUtil.getAlbumArtBitmap(this, currentPlaying.getSong(), size, true);
tabInstance.showNotification(handler, currentPlaying.getSong(), this, this.notification, this.playerState);
if (tabInstance != null) {
if (Util.isNotificationEnabled(this)) {
startForeground(NOTIFICATION_ID, buildForegroundNotification());
}
tabInstance.showNowPlaying();
}
}
@ -737,8 +723,7 @@ public class DownloadServiceImpl extends Service implements DownloadService
{
if (tabInstance != null)
{
tabInstance.nowPlayingImage = null;
tabInstance.hidePlayingNotification(handler, this);
stopForeground(true);
tabInstance.hideNowPlaying();
}
}
@ -1246,27 +1231,18 @@ public class DownloadServiceImpl extends Service implements DownloadService
UltraSonicAppWidgetProvider4x4.getInstance().notifyChange(this, this, this.playerState == PlayerState.STARTED, false);
SubsonicTabActivity tabInstance = SubsonicTabActivity.getInstance();
Entry song = null;
if (currentPlaying != null)
{
song = currentPlaying.getSong();
}
if (show)
{
if (tabInstance != null)
{
if (SubsonicTabActivity.currentSong != song)
{
int size = Util.getNotificationImageSize(this);
tabInstance.nowPlayingImage = FileUtil.getAlbumArtBitmap(this, song, size, true);
}
// Only update notification is player state is one that will change the icon
if (this.playerState == PlayerState.STARTED || this.playerState == PlayerState.PAUSED)
{
tabInstance.showNotification(handler, song, this, this.notification, this.playerState);
if (Util.isNotificationEnabled(this)) {
final NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
notificationManager.notify(NOTIFICATION_ID, buildForegroundNotification());
}
tabInstance.showNowPlaying();
}
}
@ -1275,8 +1251,7 @@ public class DownloadServiceImpl extends Service implements DownloadService
{
if (tabInstance != null)
{
tabInstance.nowPlayingImage = null;
tabInstance.hidePlayingNotification(handler, this);
stopForeground(true);
tabInstance.hideNowPlaying();
}
}
@ -1398,7 +1373,7 @@ public class DownloadServiceImpl extends Service implements DownloadService
}
catch (Exception e)
{
Log.w("Error getting user information", e);
Log.w(TAG, "Error getting user information", e);
}
return false;
@ -1417,7 +1392,7 @@ public class DownloadServiceImpl extends Service implements DownloadService
}
catch (Exception e)
{
Log.w("Error getting user information", e);
Log.w(TAG, "Error getting user information", e);
}
return false;
@ -2096,6 +2071,68 @@ public class DownloadServiceImpl extends Service implements DownloadService
}
}
private Notification buildForegroundNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_stat_ultrasonic);
builder.setAutoCancel(false);
builder.setOngoing(true);
builder.setWhen(System.currentTimeMillis());
RemoteViews contentView = new RemoteViews(this.getPackageName(), R.layout.notification);
Util.linkButtons(this, contentView, false);
RemoteViews bigView = new RemoteViews(this.getPackageName(), R.layout.notification_large);
Util.linkButtons(this, bigView, false);
builder.setContent(contentView);
Intent notificationIntent = new Intent(this, DownloadActivity.class);
builder.setContentIntent(PendingIntent.getActivity(this, 0, notificationIntent, 0));
if (playerState == PlayerState.PAUSED || playerState == PlayerState.IDLE) {
contentView.setImageViewResource(R.id.control_play, R.drawable.media_start_normal_dark);
bigView.setImageViewResource(R.id.control_play, R.drawable.media_start_normal_dark);
} else if (playerState == PlayerState.STARTED) {
contentView.setImageViewResource(R.id.control_play, R.drawable.media_pause_normal_dark);
bigView.setImageViewResource(R.id.control_play, R.drawable.media_pause_normal_dark);
}
final Entry song = currentPlaying.getSong();
final String title = song.getTitle();
final String text = song.getArtist();
final String album = song.getAlbum();
final int imageSize = Util.getNotificationImageSize(this);
try {
final Bitmap nowPlayingImage = FileUtil.getAlbumArtBitmap(this, currentPlaying.getSong(), imageSize, true);
if (nowPlayingImage == null) {
contentView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
bigView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
} else {
contentView.setImageViewBitmap(R.id.notification_image, nowPlayingImage);
bigView.setImageViewBitmap(R.id.notification_image, nowPlayingImage);
}
} catch (Exception x) {
Log.w(TAG, "Failed to get notification cover art", x);
contentView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
bigView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
}
contentView.setTextViewText(R.id.trackname, title);
bigView.setTextViewText(R.id.trackname, title);
contentView.setTextViewText(R.id.artist, text);
bigView.setTextViewText(R.id.artist, text);
contentView.setTextViewText(R.id.album, album);
bigView.setTextViewText(R.id.album, album);
Notification notification = builder.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification.bigContentView = bigView;
}
return notification;
}
private class BufferTask extends CancellableTask
{
private final DownloadFile downloadFile;

View File

@ -1,63 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/statusbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_height="64dp"
android:orientation="horizontal"
android:background="@color/background_color_dark" >
android:background="@color/background_color_dark"
>
<ImageView
android:id="@+id/notification_image"
android:layout_width="64dip"
android:layout_height="64dip"
android:gravity="center" />
android:layout_width="64dp"
android:layout_height="64dp"
android:gravity="center"
tools:background="#FF00FF"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left"
android:gravity="start"
android:orientation="vertical"
android:paddingLeft="12dip" >
android:paddingLeft="12dip"
android:paddingStart="12dp"
>
<TextView
android:id="@+id/trackname"
style="@android:style/TextAppearance.StatusBar.EventContent.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_gravity="start"
android:ellipsize="marquee"
android:focusable="true"
android:singleLine="true" />
android:maxLines="1"
tools:text="Track name"
/>
<TextView
android:id="@+id/artist"
style="@android:style/TextAppearance.StatusBar.EventContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_gravity="start"
android:ellipsize="end"
android:scrollHorizontally="true"
android:singleLine="true" />
android:maxLines="1"
tools:text="Artist"
/>
<TextView
android:id="@+id/album"
style="@android:style/TextAppearance.StatusBar.EventContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_gravity="start"
android:ellipsize="end"
android:scrollHorizontally="true"
android:singleLine="true" />
android:maxLines="1"
tools:text="Album"
/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="right"
android:orientation="horizontal" >
android:gravity="end"
android:orientation="horizontal"
>
<ImageButton
android:id="@+id/control_previous"

View File

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/statusbar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_width="match_parent"
android:layout_height="128dp"
android:orientation="horizontal"
android:background="@color/background_color_dark" >
@ -10,20 +12,23 @@
android:id="@+id/notification_image"
android:layout_width="128dp"
android:layout_height="128dp"
android:gravity="center" />
android:gravity="center"
tools:background="#ff00ff"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:paddingLeft="8dip"
android:paddingTop="8dip"
android:paddingRight="8dip"
android:paddingBottom="8dip" >
android:paddingBottom="8dip"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
@ -32,21 +37,24 @@
style="@android:style/TextAppearance.StatusBar.EventContent.Title"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:layout_gravity="center|start"
android:layout_weight="1"
android:ellipsize="marquee"
android:focusable="true"
android:singleLine="true" />
android:maxLines="1"
tools:text="Track name"
/>
<ImageButton
android:id="@+id/control_stop"
android:layout_width="22dip"
android:layout_height="22dip"
android:layout_gravity="center|right"
android:layout_gravity="center|end"
android:gravity="center_vertical"
android:background="@drawable/btn_bg"
android:scaleType="fitXY"
android:src="@drawable/ic_menu_exit_dark" />
android:src="@drawable/ic_menu_exit_dark"
/>
</LinearLayout>
<TextView
@ -54,30 +62,35 @@
style="@android:style/TextAppearance.StatusBar.EventContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_gravity="start"
android:ellipsize="end"
android:scrollHorizontally="true"
android:singleLine="true" />
android:maxLines="1"
tools:text="Artist"
/>
<TextView
android:id="@+id/album"
style="@android:style/TextAppearance.StatusBar.EventContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_gravity="start"
android:ellipsize="end"
android:scrollHorizontally="true"
android:singleLine="true" />
android:maxLines="1"
tools:text="Album"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip"
android:background="#DD696969" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip"
android:background="#DD696969"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|bottom"
android:gravity="center_horizontal"