web-dev-qa-db-fra.com

En cliquant sur Actions de notification Android ne ferme pas le tiroir de notification

J'ajoute une notification à la barre système à l'aide de la bibliothèque NotificationCompat. Cette notification a deux boutons d'action. En outre, la propriété AutoCancel() de la notification est définie sur true. 

Lors du clic sur les boutons d'action, le système est configuré pour lancer une IntentService qui appelle NotificationManager.cancel(NOTIFICATION_ID), puis lance une activité dans une nouvelle tâche.
Le problème est que même si cet appel supprime la notification du bac, il ne réduit pas le tiroir. L'activité appelée est dessinée derrière le tiroir. 

Quelqu'un peut-il faire la lumière sur le code spécial nécessaire pour fermer le tirage en dehors de l'annulation de la notification?

Je vous remercie.

44
Aster

Si votre action est sous la forme d'une diffusion ou d'un service mais que vous souhaitez que le tiroir de notification se réduise, vous devez diffuser Android.intent.action.CLOSE_SYSTEM_DIALOGS de votre onReceive. Cela fermera manuellement le tiroir.

41
Andro Id

J'ai constaté que lorsque vous utilisez les boutons d'action dans les notifications développées, vous devez écrire du code supplémentaire et vous êtes plus contraint. 

Avant d’utiliser les notifications développées, l’action par défaut de la notification de téléchargement de fichier consistait à démarrer une activité VIEW sur le fichier. L'intention de VIEW était encapsulée dans une intention de sélecteur. Je ne pouvais pas utiliser d'intention en attente pour l'intention de sélecteur directement à partir de la notification car le sélecteur plantait en l'absence d'activité pour afficher le type de fichier. J'ai donc eu un BroadcastReceiver qui lancerait l'intention de sélecteur. 

Avec les notifications développées, j'ai décidé de modifier la notification de téléchargement de fichier afin que l'action par défaut consiste à afficher l'activité des détails du fichier, avec des boutons d'action pour Afficher et envoyer. Comme indiqué par l'utilisateur 2536953, le démarrage d'un récepteur de radiodiffusion à partir de la notification ne ferme pas le tiroir de notification. En se basant sur ses informations selon lesquelles une activité ferait fermer le tiroir, j'ai remplacé mon récepteur de diffusion par NotificationActivity sans aucune interface utilisateur. 

Comme indiqué dans cet article Comment supprimer une notification Android après avoir cliqué sur une action , un autre problème est que vous devez annuler manuellement votre notification lorsque l'utilisateur clique sur un bouton d'action. La notification n'est automatiquement annulée que pour l'action par défaut. J'ai également ajouté du code dans NotificationActivity pour gérer cela. 

Construction de la notification étendue avec les boutons Voir et Envoyer:

    NotificationCompat.Builder builder = new NotificationCompat.Builder(m_context).setAutoCancel(true);

    final PendingIntent contentIntent = DownloadedFileIntentUtils.buildPendingItemDetailIntent(m_context, item);
        builder.setContentIntent(contentIntent);

    PendingIntent viewIntent = DownloadedFileIntentUtils.buildNotificationActionIntent(m_context, Intent.ACTION_VIEW,
                m_context.getString(R.string.action_open), uri, MimeTypeUtil.getMimeType(item), id);
    builder.addAction(R.drawable.actionbar_open_with, m_context.getString(R.string.action_open), viewIntent);

    PendingIntent sendIntent = DownloadedFileIntentUtils.buildNotificationActionIntent(m_context, Intent.ACTION_SEND,
                m_context.getString(R.string.action_send), uri, MimeTypeUtil.getMimeType(item), id);
    builder.addAction(R.drawable.actionbar_share, m_context.getString(R.string.action_send), sendIntent);

    builder.setTicker(title)
    .setContentTitle(title)
    .setContentText(text)
    .setSmallIcon(R.drawable.notification_download);
    .setStyle(new NotificationCompat.BigTextStyle().bigText(text));

    getNotificationManager().notify(id, builder.build());

Construire l'intention de démarrer une activité à partir des boutons d'action de notification:

    public static PendingIntent buildNotificationActionIntent(Context context, String action, String actionTitle, Uri uri,
        String mimeType, int notificationId) {
    // Build the file action intent (e.g. VIEW or SEND) that we eventually want to start.
    final Intent fileIntent = buildFileActionIntent(action, actionTitle, uri, mimeType);

    // Build the intent to start the NotificationActivity.
    final Intent notificationIntent = new Intent(context, NotificationActivity.class);
    // This flag must be set on activities started from a notification.
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // Pass the file action and notification id to the NotificationActivity.
    notificationIntent.putExtra(Intent.EXTRA_INTENT, fileIntent);
    notificationIntent.putExtra(IIntentCode.INTENT_EXTRA_NOTIFICATION_ID, notificationId);

    // Return a pending intent to pass to the notification manager.
    return PendingIntent.getActivity(context, s_intentCode.getAndIncrement(), notificationIntent, PendingIntent.FLAG_ONE_SHOT);
}

