W naszej aplikacji OneBusAway z systemem Android (open-source on Github), musimy otrzymać powiadomienie, gdy użytkownik odrzuci powiadomienie o konkretnym przypomnieniu, więc nie wysyłamy kolejnego powiadomienia o przypomnieniu dla tego samego wydarzenia (jak długo do przybycia autobusu).Powiadomienie DeleteIntent jest uszkodzone w nowszych wersjach Androida
Robimy to słuchając Intent
w naszej aplikacji, zarejestrowanej jako DeleteIntent
z Notification
. Gdy użytkownik odrzuci powiadomienie (albo przesuwając je, albo dotykając przycisku kasowania w oknie powiadomień), nasza aplikacja powinna otrzymać tę Intent
.
Z badań wydaje się, że z the current version on Google Play (i current master branch on Github), to nigdy nie otrzymał DeleteIntent w naszej aplikacji w następujących wersjach Androida:
- Android 4.4.3
- Android 4.4.4
jednak dokładnie ten sam kod CZY pracę (tj Intent zarejestrowany jako DeleteIntent jest odbierany przez aPP) na:
- Android 2.3.3
- Android 2.3.6
- Android 4.1.1
- Android 4.1.2
Szukałem w następujących SO stanowisk, które zajmują się DeleteIntent, Żadne z wymienionych rozwiązań nie działają w systemie Android 4.4.3 i 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
Obecny mistrz roboczego gałąź wykorzystuje usługę do słuchania dla intencyjny. Jednakże, na podstawie niektórych z powyższych postów, zmodyfikowałem trochę kodu tak, aby był bardziej zgodny z przykładami pracy, które wykorzystują BroadcastReceiver do słuchania intencji.
Kod pomocą BroadcastReceiver jest w następujący GitHub Branża:
https://github.com/CUTR-at-USF/onebusaway-android/tree/issue104-RepeatingReminders
Poniżej znajdują się fragmenty o co moja obecna wersja wygląda (który nadal działa na Androidzie 4.1.2 i niższe, ale nie 4,4 .3 lub 4.4.4), wraz z linkami do GitHub źródła:
Tworzenie powiadomienia
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();
}
Tytuł i inne informacje dynamiczne powiadomienia są ustawione kilka linijek później (i przywrócić później , jeśli powiadomienie pozostanie nierozstrzygnięte):
@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
zawiera stałe do działania:
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>
z powyższym, na Androidzie 4.4.3/4.4.4 The AlarmReceiver nie widzi Intent, gdy użytkownik odrzuca zgłoszenie.
Próbowałem też dodanie typu MIME, jak określono w Custom actions using implicit intents between applications, ale to nie działa na Androidzie 4.4.3/4.4.4 albo:
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
jest application/vnd.com.joulespersecond.seattlebusbot.reminder
Oczywisty dla przy użyciu typu 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>
próbowałem też nie z wykorzystaniem wsparcia l ibrary (to jest, używając Notification.Builder
zamiast NotificationCompat.Builder
), ale to też niczego nie zmieniło.
Jakieś pomysły, dlaczego to nie działa w systemie Android 4.4.3/4.4.4?
Więcej informacji jest pokazane w Github issue dla tego problemu.
EDIT
Ja również powielane ten problem w małym projekcie GitHub "DeleteIntentDemo":
https://github.com/barbeau/DeleteIntentDemo
Instrukcje do odtworzenia są w README dla tego projektu.
EDIT 2
Wydaje się to być spowodowane błędem w systemie Android w Notification.setLatestEventInfo()
- ja już zgłaszane tutaj: https://code.google.com/p/android/issues/detail?id=73720
proszę zobaczyć @ odpowiedź CommonsWare za obejścia.
EDIT 3
Moja AOSP łata, aby rozwiązać ten problem został już połączyły więc ten problem nie pojawi się dla starszych aplikacji w przyszłych wydaniach Androida: https://code.google.com/p/android/issues/detail?id=73720#c4
Jednak w powyższym W wątku AOSP podkreślono, że nie należy już używać Notification.setLatestEventInfo()
- zamiast tego należy użyć Notification.Builder
, aby utworzyć nowe powiadomienie.
Czy próbowałeś wyraźnego "zamiaru"? Jeśli te działania nie są częścią publicznego zestawu SDK, do którego mają się odwoływać osoby trzecie, nie powinieneś mieć '' on 'AlarmReceiver'. Nie mogę odtworzyć twojego problemu z wyraźnym 'Intent' -' setDeleteIntent() 'działa poprawnie na moim Nexusie 4 działającym 4.4.4. –
CommonsWare
'Intent deleteIntent = new Intent (mContext, AlarmReceiver.class) ;, który jest obecnie używany, jest wyraźnym intencją, prawda? Niektóre z tych projektów są wcześniejsze niż moje zaangażowanie w projekt, ale uważam, że pomysł polegał na tym, aby (ostatecznie) zezwalać zewnętrznym aplikacjom na planowanie/kasowanie alarmów tranzytowych, a także wywoływanie tych samych działań z wewnętrznego kodu. Próbowałem usunąć '' s na AlarmReceiver, ale to niczego nie zmieniło. –
@CommonsWare U dołu mojej odpowiedzi dodałem mały przykładowy projekt na Github, który odtwarza problem - https://github.com/barbeau/DeleteIntentDemo. Wszelkie opinie są mile widziane.Jeśli mógłbyś dostarczyć próbkę, która działa poprawnie, to też by pomogło. –