5

Ho un IntentService che carica un file. Tutto funziona bene, ma sono un po 'confuso su come gestire le notifiche. Quando avvio la notifica, utilizzo startForeground() perché i file possono essere piuttosto grandi e non voglio che il caricamento venga ucciso a meno che non sia assolutamente necessario. Quando uso startForeground() visualizza due notifiche nell'area di notifica (uno sotto in corso e un'altra in Notifiche):Come gestire correttamente startForegrounds due notifiche

Example:

che ho letto attraverso una serie di diversi posti di overflow dello stack e articoli web, ma nessuno di loro rispondono alla domanda che ho ... spero di non aver perso uno che parla di questo.

È a mia conoscenza che la notifica in corso nell'immagine sopra (quella senza la barra di avanzamento) viene inserita poiché è in esecuzione in primo piano (Services documentation). Va tutto bene se me lo chiedi, e capisco perché. Tuttavia, non ho bisogno di due notifiche visualizzate e sono abbastanza sicuro che la maggior parte delle persone non vorrebbe che due notifiche ingombrino l'area di notifica. Mi piacerebbe sapere come gestire correttamente la notifica in modo che solo uno schermo e non ingombrare l'area di notifica.

L'unico modo in cui sono stato in grado di aggirare questo è se ho impostato l'ID intero per startForeground (int id, Notification notification) (ONGOING_NOTIFICATION_ID nel mio codice qui sotto) a zero. Tuttavia, la documentazione cito sopra dice:

Caution: The integer ID you give to startForeground() must not be 0

Impostandola a 0 disabilita la notifica in corso e poi basta mostra la notifica regolare con la barra di avanzamento. Immagino di poter "sistemare" questo problema impostando .setOngoing(true) fino a quando non è stato completato il caricamento del file e quindi l'impostazione di .setOngoing(false) una volta terminata, in modo che possa essere chiusa. Non sono sicuro di come si debba essere "cauti" con l'impostazione dell'ID intero su 0. Per me sembra un modo pigro per essere in grado di aggirare il problema che sto avendo, ma non lo faccio sapere se ci sono altre conseguenze per impostarlo su 0. Inoltre, questo funziona solo se ho solo una notifica con cui ho a che fare. Se ho più notifiche diverse, allora avrò bisogno di ID diversi per ognuno e questo non funzionerà. Aggiornamento: Sembra setting the ID to 0 won't work in Android 4.3, quindi ora torno al punto di partenza.

Qual è un modo valido per andare in giro visualizzando entrambe le notifiche?

Aggiornamento/Soluzione: Duh, prendersi un po 'di tempo libero e poi tornare a questo e ricontrollare ciò che avevo fatto in base alla raccomandazione di @dsandler mi ha aiutato a capire cosa stavo facendo male. Non stavo impostando l'ID corretto quando stavo facendo l'aggiornamento del progresso, ecco perché stava creando due notifiche e una non veniva aggiornata. L'utilizzo dello stesso ID (ONGOING_NOTIFICATION_ID) per tutte le notifiche ha risolto il problema per me. Vedere il codice qui sotto per i pezzi aggiuntivi che non avevo incluso prima e dove avevo commesso l'errore.

codice

Rilevante da UploadFile.java:

public class UploadFile extends IntentService { 

    private static final int ONGOING_NOTIFICATION_ID = 1; 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
     mBuilder = new NotificationCompat.Builder(this); 
     mBuilder.setContentTitle(getText(R.string.upload)) 
      .setContentText("0% " + getText(R.string.upload_in_progress)) 
      .setSmallIcon(android.R.drawable.stat_sys_upload); 

     startForeground(ONGOING_NOTIFICATION_ID, mBuilder.build()); 


.... 

    if (progress > 0){ 
     percent = (Long.valueOf(progress) * 100)/totalSize; 
     mBuilder.setProgress(100, percent.intValue(), false); 
     mBuilder.setContentText(percent.intValue() + "% " + getText(R.string.upload_in_progress)); 
     mNotifyManager.notify(ONGOING_NOTIFICATION_ID, mBuilder.build()); // <-- My problem was that I had set the ID here to 0 and did not make it the same as the ID I set above 
    }      

.... 

} 

risposta

1

Prima di tutto, a giudicare dalla descrizione, si potrebbe essere in grado di cavarsela con un servizio regolare, riconoscendo che il killer out-of-memory ha vinto' Viene la chiamata a meno che le cose non stiano peggiorando sul dispositivo e il tuo servizio ha funzionato davvero da molto tempo.

Detto questo, se è necessario rendere il servizio in primo piano, la strategia tipica qui è mostrare i propri progressi utilizzando la notifica che si è utilizzata quando si mette il servizio in primo piano. Usando NotificationManager.notify puoi postare tutti gli aggiornamenti a tale notifica come vuoi, ad esempio le regolazioni alle barre di avanzamento tramite Notification.Builder.setProgress, ad esempio.

In questo modo viene mostrata all'utente solo una notifica, ed è quella richiesta da startForeground.

+0

grazie per la risposta. Sono tornato indietro e ho ricontrollato quello che stavo facendo (che stava facendo ciò che mi hai consigliato) e mi sono reso conto che non stavo usando l'ID di notifica corretto quando ho postato i progressi. Ora funziona come un incantesimo! – Jason

+0

Ho una domanda riguardante la notifica: quale icona dovrebbe essere usata per "setLargeIcon", se vuoi usare quella di Android (come hai fatto per "setSmallIcon")? –

+0

Perché è necessario ** NotificationManager.notify **? 'startForegroundService()' mostra già la notifica. –

-1

Quando si desidera aggiornare un set di notifiche di startForeground(), è sufficiente creare una nuova notificazione e quindi utilizzare NotificationManager per notificarlo.

Il punto KEY è utilizzare lo stesso ID di notifica.

Non ho provato lo scenario di chiamare ripetutamente startForeground() per aggiornare la notifica, ma penso che l'uso di NotificationManager.notify sarebbe meglio.

L'aggiornamento della notifica NON rimuoverà il servizio dallo stato in primo piano (ciò può essere fatto solo chiamando stopForground);

Esempio:

private static final int notif_id=1; 

@Override 
public void onCreate(){ 
    this.startForeground(); 
} 

private void startForeground() { 
     startForeground(notif_id, getMyActivityNotification("")); 
} 

private Notification getMyActivityNotification(String text){ 
     // The PendingIntent to launch our activity if the user selects 
     // this notification 
     CharSequence title = getText(R.string.title_activity); 
     PendingIntent contentIntent = PendingIntent.getActivity(this, 
       0, new Intent(this, MyActivity.class), 0); 

     return new Notification.Builder(this) 
       .setContentTitle(title) 
       .setContentText(text) 
       .setSmallIcon(R.drawable.ic_launcher_b3) 
       .setContentIntent(contentIntent).getNotification();  
} 
/** 
this is the method that can be called to update the Notification 
*/ 
private void updateNotification() { 

       String text = "Some text that will update the notification"; 

       Notification notification = getMyActivityNotification(text); 

       NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
       mNotificationManager.notify(notif_id, notification); 
} 
Problemi correlati