Comment effectuer une action de notification (clic) sur l'écran de verrouillage?

TL; DR

Comment puis-je faire une notification qui fonctionne à partir de l'écran de verrouillage sans déverrouiller? Après avoir cliqué sur une action, un bouton sur la notification ou juste la notification complète, je veux faire un appel API (sans taper mon code de déverrouillage)

Détails

Objectif

Basé sur la réponse sur cette question j'ai essayé de faire une notification avec une action qui fonctionne sur le lockscreen sans déverrouiller l'appareil. L'action est quelque chose qui n'a pas besoin d'une autre interface ou interaction (pensez à "envoyer une demande D'API").

Statut

La notification et cliquez sur faire fonctionner avec un périphérique déverrouillé. Cependant, lorsqu'il est verrouillé, je dois toujours entrer le code de déverrouillage en premier, donc soit il y a quelque chose de nouveau, soit je viens de mal comprendre la façon dont il est censé fonctionner.

Si je comprends bien, je peux définir ma visibilité sur 'public' pour afficher le contenu (cela fonctionne), et au lieu de définir une action (ce qui ne semble pas être public) je peux gérer les clics sur la mise en page (maintenant visible). J'ai essayé ceci avec le code ci-dessous, mais évidemment cela ne fonctionne pas.

J'ai essayé à la fois d'envoyer l'intention à mon application et à un service, comme florian l'a suggéré ci-dessous.

Code

C'est le code où je commence la notification (cela vit dans une activité, le code a été raccourci pour votre commodité)

private void startNotification() {

    NotificationCompat.Builder builder = 
            new NotificationCompat.Builder(this)
            .setVisibility(Notification.VISIBILITY_PUBLIC)
            .setOngoing(true)
            .setSmallIcon(R.drawable.abc_ic_menu_share_mtrl_alpha)
            .setContentTitle("title text")
            .setContentText("content text");

    Intent openIntent = new Intent(MyMainActivity.this, MyMainActivity.class);
    openIntent.setAction("some_string");
    PendingIntent pOpenIntent = PendingIntent.getActivity(this, 0, openIntent, 0);
    builder.setContentIntent(pOpenIntent);

    RemoteViews view = new RemoteViews(getPackageName(), R.layout.notification);
    builder.setContent(view);

    NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    mNotificationManager.notify(id, builder.build());

}

Comme dit, j'ai aussi essayé avec le service comme Florian l'a suggéré, avec ceci comme un appel:

    Intent yepIntent = new Intent(this, MyIntentService.class);
    yepIntent.setAction("test");
    yepIntent.putExtra("foo", true);
    yepIntent.putExtra("bar", "more info");
    PendingIntent yepPendingIntent = PendingIntent.getService(this, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    //builder.addAction(R.drawable.abc_ic_menu_share_mtrl_alpha, "My Action", yepPendingIntent);
    builder.setContentIntent(yepPendingIntent);

L'action ne s'est pas montré sur l'écran de verrouillage, donc je l'ai changé pour le setContentIntent que vous voyez ci-dessus. Le résultat est le même, pas d'action pour moi: (

24
demandé sur Community 2015-11-15 23:20:48

3 réponses

Essayez d'utiliser un IntentService. Remplacez votre cible d'intention par votre service d'intention:

    Intent yepIntent = new Intent(context, MyIntentService.class);
    yepIntent.putExtra("foo", true);
    yepIntent.putExtra("bar", "more info");
    PendingIntent yepPendingIntent = PendingIntent.getService(context, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    notificationBuilder.addAction(R.drawable.icon_of_choice, "My Action", yepPendingIntent);

Enregistrez votre service dans le Manifeste:

  <service
        android:name="app.great.mypackage.MyIntentService"
        android:exported="false"/>

Votre Service pourrait ressembler à ceci:

public class MyIntentSerice extends IntentService {
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("myapp", "I got this awesome intent and will now do stuff in the background!");
        // .... do what you like
    }
}

Mise à jour avec les commentaires de Nanne

L'astuce semble être de

  1. utiliser un service
  2. ajoutez l'intention non pas comme une action ou un contentIntent, mais avec la méthode RemoteViews.

Combiné ce sera:

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
        .setVisibility(Notification.VISIBILITY_PUBLIC)
        .setOngoing(true)
        .setSmallIcon(R.drawable.abc_ic_menu_share_mtrl_alpha)
        .setContentTitle("My notification")
        .setContentText("Hello World!");

int notificationId = 1;
Intent yepIntent = new Intent(this, MyIntentService.class);
yepIntent.setAction("test");
yepIntent.putExtra("foo", true);
yepIntent.putExtra("bar", "more info");
PendingIntent yepPendingIntent = PendingIntent.getService(this, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);

// doesn't show up on my lock-screen
//builder.addAction(R.drawable.abc_ic_menu_share_mtrl_alpha, "My Action", yepPendingIntent);

// asks for unlock code for some reason
//builder.setContentIntent(yepPendingIntent);

// Bingo
RemoteViews view = new RemoteViews(getPackageName(), R.layout.notification);
view.setOnClickPendingIntent(R.id.notification_closebtn_ib, yepPendingIntent);
builder.setContent(view);
15
répondu Florian Barth 2015-11-19 12:17:35

Combinant la réponse de la question que j'ai liée (Bouton D'action de Notification non cliquable dans l'écran de verrouillage) et celui que @ florian_barth a donné ci-dessus, je l'ai fait fonctionner

L'astuce semble être de

  1. Utiliser un service
  2. ajoutez l'intention non pas comme une action ou un contentIntent, mais avec la méthode RemoteViews.

Combiné ce sera:

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
            .setVisibility(Notification.VISIBILITY_PUBLIC)
            .setOngoing(true)
            .setSmallIcon(R.drawable.abc_ic_menu_share_mtrl_alpha)
            .setContentTitle("My notification")
            .setContentText("Hello World!");

    int notificationId = 1;
    Intent yepIntent = new Intent(this, MyIntentService.class);
    yepIntent.setAction("test");
    yepIntent.putExtra("foo", true);
    yepIntent.putExtra("bar", "more info");
    PendingIntent yepPendingIntent = PendingIntent.getService(this, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);

    // doesn't show up on my lock-screen
    //builder.addAction(R.drawable.abc_ic_menu_share_mtrl_alpha, "My Action", yepPendingIntent);

    // asks for unlock code for some reason
    //builder.setContentIntent(yepPendingIntent);

    // Bingo
    RemoteViews view = new RemoteViews(getPackageName(), R.layout.notification);
    view.setOnClickPendingIntent(R.id.notification_closebtn_ib, yepPendingIntent);
    builder.setContent(view);
4
répondu Nanne 2017-05-23 12:09:24

Il fonctionne également avec Broadcast receiver et setAction

PendingIntent pendingIntent = PendingIntent.getBroadcast(..
builder.addAction(..
   .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

Sur l'écran de verrouillage, balayez la notification vers le bas pour la développer et appuyez sur la zone d'action pour appeler le récepteur de diffusion sans déverrouiller le téléphone.

1
répondu farid_z 2016-11-04 15:18:00