Nella nostra app OneBusAway Android (open-source on Github), è necessario essere avvisati quando l'utente chiude una particolare notifica di sollecito, quindi non pubblichiamo un'altra notifica di promemoria per lo stesso evento (per quanto tempo fino a quando arriva il loro autobus).Notifica DeleteIntent interrotta nelle versioni successive di Android
Lo stiamo ascoltando per un Intent
nella nostra app, registrato come DeleteIntent
con il Notification
. Quando l'utente rifiuta la notifica (sia scorrendo via, o toccando il pulsante Cancella nella finestra di notifica), la nostra app dovrebbe ricevere tale Intent
.
Da test, sembra che con the current version on Google Play (e la current master branch on Github), il DeleteIntent non viene mai ricevuto nella nostra applicazione nelle seguenti versioni di Android:
- Android 4.4.3
- Android 4.4.4
Tuttavia, lo stesso identico codice di DOES lavoro (vale a dire, l'intento registrato come DeleteIntent viene ricevuto dal app) su:
- Android 2.3.3
- Android 2.3.6
- Android 4.1.1
- Android 4.1.2
Ho guardato i seguenti SO messaggi che si occupano di DeleteIntent, e nessuna delle soluzioni elencate lavoro su Android 4.4.3 e 4.4.4:
- Notification Auto-Cancel does not call DeleteIntent
- Android - DeleteIntent, how to use?
- Notification deleteIntent does not work
- https://stackoverflow.com/questions/24218626/how-to-detect-notification-cancel-event-in-android-not-deleteintent
- https://stackoverflow.com/questions/22769523/why-my-deleteintent-is-not-working-on-my-notification
- Android deleteIntent not working? What's wrong with my code?
- Custom actions using implicit intents between applications
Il branch master di lavoro attuale utilizza un servizio per ascoltare l'intento. Tuttavia, basandomi su alcuni dei post di cui sopra, ho modificato alcuni dei codici per essere più in linea con gli esempi di lavoro che utilizzano un BroadcastReceiver per ascoltare l'Intent.
Il codice utilizzando il BroadcastReceiver è nel seguente ramo Github:
https://github.com/CUTR-at-USF/onebusaway-android/tree/issue104-RepeatingReminders
Qui di seguito sono estratti di ciò che la mia versione attuale sembra (che funziona ancora su Android 4.1.2 e inferiori, ma non 4.4 .3 o 4.4.4), insieme con i link alle Github fonte:
Creare la notifica
private Notification createNotification(Uri alertUri) {
//Log.d(TAG, "Creating notification for alert: " + alertUri);
Intent deleteIntent = new Intent(mContext, AlarmReceiver.class);
deleteIntent.setAction(TripService.ACTION_CANCEL);
deleteIntent.setData(alertUri);
return new NotificationCompat.Builder(mContext)
.setSmallIcon(R.drawable.ic_stat_notification)
.setDefaults(Notification.DEFAULT_ALL)
.setOnlyAlertOnce(true)
.setDeleteIntent(PendingIntent.getBroadcast(mContext, 0,
deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setAutoCancel(true)
.build();
}
Titolo e altre informazioni di notifica dinamica sono impostate poche righe dopo (e ripristinati in seguito , se la notifica rimane non modificata):
@SuppressWarnings("deprecation")
private void setLatestInfo(Notification notification,
String stopId,
String routeId,
long timeDiff) {
final String title = mContext.getString(R.string.app_name);
final PendingIntent intent = PendingIntent.getActivity(mContext, 0,
new ArrivalsListActivity.Builder(mContext, stopId).getIntent(),
PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(mContext,
title,
getNotifyText(routeId, timeDiff),
intent);
}
TripService
contiene le costanti per l'azione:
public static final String ACTION_CANCEL =
"com.joulespersecond.seattlebusbot.action.CANCEL";
AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver {
private static final String TAG = "AlarmReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "In onReceive with intent action " + intent.getAction());
...
}
}
AndroidManifest
<receiver android:name=".AlarmReceiver">
<!-- These action names must match the constants in TripService -->
<intent-filter>
<action android:name="com.joulespersecond.seattlebusbot.action.SCHEDULE" />
<action android:name="com.joulespersecond.seattlebusbot.action.POLL" />
<action android:name="com.joulespersecond.seattlebusbot.action.CANCEL" />
</intent-filter>
</receiver>
Con quanto sopra, su Android 4.4.3/4.4.4, l'AlarmReceiver non vede mai l'Intento quando l'utente chiude la notifica.
Ho anche provato ad aggiungere un tipo MIME, come specificato nella Custom actions using implicit intents between applications, ma che non ha funzionato su Android 4.4.3/4.4.4 o:
Intent deleteIntent = new Intent(mContext, AlarmReceiver.class);
deleteIntent.setAction(TripService.ACTION_CANCEL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
deleteIntent.setDataAndTypeAndNormalize(alertUri, TripService.REMINDER_MIME_TYPE);
} else {
deleteIntent.setDataAndType(alertUri, TripService.REMINDER_MIME_TYPE);
}
return new NotificationCompat.Builder(mContext)
.setSmallIcon(R.drawable.ic_stat_notification)
.setDefaults(Notification.DEFAULT_ALL)
.setOnlyAlertOnce(true)
.setDeleteIntent(PendingIntent.getBroadcast(mContext, 0,
deleteIntent, 0))
//.setLights(0xFF00FF00, 1000, 1000)
//.setVibrate(VIBRATE_PATTERN)
.build();
REMINDER_MIME_TYPE
è application/vnd.com.joulespersecond.seattlebusbot.reminder
Manifesto per utilizzando il tipo MIME:
<receiver android:name=".AlarmReceiver">
<!-- These action names must match the constants in TripService -->
<intent-filter>
<action android:name="com.joulespersecond.seattlebusbot.action.SCHEDULE" />
<action android:name="com.joulespersecond.seattlebusbot.action.POLL" />
<action android:name="com.joulespersecond.seattlebusbot.action.CANCEL" />
<data android:mimeType="application/vnd.com.joulespersecond.seattlebusbot.reminder" />
</intent-filter>
</receiver>
ho anche provato non utilizzando il supporto l ibrary (cioè, usando Notification.Builder
invece di NotificationCompat.Builder
), ma questo non ha cambiato nulla.
Qualche idea sul perché questo non funziona su Android 4.4.3/4.4.4?
Ulteriori informazioni sono visualizzate nello Github issue per questo problema.
EDIT
Ho anche replicato questo problema in un piccolo progetto GitHub "DeleteIntentDemo":
https://github.com/barbeau/DeleteIntentDemo
Istruzioni di riprodurre sono nel README per questo progetto.
EDIT 2
Questo sembra essere dovuto a un bug in Android in Notification.setLatestEventInfo()
- ho riportato qui: https://code.google.com/p/android/issues/detail?id=73720
Si prega di vedere @ risposta di CommonsWare per la soluzione.
EDIT 3
mia patch AOSP per risolvere questo problema è stato ora fusa quindi questo problema non verrà visualizzato per le applicazioni legacy in future versioni di Android: https://code.google.com/p/android/issues/detail?id=73720#c4
Tuttavia, in quanto sopra Il thread AOSP è sottolineato dal fatto che non si dovrebbe più usare Notification.setLatestEventInfo()
- invece, usare Notification.Builder
per creare una nuova Notifica.
Hai provato un esplicito 'Intento'? A meno che tali azioni non facciano parte di un SDK pubblico che le terze parti dovrebbero invocare, non si dovrebbe avere il su 'AlarmReceiver'. Non riesco a riprodurre il tuo problema con un esplicito 'Intento' -' setDeleteIntent() 'funziona bene sul mio Nexus 4 con 4.4.4. –
CommonsWare
'Intent deleteIntent = new Intent (mContext, AlarmReceiver.class);' che è attualmente in uso è un Intent esplicito, giusto? Alcuni di questi design sono precedenti al mio coinvolgimento nel progetto, ma credo che l'idea fosse di (eventualmente) consentire alle app esterne di programmare/annullare gli allarmi di transito e di attivare la stessa azione dal codice interno. Ho provato a rimuovere '' intent-filter> su AlarmReceiver, ma questo non ha cambiato nulla. –
@CommonsWare Alla fine della mia risposta ho aggiunto un piccolo progetto di esempio su Github che riproduce il problema - https://github.com/barbeau/DeleteIntentDemo. Qualsiasi feedback è apprezzato.Se potessi fornire l'esempio che funziona correttamente, sarebbe anche d'aiuto. –