14

我有一個媒體服務使用startForeground()在播放開始時顯示通知。播放時暫停/停止按鈕,暫停時播放/停止按鈕。允許通知在調用stopForeground(false)後被取消

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this); 
// setup... 

Notification n = mBuilder.build(); 

if (state == State.Playing) { 
    startForeground(mId, n); 
} 
else { 
    stopForeground(false); 
    mNotificationManager.notify(mId, n);   
} 

這裏的問題是,當我顯示/更新處於暫停狀態的通知時,應該允許您將其刪除。 mBuilder.setOngoing(false)似乎沒有效果,因爲之前的startForeground會覆蓋它。

使用相同的代碼調用stopForeground(true);的工作方式與預期的一樣,但通知會在銷燬和重新創建時閃爍。有沒有辦法「更新」從startForeground創建的通知,以便在通話結束後可以將其刪除?

編輯:根據要求,這裏是創建通知的完整代碼。每當服務被播放或暫停時,都會調用createNotification。

private void createNotification() { 
    NotificationCompat.Builder mBuilder = 
      new NotificationCompat.Builder(this) 
    .setSmallIcon(R.drawable.ic_launcher) 
    .setContentTitle("No Agenda") 
    .setContentText("Live stream"); 

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) 
    { 
     if (state == State.Playing) { 
      Intent pauseIntent = new Intent(this, MusicService.class); 
      pauseIntent.setAction(ACTION_PAUSE); 
      PendingIntent pausePendingIntent =  PendingIntent.getService(MusicService.this, 0, pauseIntent, 0);    

      mBuilder.addAction(R.drawable.pause, "Pause", pausePendingIntent); 
      //mBuilder.setOngoing(true); 
     } 
     else if (state == State.Paused) { 
      Intent pauseIntent = new Intent(this, MusicService.class); 
      pauseIntent.setAction(ACTION_PAUSE); 
      PendingIntent pausePendingIntent = PendingIntent.getService(MusicService.this, 0, pauseIntent, 0); 

      mBuilder.addAction(R.drawable.play, "Play", pausePendingIntent); 
      mBuilder.setOngoing(false); 
     } 

     Intent stopIntent = new Intent(this, MusicService.class); 
     stopIntent.setAction(ACTION_STOP); 
     PendingIntent stopPendingIntent = PendingIntent.getService(MusicService.this, 0, stopIntent, 0); 

     setNotificationPendingIntent(mBuilder); 
     mBuilder.addAction(R.drawable.stop, "Stop", stopPendingIntent); 
    } 
    else 
    { 
     Intent resultIntent = new Intent(this, MainActivity.class); 
     PendingIntent intent = PendingIntent.getActivity(this, 0, resultIntent, 0); 

     mBuilder.setContentIntent(intent); 
    } 

    Notification n = mBuilder.build(); 

    if (state == State.Playing) { 
     startForeground(mId, n); 
    } 
    else { 
     stopForeground(true); 
     mNotificationManager.notify(mId, n); 
    } 
} 

@TargetApi(Build.VERSION_CODES.JELLY_BEAN) 
private void setNotificationPendingIntent(NotificationCompat.Builder mBuilder) { 
    Intent resultIntent = new Intent(this, MainActivity.class); 

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 
    stackBuilder.addParentStack(MainActivity.class); 
    stackBuilder.addNextIntent(resultIntent); 

    PendingIntent resultPendingIntent = 
      stackBuilder.getPendingIntent(
       0, 
       PendingIntent.FLAG_UPDATE_CURRENT 
      ); 

    mBuilder.setContentIntent(resultPendingIntent); 
} 

後續編輯:下面

一位評論提到,答案可能是「脆弱的」,並且採用Android 4.3的發佈,背後startForeground的行爲發生了變化。 startForeground會強制您的應用程序在前臺顯示通知,並且只需在顯示通知的情況下調用該方法即可。我沒有測試過,但接受的答案可能不再按預期工作。

在致電stopForeground時停止閃爍的方面,我不認爲值得與框架戰鬥。有一些additional information on the Android 4.3 notification change here

+0

當你嘗試調用'setOngoing(false)'時,你可以顯示你的代碼嗎?我懷疑這個通知並沒有被重建來接收這些更改,但很難從這段代碼中看出來。 – dsandler 2013-03-25 15:14:15

+0

@dsandler我已經添加了createNotification()的完整代碼。 – 2013-03-26 00:24:51

+0

我還想指出,目前我只在Jellybean上測試,目前是4.2.2(模擬器和手機),這是我設置setOngoing(false)的地方。此外,setOngoing(false)在通知不是通過startForeground啓動(並且setOngoing(true)未註釋)時才起作用。 – 2013-03-26 00:44:46

回答

4

您可以考慮使用不同的方法。
因爲你應該使用前臺服務這樣的任務(媒體播放)我建議你繼續做start foreground(),但不是傳遞一個通知給它只需設置ID 0和通知null像這樣startForeground(0, null);

這樣前景服務將不會顯示任何通知。

現在,爲了您的目的,您可以使用常規通知並更新其狀態(正在進行的,佈局,文本等),這樣您就不依賴前臺服務的通知行爲。

希望這會有所幫助。

+0

這聽起來像是正確的路徑,但傳遞null通知會在startForeground()上引發IllegalArgumentException。下面的問題似乎表明相同:http://stackoverflow.com/questions/10962418/startforeground-without-showing-notification – 2013-04-09 08:39:53

+0

這很有趣,因爲我已經使用了這種方法幾次,只是重新測試它與空白項目。我也通過查詢'PackageManager'來確保服務確實在前臺運行。您也可以嘗試在'startForeground(id,notification)' – 2013-04-09 10:10:53

+0

中使用0作爲id,使用0作爲id工作,並且所有內容都按預期工作。除0之外的任何id似乎都會導致IllegalArgumentException。完善! – 2013-04-09 20:28:30

2

根據docs此行爲是設計棒棒堂之前

應用針對這個或以後的版本會得到這些行爲中的新變化:

...

  • 呼叫服務使用removeNotification false的.stopForeground將修改仍發佈的通知,以使其不再被強制進行。
1

代替stopService(true),主叫stopService(false)將保留通知,因爲它是(沒有正在進行的狀態),除非它被使用者駁回/移除編程或如果服務停止。因此,只需調用stopService(false)並更新通知以顯示暫停狀態,現在通知可以由用戶解除。這也可以防止閃爍,因爲我們沒有重新創建通知。

+0

這完美地工作 – Hackmodford 2016-06-27 23:36:19

相關問題