快速更新Android通知



我为Android编写一个简单的音频播放器。我写了基本的功能,现在我想创建通知控制音频播放器。我使用Android类Service和Notification以及RemoteViews来处理大小通知。这个工作很好,但是,当我使用快速翻转音轨时,我的通知不会更新带有名称音轨的文本。我为演示问题创建了一个简单的视频:

you-tube.com

我使用c#和Xamarin Forms,但没关系,因为代码与Java非常相似。我的服务:

[Service]
public class PlayerService : Service, IPlayerService
{
private const string ACTION_SHOW_PLAYER = "music.player.ACTION.SHOW_PLAYER";
private const string ACTION_PLAY_PAUSE = "music.player.ACTION.PLAY_PAUSE";
private const string ACTION_PLAY_PREW = "music.player.ACTION.PLAY_PREW";
private const string ACTION_PLAY_NEXT = "music.player.ACTION.PLAY_NEXT";
private const string ACTION_STOP_SERVICE = "music.player.ACTION.STOP_SERVICE";
private const string ANDROID_CHANNEL_ID = "com.companyname.homeremotecontroller";
private const int NOTIFICATION_ID = 46;
private RemoteViews _remoteViewsBig = null;
private RemoteViews _remoteViewsSmall = null;
private NotificationManager _notificationManager = null;
private NotificationCompat.Builder _builder = null;
private static IPlayerService _instance = null;
private static bool _isActiveBackgroundService = false;
private static bool _isBeenStartBackgroundService= false;
public IPlayerService GetInstance()
{
return _instance;
}
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
base.OnCreate();
_instance = this;
MusicPlaylistModel.GetInstance().ChangeSound += () =>
{
UpdateSound(MusicPlaylistModel.GetInstance().CurrentSound.SoundName);
};
MusicPlaylistModel.GetInstance().MusicPlayer.TimeSound += (start, end) =>
{
// TODO: empty
};
MusicPlaylistModel.GetInstance().MusicPlayer.TickCurrentSound += (curr) =>
{
UpdateProgressSound(curr);
};
MusicPlaylistModel.GetInstance().PlayingStatus += (status) =>
{
UpdatePlayPauseStatus(status);
};
_notificationManager = ((NotificationManager)GetSystemService(NotificationService));
_notificationManager.CreateNotificationChannel(new NotificationChannel(ANDROID_CHANNEL_ID, "Audio player", NotificationImportance.High));
Intent notificationIntent = new Intent(MainActivity.Activity, typeof(MainActivity));
_remoteViewsSmall = GetSmallContentView();
_remoteViewsBig = GetBigContentView();
CreateBuilderNotification();
}
public override void OnDestroy()
{
base.OnDestroy();
}
public void CreateBuilderNotification()
{
_builder = new NotificationCompat.Builder(MainActivity.Activity, ANDROID_CHANNEL_ID)
.SetCategory(Notification.ExtraMediaSession)
.SetCustomBigContentView(_remoteViewsBig)
.SetCustomContentView(_remoteViewsSmall)
.SetSmallIcon(Resource.Mipmap.icon)
.SetOngoing(true)
.SetSilent(true)
.SetPriority((int)NotificationPriority.Max)
.SetVisibility(NotificationCompat.VisibilityPublic)
.SetAutoCancel(true)
.SetStyle(new NotificationCompat.DecoratedCustomViewStyle());
}
public Notification RecreateNotification()
{
return _builder.Build();
}
private RemoteViews GetBigContentView()
{
RemoteViews mContentViewBig = new RemoteViews(MainActivity.Activity.PackageName, Resource.Layout.player_notify_big);
Intent closeIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
closeIntent.SetAction(ACTION_STOP_SERVICE);
PendingIntent pcloseIntent = PendingIntent.GetService(MainActivity.Activity, 0, closeIntent, 0);
Intent playPauseIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
playPauseIntent.SetAction(ACTION_PLAY_PAUSE);
PendingIntent pPlayPauseIntent = PendingIntent.GetService(MainActivity.Activity, 0, playPauseIntent, 0);
Intent nextIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
nextIntent.SetAction(ACTION_PLAY_NEXT);
PendingIntent pNextIntent = PendingIntent.GetService(MainActivity.Activity, 0, nextIntent, 0);
Intent prewIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
prewIntent.SetAction(ACTION_PLAY_PREW);
PendingIntent pPrewIntent = PendingIntent.GetService(MainActivity.Activity, 0, prewIntent, 0);

mContentViewBig.SetOnClickPendingIntent(Resource.Id.btnWidgetPlayPauseMusicBig, pPlayPauseIntent);
mContentViewBig.SetOnClickPendingIntent(Resource.Id.btnWidgetCloseService, pcloseIntent);
mContentViewBig.SetOnClickPendingIntent(Resource.Id.playNextBig, pNextIntent);
mContentViewBig.SetOnClickPendingIntent(Resource.Id.playPrevBig, pPrewIntent);
return mContentViewBig;
}
private RemoteViews GetSmallContentView()
{
RemoteViews mContentViewSmall = new RemoteViews(MainActivity.Activity.PackageName, Resource.Layout.player_notify_small);
Intent closeIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
closeIntent.SetAction(ACTION_STOP_SERVICE);
PendingIntent pcloseIntent = PendingIntent.GetService(MainActivity.Activity, 0, closeIntent, 0);
Intent playPauseIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
playPauseIntent.SetAction(ACTION_PLAY_PAUSE);
PendingIntent pPlayPauseIntent = PendingIntent.GetService(MainActivity.Activity, 0, playPauseIntent, 0);
Intent nextIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
nextIntent.SetAction(ACTION_PLAY_NEXT);
PendingIntent pNextIntent = PendingIntent.GetService(MainActivity.Activity, 0, nextIntent, 0);
Intent prewIntent = new Intent(MainActivity.Activity, typeof(PlayerService));
prewIntent.SetAction(ACTION_PLAY_PREW);
PendingIntent pPrewIntent = PendingIntent.GetService(MainActivity.Activity, 0, prewIntent, 0);
mContentViewSmall.SetOnClickPendingIntent(Resource.Id.btnWidgetCloseServiceSmall, pcloseIntent);
mContentViewSmall.SetOnClickPendingIntent(Resource.Id.btnWidgetPlayPauseMusic, pPlayPauseIntent);
mContentViewSmall.SetOnClickPendingIntent(Resource.Id.btnWidgetPlayNext, pNextIntent);
mContentViewSmall.SetOnClickPendingIntent(Resource.Id.btnWidgetPlayPrevious, pPrewIntent);
return mContentViewSmall;
}
public void RedrawNotification()
{
if(!_isActiveBackgroundService)
{
return;
}
var notification = RecreateNotification();
notification.Flags = NotificationFlags.NoClear | NotificationFlags.OngoingEvent;
_notificationManager.Notify(NOTIFICATION_ID, notification);
StartForeground(NOTIFICATION_ID, notification);
}
public void Start()
{
MainActivity.Activity.StartForegroundService(new Intent(MainActivity.Activity, typeof(PlayerService)));
_isActiveBackgroundService = true;
_isBeenStartBackgroundService = true;
}
public void Stop()
{
MainActivity.Activity.StopService(new Intent(MainActivity.Activity, typeof(PlayerService)));
_isActiveBackgroundService = false;
}

