如何在锁定屏幕上执行通知操作(点击)?
Posted
技术标签:
【中文标题】如何在锁定屏幕上执行通知操作(点击)?【英文标题】:How to perform notification-action (click) on lock-screen? 【发布时间】:2016-02-16 21:55:00 【问题描述】:TL;DR
如何在不解锁的情况下从锁定屏幕发出通知?在单击一个操作、通知上的按钮或只是完整的通知后,我想做一个 API 调用(无需输入我的解锁代码)
详情
目标
根据this question 上的回答,我尝试使用在锁定屏幕上有效的操作发出通知,而无需解锁设备。该操作不需要任何进一步的接口或交互(想想“发送 API 请求”)。
状态
通知和点击确实适用于未锁定的设备。但是,当被锁定时,我仍然需要先输入解锁码,所以要么有新的事情发生,要么我只是误解了它应该工作的方式。
如果我理解正确,我可以将我的可见性设置为“公开”以显示内容(这可行),而不是定义一个动作(这似乎不公开)我可以处理点击(现在可见) 布局。我用下面的代码试过了,但显然它不起作用。
我已尝试将意图发送到我的应用和服务,如下 florian 建议的那样。
代码
这是我开始通知的代码(它存在于 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());
如前所述,我还尝试了 florian 建议的服务,并以此作为调用:
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
。结果是一样的,对我来说没有任何动作:(
【问题讨论】:
您是否打算在点击通知时禁用锁定功能? 不,我只是想执行一些代码,在这种情况下是一个 API 调用 这是一个安全漏洞。如果您在被锁定时访问该应用程序,则属于违规行为。就问题而言,您可以禁用键盘保护,但不建议这样做 不,不是,这是为了执行某项操作而刻意设置的。您可以在锁定时执行一些非安全操作,例如将播放器设置为暂停、拍照,如果您设置了我的应用程序,您可以打开灯(如果您已设置应用程序来执行此操作)。请不要随意将事情称为“安全漏洞”。 【参考方案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);
在 Manifest 中注册您的服务:
<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 的反馈
诀窍似乎是
-
使用服务
不是将意图添加为操作或 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);
【讨论】:
在这种情况下,intent 被注册为通知中的操作,为了将其用作内容意图,只需使用您在原始代码中使用的 NotificationBuilder 操作。 但作为对问题的回答:您是说是的,服务可以在活动没有的地方工作? 是的,我猜活动是“链接”到 UI 和交互,为此您需要解锁屏幕。将上面的 sn-ps 放入您的代码中,让我们找出答案:) 我会的!这可能需要我几个小时,因为从事私人项目并不是真正的日常工作;) 非常真实,期待结果:)【参考方案2】:结合我链接的问题的答案 (Notification action button not clickable in lock screen) 和上面给出的@florian_barth 的答案,我得到了它的工作
诀窍似乎是
-
使用服务
不是将意图添加为操作或内容意图,而是使用
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)
在锁定屏幕上向下滑动通知以将其展开,然后点击操作区域以调用广播接收器而无需解锁手机。
【讨论】:
以上是关于如何在锁定屏幕上执行通知操作(点击)?的主要内容,如果未能解决你的问题,请参考以下文章