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

TL; DR

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

Детали

Цель

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

Положение дел

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

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

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

Код

Это код, в котором я начинаю уведомление (это живет в 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 экране блокировки, поэтому я изменил его на setContentIntent вы видите выше. Результат тот же, хотя для меня нет действий 🙁

Solutions Collecting From Web of "Как выполнить уведомление-действие (щелчок) на заблокированном экране?"

Попробуйте использовать 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

Трюк, похоже,

  1. Использовать сервис
  2. Добавьте намерение не как действие или 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); 

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

Трюк, похоже,

  1. Использовать сервис
  2. Добавьте намерение не как действие или contentIntent, а с RemoteViews метода 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); 

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

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

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