public void UpdateSound(string snd_name)
{
_remoteViewsSmall.SetTextViewText(Resource.Id.lblWidgetCurrentMusicName, snd_name);
_remoteViewsBig.SetTextViewText(Resource.Id.lblWidgetCurrentMusicName, snd_name);
_builder.SetCustomBigContentView(_remoteViewsBig)
.SetCustomContentView(_remoteViewsSmall);
RedrawNotification();
}
public void UpdateProgressSound(int currProgress)
{
// TODO: empty
}
public void UpdatePlayPauseStatus(bool status)
{
if(status)
{
_remoteViewsSmall.SetImageViewResource(Resource.Id.btnWidgetPlayPauseMusic, Resource.Drawable.play_off);
_remoteViewsBig.SetImageViewResource(Resource.Id.btnWidgetPlayPauseMusicBig, Resource.Drawable.play_off);
}
else
{
_remoteViewsSmall.SetImageViewResource(Resource.Id.btnWidgetPlayPauseMusic, Resource.Drawable.pause_off);
_remoteViewsBig.SetImageViewResource(Resource.Id.btnWidgetPlayPauseMusicBig, Resource.Drawable.pause_off);
}
_builder.SetCustomBigContentView(_remoteViewsBig)
.SetCustomContentView(_remoteViewsSmall);
RedrawNotification();
}
public override StartCommandResult OnStartCommand(Intent? intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
if (_isBeenStartBackgroundService)
{
UpdateSound(MusicPlaylistModel.GetInstance().CurrentSound.SoundName);
UpdatePlayPauseStatus(false);
RedrawNotification();
_isBeenStartBackgroundService = false;
}
string action = intent.Action;
if (action != null)
{
if (action == ACTION_STOP_SERVICE)
{
Stop();
}
else
{
new Task(async () =>
{
if (action == ACTION_PLAY_PAUSE)
{
await MusicPlaylistModel.GetInstance().Play();
return;
}
else if (action == ACTION_PLAY_PREW)
{
await MusicPlaylistModel.GetInstance().Prew();
return;
}
else if (action == ACTION_PLAY_NEXT)
{
await MusicPlaylistModel.GetInstance().Next();
return;
}
}).Start();
}
}
return StartCommandResult.Sticky;
}
}

为了显示通知,外部代码调用Start方法,为了隐藏通知,外部代码调用Stop方法。我检查调试。UpdateSound法应用成功,其中snd_name-法是正确的。但是通知中的文本不正确。

如何修复?

UpdateSound()中调用RedrawNotification()

RedrawNotification()中调用RecreateNotification()

RecreateNotification()中调用_builder.Build()

但是你从来没有对_builder做过任何修改。

解决方案:使用通知。MediaStyle类。

最新更新