Android Oreo: Keep started background service alive without setting it foreground (but with a notification)?
在AndroID Oreo中处理媒体播放器服务的正确方法似乎是在媒体播放器暂停时存储状态信息,因此如果它被销毁,按下播放将创建一个新的媒体播放器并从它停止的地方开始.
我的问题是如何创建一个通知,当启动它的服务被销毁时不会被销毁.我没有运行任何代码来解除通知,但是当服务被破坏时,它仍然会自动被解雇.正如您在我的代码中看到的,我可以重建通知onDestroy,但我不喜欢它看起来的方式,因为用户可以看到它再次解雇和重建.
这是我的通知代码:
private voID buildNotification() { Cat.d("building notification"); final MediaPlayerService context = this; RequestBuilder<Bitmap> requestBuilder = GlIDe.with(this).asBitmap() .load(R.mipmap.ic_launcher); NotificationCompat.Action action; if (mediaPlayer != null && mediaPlayer.isPlaying()) action = generateAction(R.drawable.ic_pause,"Pause"); else action = generateAction(R.drawable.ic_play_arrow,"Play"); int[] actionsInCompact; builder = new NotificationCompat.Builder(context,NOTIFICATION_CHANNEL_ID) .setSmallicon(R.drawable.ic_navbooks_icon_black) //.setonlyAlertOnce(true) .setContentTitle(book.getTitle()) .setContentText(book.getAuthor()) .setautoCancel(false) .setContentIntent(PendingIntentHelper.getopenMainActivityIntent(context,book.getID())) .setDeleteIntent(PendingIntentHelper.getStopServiceIntent(context)); if (SettingsUtil.GetNotificationSkip(context)) { builder.addAction(R.drawable.ic_skip_backward,"Skip PrevIoUs",PendingIntentHelper.getSkipBackwardIntent(context)) .addAction(R.drawable.ic_backward,"Rewind",PendingIntentHelper.getSeekBackwardIntent(context)) .addAction(action) .addAction(R.drawable.ic_forward,"Fast Forward",PendingIntentHelper.getSeekForwardIntent(context)) .addAction(R.drawable.ic_skip_forward,"Skip Next",PendingIntentHelper.getSkipForwardIntent(context)); actionsInCompact = new int[]{0,1,2,3,4}; } else { builder.addAction(R.drawable.ic_backward,PendingIntentHelper.getSeekForwardIntent(context)); actionsInCompact = new int[]{0,2}; } builder.setStyle(new androID.support.v4.media.app.NotificationCompat.MediaStyle() .setMediaSession(mediaSession.getSessionToken()) .setShowActionsInCompactVIEw(actionsInCompact)); // Load a cover image if there isn't one loaded yet or the cover has changed if(cover == null || !book.getCover().equals(lastCover)) { lastCover = book.getCover(); mediaSession.setMetadata(new MediaMetadataCompat.Builder() .putString(MediaMetadataCompat.MetaDATA_KEY_ARTIST,book.getTitle()) .putString(MediaMetadataCompat.MetaDATA_KEY_Title,book.getAuthor()) .build()); GlIDe.with(this) .asBitmap() .error(requestBuilder) .load(book.getCover()) .into(new SimpleTarget<Bitmap>() { @OverrIDe public voID onResourceReady(Bitmap largeIcon,Transition Transition) { Cat.d("Finished loading"); cover = largeIcon; // initBuilder builder.setLargeIcon(largeIcon); mediaSession.setMetadata(new MediaMetadataCompat.Builder() .putBitmap(MediaMetadataCompat.MetaDATA_KEY_ALBUM_ART,largeIcon) .putString(MediaMetadataCompat.MetaDATA_KEY_ARTIST,book.getTitle()) .putString(MediaMetadataCompat.MetaDATA_KEY_Title,book.getAuthor()) .build()); startNotification(); } }); } else { mediaSession.setMetadata(new MediaMetadataCompat.Builder() .putBitmap(MediaMetadataCompat.MetaDATA_KEY_ALBUM_ART,cover) .putString(MediaMetadataCompat.MetaDATA_KEY_ARTIST,book.getAuthor()) .build()); if(cover != null) builder.setLargeIcon(cover); } startNotification(); } private NotificationCompat.Action generateAction(int icon,String Title) { return new NotificationCompat.Action.Builder( icon,Title,PendingIntentHelper.getPlayPauseIntent(this)).build(); } private voID startNotification() { mediaSession.setPlaybackState(new PlaybackStateCompat.Builder() .setActions(MEDIA_SESSION_ACTIONS) .setState(mediaPlayer.isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,book.getLastposition(),1) .build()); if(mediaPlayer.isPlaying()) startForeground(NOTIFICATION_ID,builder.build()); else { notificationmanager notificationmanager = (notificationmanager)getSystemService(NOTIFICATION_SERVICE); if(notificationmanager != null) { notificationmanager.notify(NOTIFICATION_ID,builder.build()); } stopForeground(false); } }
以下是服务销毁时发生的情况:
@OverrIDepublic voID onDestroy() { //super.onDestroy(); handleDestroy();}private voID handleDestroy() { if(book != null) sendProgressUpdate(); else book = new BookDBHelper(this).getBook(SettingsUtil.GetLastPlayedBook(this)); if(mediaPlayer != null) { book.setLastposition(this,getposition()); SyncHelper.SendProgressUpdate(this,book); } if(mediaSession != null) mediaSession.release(); if(noisyRegistered) { unregisterReceiver(becomingNoisyReceiver); unregisterReceiver(shakeReceiver); } buildNotification(); }解决方法 好的.我发现stopForeground函数有一个标志的可选参数而不是布尔值.可以给它一个标志Stop_FOREGROUND_DETACH,即使在调用stopForeground之后也需要从服务中分离通知,这样当服务被销毁时,通知将不会被解除,并且不需要构建新的通知.这是我更新的启动通知代码:
private voID startNotification() { int NOTIFICATION_ID = 7853154; mediaSession.setPlaybackState(new PlaybackStateCompat.Builder() .setActions(MEDIA_SESSION_ACTIONS) .setState(mediaPlayer.isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,1) .build()); if(mediaPlayer.isPlaying()) startForeground(NOTIFICATION_ID,builder.build()); else { stopForeground(Stop_FOREGROUND_DETACH); notificationmanager notificationmanager = (notificationmanager)getSystemService(NOTIFICATION_SERVICE); if(notificationmanager != null) { notificationmanager.notify(NOTIFICATION_ID,builder.build()); } }}总结
以上是内存溢出为你收集整理的android – 在Oreo中销毁服务时保持通知不被解雇全部内容,希望文章能够帮你解决android – 在Oreo中销毁服务时保持通知不被解雇所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)