public static Intent buildFileActionIntent(String action, String actionTitle, 
        Uri uri, String mimeType) {
    Intent intent = new Intent(action);
    intent.addCategory(Intent.CATEGORY_DEFAULT);

    if (action.equals(Intent.ACTION_SEND)) {
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        intent.setType(mimeType);
    } else {
        intent.setDataAndType(uri, mimeType);
    }

    intent.putExtra(Intent.EXTRA_TITLE, actionTitle);

    // Grant read permission on the file to other apps without declared permission.
    int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
    intent.setFlags(flags);

    return intent;
}

Activité de notification sans interface utilisateur:

public class NotificationActivity extends Activity {
private final static Logger s_logger = LogUtil.getLogger(NotificationActivity.class);

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent intent = getIntent();

    // Cancel the notification that initiated this activity.
    // This is required when using the action buttons in expanded notifications.
    // While the default action automatically closes the notification, the
    // actions initiated by buttons do not.
    int notificationId = intent.getIntExtra(IIntentCode.INTENT_EXTRA_NOTIFICATION_ID, -1);
    if (notificationId != -1) {
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.cancel(notificationId);
    }

    // If there is an activity to handle the action, start the file action.
    if (DownloadedFileIntentUtils.verifyActivityIsAvailable(this, fileActionIntent, false)) {
            fileActionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            DownloadedFileIntentUtils.startFileActionActivity(this, fileActionIntent);
    }

    // Finish activity.
    finish();
}

public static void startFileActionActivity(Context context, Intent fileActionIntent) {
    // Start chooser intent.
    Intent chooser = Intent.createChooser(fileActionIntent, fileActionIntent.getStringExtra(Intent.EXTRA_TITLE));

    // Copy the flags from fileActionIntent to chooser intent.
    // FileActionExecutor must set FLAG_ACTIVITY_NEW_TASK on the intent passed to startActivity
    // because the flag is required when starting an activity from a context that is not an activity.
    chooser.addFlags(fileActionIntent.getFlags());

    context.startActivity(chooser);
}

N'oubliez pas d'ajouter NotificationActivity à AndroidManifest.xml. 

9
Vicki

Bien que j'apprécie beaucoup que la réponse de Soumyajyoti soit correcte ... ce n'est en fait pas ... 

j'utilise

Intent CR = new Intent(CRCODE); 
PendingIntent.getBroadcast(getApplicationContext(), MY_ID, CR, 0);

dans une disposition à distance pour une notification en cours ...

je peux vous assurer qu'il ne ferme pas le tiroir, mais déclenche l'intention et dessine l'activité derrière le tiroir ouvert, ainsi que l'exécution des autres tâches que j'ai assignées à mon récepteur ...

j'ai testé à la fois les méthodes getActivity et getService (qui ne fonctionneront pas dans mon cas, je dois activer plusieurs intentions onRecieve) et les deux ferment correctement le tiroir ...

Je sais que ce n'est pas une réponse, mais quand et si je le trouve, je ferai un rapport pour le modifier ...

pensée folle ... peut-être qu'une activité sans vue de contenu pourrait s'appeler un récepteur de diffusion qui déclencherait les intentions appropriées vers d'autres classes ou applications, selon les besoins ...

La pensée folle énumérée ci-dessus fonctionne ... commencez une activité avec PendingIntent.getActivity et utilisez-la pour relayer des émissions ou d'autres intentions, puis terminez vous-même ... l'effet n'est pas direct mais imperceptible pour l'utilisateur final

1
me_

essaye ça:

    NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(getApplicationContext().NOTIFICATION_SERVICE);
    Intent notificationIntent = new Intent(this.getBaseContext(), MainActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder mNotifyBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(
            getApplicationContext())
            .setTicker(getApplicationContext().getText(R.string.app_name))
            .setContentTitle(getApplicationContext().getText(R.string.app_name))
            .setContentText(getApplicationContext().getText(R.string.text))
            .setSmallIcon(R.drawable.smallicon)
            .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.ic_launcher))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .setVibrate(new long[]{150, 300});
    mNotifyBuilder.build().flags |= Notification.FLAG_AUTO_CANCEL;
    notificationManager.notify(1, mNotifyBuilder.build());
0

Le système Android réduit le tiroir de notification pour vous chaque fois que vous cliquez sur une notification et lancez une activité ou une diffusion. Je ne pense pas qu'il existe un moyen programmatique de fermer le tiroir de notification par votre code. Je vous suggère de vérifier les intentions que vous transmettez au constructeur de notifications et de vous assurer que les intentions de référence sont correctes. Je pense que quelque chose à l'intérieur du gestionnaire de notifications Android est bloqué en raison de l'intention que vous fournissez. Jusqu'ici, je n'ai pas vu le tiroir de notification rester ouvert une fois que l'action est déclenchée à partir de la notification. Juste curieux de savoir si votre activité cible est d'avoir une zone semi-transparente où l'activité précédente est visible, si c'est le cas, je vous suggère de rendre le fond complètement opaque (sans région transparente/semi-transparente). Peut-être empêche-t-il le lanceur domestique Android d’achever la séquence d’arrêt et empêche-t-il le lanceur de fermer le tiroir de notification pour vous. J'espère que j'ai pu vous aider. Bonne chance.

0
Soumyajyoti Saha