manager - open activity from notification android
PendingIntent funciona correctamente para la primera notificación pero incorrectamente para el resto (13)
protected void displayNotification(String response) {
Intent intent = new Intent(context, testActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification = new Notification(R.drawable.icon, "Upload Started", System.currentTimeMillis());
notification.setLatestEventInfo(context, "Upload", response, pendingIntent);
nManager.notify((int)System.currentTimeMillis(), notification);
}
Esta función se llamará varias veces. Me gustaría que cada notification
inicie testActivity cuando se hace clic. Lamentablemente, solo la primera notificación inicia testActivity. Al hacer clic en el resto, se minimiza la ventana de notificación.
Información adicional: Función displayNotification()
está en una clase llamada UploadManager
. Context
se pasa a UploadManager
desde la activity
que UploadManager
la instancia. Función displayNotification()
se llama varias veces desde una función, también en UploadManager, que se ejecuta en una AsyncTask
.
Editar 1: Olvidé mencionar que estoy pasando la respuesta de Cadena al Intent intent
como un extra
.
protected void displayNotification(String response) {
Intent intent = new Intent(context, testActivity.class);
intent.putExtra("response", response);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Esto hace una gran diferencia porque necesito la "respuesta" adicional para reflejar qué respuesta de cadena fue cuando se creó la notificación. En cambio, al usar PendingIntent.FLAG_UPDATE_CURRENT
, la "respuesta" adicional refleja qué respuesta de cadena fue en la última llamada a displayNotification()
.
Sé por qué esto es por leer la documentación en FLAG_UPDATE_CURRENT
. Sin embargo, no estoy seguro de cómo solucionarlo en este momento.
Set Action Resolvió esto para mí. Aquí está mi entendimiento de la situación:
Tengo varios widgets que tienen un PendingIntent adjunto a cada uno. Cada vez que uno se actualizó, todos se actualizaron. Los Indicadores están ahí para describir lo que ocurre con los Ítems Pendientes que son exactamente lo mismo.
La descripción de FLAG_UPDATE_CURRENT ahora es mucho mejor:
Si ya existe el mismo PendingIntent que está creando, actualice todos los antiguos al nuevo PendingIntent que está creando.
La definición de exactamente lo mismo se ve en todo PendingIntent EXCEPTO los extras. Por lo tanto, incluso si tiene diferentes extras en cada intento (para mí, yo estaba agregando el appWidgetId) luego a Android, son lo mismo.
Agregar .setAction con una cadena única ficticia le dice al sistema operativo. Estos son completamente diferentes y no actualizan nada. Al final aquí está mi implementación que funciona como yo quería, donde cada widget tiene su propia configuración de intención adjunta:
Intent configureIntent = new Intent(context, ActivityPreferences.class);
configureIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
configureIntent.setAction("dummy_unique_action_identifyer" + appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, configureIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
ACTUALIZAR
Una solución aún mejor en caso de que esté trabajando con transmisiones. Unique PendingIntents también se definen mediante códigos de solicitud únicos. Aquí está mi solución:
//Weee, magic number, just want it to be positive nextInt(int r) means between 0 and r
int dummyuniqueInt = new Random().nextInt(543254);
PendingIntent pendingClearScreenIntent = PendingIntent.getBroadcast(context,
dummyuniqueInt, clearScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Como dice la documentación, use un código de solicitud único:
Si realmente necesita varios objetos distintos PendingIntent activos al mismo tiempo (por ejemplo, para utilizarlos como dos notificaciones que se muestran al mismo tiempo), deberá asegurarse de que haya algo diferente en ellos para asociarlos con diferentes PendingIntents. Este puede ser cualquiera de los atributos de intención considerados por Intent.filterEquals, o diferentes enteros de código de solicitud suministrados a getActivity (Context, int, Intent, int), getActivities (Context, int, Intent [], int), getBroadcast (Context, int , Intento, int), o getService (Context, int, Intent, int).
Estaba luchando con RemoteViews
y varias Intents
diferentes para cada Button
en Widget de HomeScreen
. Funcionó cuando se agregaron estos:
1. intent.setAction(Long.toString(System.currentTimeMillis()));
2. PendingIntent.FLAG_UPDATE_CURRENT
PackageManager pm = context.getPackageManager();
Intent intent = new Intent(context, MyOwnActivity.class);
intent.putExtra("foo_bar_extra_key", "foo_bar_extra_value");
intent.setAction(Long.toString(System.currentTimeMillis()));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
views.setOnClickPendingIntent(my_button_r_id_received_in_parameter, pendingIntent);
Fwiw, he tenido mejor suerte con PendingIntent.FLAG_CANCEL_CURRENT
que con PendingIntent.FLAG_UPDATE_CURRENT
.
No use Intent.FLAG_ACTIVITY_NEW_TASK
para PendingIntent.getActivity, use FLAG_ONE_SHOT en FLAG_ONE_SHOT lugar
Copiado de los comentarios:
A continuación, establezca una acción ficticia en el Intent, de lo contrario, los extras se descartarán. Por ejemplo
intent.setAction(Long.toString(System.currentTimeMillis()))
Tengo el mismo problema y uso el PendingIntent.html.FLAG_UPDATE_CURRENT para solucionarlo.
Revisé el código fuente. En ActivityManagerService.java , el método clave es el siguiente. Cuando el indicador es PendingIntent.FLAG_UPDATE_CURRENT y updateCurrent es verdadero. Algunos extras serán reemplazados por nuevos y obtendremos un PendingIntent reemplazado.
IIntentSender getIntentSenderLocked(int type, String packageName,
int callingUid, int userId, IBinder token, String resultWho,
int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
Bundle bOptions) {
// ... omitted
final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
|PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntentRecord.Key key = new PendingIntentRecord.Key(
type, packageName, activity, resultWho,
requestCode, intents, resolvedTypes, flags, bOptions, userId);
WeakReference<PendingIntentRecord> ref;
ref = mIntentSenderRecords.get(key);
PendingIntentRecord rec = ref != null ? ref.get() : null;
if (rec != null) {
if (!cancelCurrent) {
if (updateCurrent) {
if (rec.key.requestIntent != null) {
rec.key.requestIntent.replaceExtras(intents != null ?
intents[intents.length - 1] : null);
}
if (intents != null) {
intents[intents.length-1] = rec.key.requestIntent;
rec.key.allIntents = intents;
rec.key.allResolvedTypes = resolvedTypes;
} else {
rec.key.allIntents = null;
rec.key.allResolvedTypes = null;
}
}
return rec;
}
rec.canceled = true;
mIntentSenderRecords.remove(key);
}
Tuve el mismo problema y lo solucioné siguiendo los pasos a continuación
1) Borrar cualquier bandera para intentar
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
2) inserte intent.setAction con el siguiente código
intent.setAction(Long.toString(System.currentTimeMillis()));
3) para Pendingintent, inserte el código a continuación
PendingIntent Pintent = PendingIntent.getActivity(ctx,0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
Espero trabajar contigo
Tuve el mismo problema y pude solucionarlo cambiando la bandera a:
LayoutInflater factory = LayoutInflater.from(this);
final View textEntryView = factory.inflate(R.layout.appointment, null);
AlertDialog.Builder bulider= new AlertDialog.Builder(PatientDetail.this);
final AlertDialog alert=bulider.create();
bulider.setTitle("Enter Date/Time");
bulider.setView(textEntryView);
bulider.setPositiveButton("Save", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
EditText typeText=(EditText) textEntryView.findViewById(R.id.Editdate);
EditText input1 =(EditText) textEntryView.findViewById(R.id.Edittime);
getDateAndTime(typeText.getText().toString(),input1.getText().toString());
}
});
bulider.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
bulider.show();
}
Tuve el mismo problema y pude solucionarlo cambiando la bandera a:
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Veo respuestas pero no hay explicaciones. Además, ninguna de las respuestas aborda todas las soluciones posibles, así que intentaré dejar eso en claro.
Documentación:
Si realmente necesita varios objetos distintos PendingIntent activos al mismo tiempo (por ejemplo, para utilizarlos como dos notificaciones que se muestran al mismo tiempo), deberá asegurarse de que haya algo diferente en ellos para asociarlos con diferentes PendingIntents. Este puede ser cualquiera de los atributos de intención considerados por Intent.filterEquals, o diferentes enteros de código de solicitud suministrados a getActivity (Context, int, Intent, int), getActivities (Context, int, Intent [], int), getBroadcast (Context, int , Intento, int), o getService (Context, int, Intent, int).
Causa del problema:
Crea 2 notificaciones con 2 intenciones pendientes. Cada intento pendiente está asociado a una intención:
Intent intent = new Intent(context, testActivity.class);
Sin embargo, estos 2 intentos son iguales, por lo tanto, cuando llegue tu segunda notificación, se lanzará el primer intento.
Solución:
Tienes que hacer que cada intento sea único, de modo que ningún intento pendiente sea igual. ¿Cómo haces que los intentos sean únicos? No por los extras que pones con putExtra()
. Incluso si los extras son diferentes, los intentos podrían ser iguales. Para que cada intento sea único, debe establecer un valor único para la acción de intención, o datos, o tipo, o clase, o categoría, o código de solicitud: (cualquiera de ellos funcionará)
- acción:
intent.setAction(...)
- data:
intent.setData(...)
- tipo:
intent.setType(...)
- clase:
intent.setClass(...)
- categoría:
intent.addCategory(...)
- código de solicitud:
PendingIntent.getActivity(context, YOUR_UNIQUE_CODE, intent, Intent.FLAG_ONE_SHOT);
Nota : Establecer un código de solicitud único puede ser complicado porque necesita un int, mientras que System.currentTimeMillis()
devuelve long, lo que significa que se eliminarán algunos dígitos. Por lo tanto, recomendaría ir con la categoría o la acción y establecer una cadena única.
para enviar datos extra correctamente, debe enviar con intención pendiente el ID de notificación como este: PendingIntent pendingIntent = PendingIntent.getActivity (context, (int) System.currentTimeMillis () , intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Use pending Intent and also use unique id for display notification....
// Get a PendingIntent containing the entire back stack
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotificationManager = (NotificationManager) sqlitewraper.context.getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(id, builder.build());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
En PendingIntent hay dos parámetros int, el segundo y el último. El segundo es el "código de solicitud" y debe ser un número único (por ejemplo, id de tu notificación), sino (si en tu ejemplo es igual a cero, siempre se sobrescribirá).