Подтвердить что ты не робот

Как выполнить уведомление-действие (щелчок) на экране блокировки?

TL; DR

Как я могу сделать уведомление, которое выполняет некоторую работу с блокировки без разблокировки? После нажатия на действие, кнопку уведомления или только полное уведомление, я хочу выполнить вызов API (без ввода кода разблокировки)

Подробнее

Цель

Основываясь на ответе на этот вопрос, я попытался сделать уведомление с действием, которое работает на lockscreen без разблокировки устройства. Действие - это то, что не требует никакого дополнительного интерфейса или взаимодействия (подумайте "отправьте запрос API" ).

Состояние

Уведомление и щелчок работают с разблокированным устройством. Однако, когда я заблокирован, мне все равно нужно сначала ввести код разблокировки, так что либо происходит что-то новое, либо я просто неправильно понял, как он должен работать.

Если я правильно понимаю, я могу установить видимость для публики, чтобы показать содержимое (это работает), и вместо определения действия (которое, похоже, не является общедоступным) я могу обрабатывать клики на (теперь видимом ) макет. Я попробовал это с приведенным ниже кодом, но, очевидно, он не работает.

Я попробовал как отправить намерение своему приложению, так и службе, как показано ниже.

код

Это код, в котором я начинаю уведомление (это живет в Activity, код был сокращен для вашего удобства)

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());

}

Как уже было сказано, я также пробовал использовать эту услугу, как предложил флориан, причем это как звонок:

    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);

Действие не появилось на экране блокировки, поэтому я изменил его на setContentIntent, который вы видите выше. Результат тот же, хотя для меня нет действий: (

4b9b3361

Ответ 1

Попробуйте использовать IntentService. Замените целевую цель своим сервисом:

    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);

Зарегистрируйте свою службу в манифесте:

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

Ваша служба может выглядеть так:

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
    }
}

ОБНОВЛЕНИЕ с отзывами от Nanne

Кажется, что трюк должен быть

  • Использовать службу
  • Добавьте намерение не как действие или контент, а метод RemoteViews.

В сочетании это будет:

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);

Ответ 2

Объединив ответ с вопросом, который я связал (кнопка действия уведомления, не щелкнув по экрану блокировки), а один @florian_barth дал выше, я получил его работу

Кажется, что трюк должен быть

  • Использовать службу
  • Добавить намерение не как действие или contentIntent, а с помощью метода RemoteViews.

В сочетании это будет:

    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);

Ответ 3

Он также работает с широковещательным приемником и setAction

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

На экране блокировки проведите пальцем по уведомлению, чтобы развернуть его, и коснитесь области действия, чтобы вызвать широковещательный приемник, не отпирая телефон.