14

Tôi có dịch vụ Phương tiện sử dụng startForeground() để hiển thị thông báo khi quá trình phát lại bắt đầu. Nó có nút tạm dừng/dừng khi chơi, chơi/dừng nút trong khi tạm dừng.Cho phép thông báo bị hủy sau khi gọi đến stopForeground (sai)

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);   
} 

Vấn đề ở đây là khi tôi hiển thị/cập nhật thông báo ở trạng thái tạm dừng, bạn nên được phép xóa thông báo đó. mBuilder.setOngoing(false) dường như không có tác dụng như trước startForeground ghi đè lên.

Gọi stopForeground(true); với cùng mã hoạt động như mong đợi, nhưng thông báo nhấp nháy khi bị phá hủy và được tạo lại. Có cách nào để "cập nhật" thông báo được tạo từ startForeground để cho phép nó được xóa sau khi ngừng gọi không?

Chỉnh sửa: Theo yêu cầu, đây là mã đầy đủ đang tạo thông báo. createNotification được gọi bất cứ khi nào dịch vụ được phát hoặc tạm dừng.

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); 
} 

Follow-up Edit:

Một trong những ý kiến ​​dưới đây đề cập rằng câu trả lời có thể là "mong manh", và tính đến việc phát hành Android 4.3, các hành vi sau startForeground đã thay đổi. startForeground sẽ buộc ứng dụng của bạn hiển thị thông báo trong khi ở nền trước và phương thức chỉ nên được gọi bằng thông báo để hiển thị. Tôi chưa thử nghiệm, nhưng câu trả lời được chấp nhận có thể không còn hoạt động như dự định.

Trong điều khoản dừng nhấp nháy khi gọi stopForeground, tôi không nghĩ rằng nó đáng để chiến đấu khung.

Có một số additional information on the Android 4.3 notification change here.

+0

Bạn có thể hiển thị mã của mình khi bạn cố gắng gọi 'setOngoing (false)' không? Tôi nghi ngờ thông báo không được xây dựng lại để nhận các thay đổi nhưng thật khó để nói từ đoạn mã này. – dsandler

+0

@dsandler Tôi đã thêm mã đầy đủ cho createNotification(). –

+0

Tôi cũng muốn chỉ ra rằng tôi chỉ đang thử nghiệm trên Jellybean vào lúc này, hiện tại là 4.2.2 (giả lập và điện thoại), đây là nơi tôi đang thiết lập setOngoing (false). Ngoài ra, setOngoing (false) không hoạt động khi thông báo không được bắt đầu thông qua startForeground (và setOngoing (true) là uncommented). –

Trả lời

4

Bạn có thể xem xét sử dụng một cách tiếp cận khác.
Vì bạn nên sử dụng dịch vụ nền trước cho một tác vụ như vậy (phương tiện truyền thông) Tôi đề nghị bạn tiếp tục làm start foreground(), nhưng thay vì gửi thông báo đến nó chỉ cần đặt id 0 và thông báo null như thế này startForeground(0, null);.

Bằng cách này, dịch vụ nền trước sẽ không hiển thị bất kỳ thông báo nào.

Bây giờ, vì mục đích của bạn, bạn có thể sử dụng thông báo thường xuyên và cập nhật trạng thái của chúng (liên tục, bố cục, văn bản, v.v.), bằng cách này bạn không phụ thuộc vào hành vi thông báo của dịch vụ nền trước.

Hy vọng điều này sẽ hữu ích.

+0

Điều này nghe có vẻ như đường dẫn chính xác, tuy nhiên đi qua một thông báo null ném một IllegalArgumentException trên startForeground(). Câu hỏi sau đây có vẻ giống nhau: http://stackoverflow.com/questions/10962418/startforeground-without-showing-notification –

+0

Thật thú vị, bởi vì tôi đã sử dụng phương pháp này trong một vài lần, và chỉ kiểm tra lại nó với một dự án trống. Tôi cũng đảm bảo rằng dịch vụ thực sự đang chạy nền trước bằng cách truy vấn 'PackageManager'. Bạn cũng có thể thử truyền 0 làm id trong 'startForeground (id, thông báo)' –

+0

Sử dụng 0 làm id, và mọi thứ hoạt động như mong đợi. Bất kỳ id nào khác ngoài 0 dường như gây ra IllegalArgumentException. Hoàn hảo! –

2

Theo docs hành vi này là do thiết kế trước khi Lollipop

Ứng dụng nhắm mục tiêu này hay một thông cáo sau này sẽ có được những thay đổi mới trong hành vi:

...

  • Calling Dịch vụ .stopForeground với removeNotification false sẽ sửa đổi thông báo vẫn được đăng để nó không còn bị buộc phải tiếp tục.
1

Thay vì stopService(true), gọi stopService(false) sẽ giữ lại thông báo vì nó là (không có tình trạng đang diễn ra) trừ khi nó được bác bỏ bởi người dùng/loại bỏ lập trình hoặc nếu dịch vụ dừng. Do đó chỉ cần gọi stopService (false) và cập nhật thông báo để hiển thị trạng thái bị tạm dừng và giờ đây thông báo có thể bị người dùng loại bỏ. Điều này cũng ngăn chặn nhấp nháy vì chúng tôi không tạo lại thông báo.

+0

Điều này hoạt động hoàn hảo – Hackmodford

Các vấn đề liên quan