Android如何实现锁屏状态下弹窗

前言

想在锁屏上面实现弹窗,第一个想法就是利用 WindowManager 设置 Window 的 Flag,通过设置 Flag 的显示优先级来让窗口显示在锁屏的上面。

接下来就是试验可能相关的 Window Type 属性,验证该方案是否可行。

在尝试各个 Window Type 属性之前需要明确各个 Type 所需要的权限,下面是 com.android.internal.policy.impl.PhoneWindowManager.checkAddPermission 的源码:

public int checkAddPermission(WindowManager.LayoutParams attrs) { int type = attrs.type; if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) { return WindowManagerImpl.ADD_OKAY; } String permission = null; switch (type) { case TYPE_TOAST: // XXX right now the app process has complete control over // this... should introduce a token to let the system // monitor/control what they are doing. break; case TYPE_INPUT_METHOD: case TYPE_WALLPAPER: // The window manager will check these. break; case TYPE_PHONE: case TYPE_PRIORITY_PHONE: case TYPE_SYSTEM_ALERT: case TYPE_SYSTEM_ERROR: case TYPE_SYSTEM_OVERLAY: permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; break; default: permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; } if (permission != null) { if (mContext.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { return WindowManagerImpl.ADD_PERMISSION_DENIED; } } return WindowManagerImpl.ADD_OKAY; }

明显不适合的 Type:TYPE_TOAST, TYPE_INPUT_METHOD, TYPE_WALLPAPER; 可能适合的 Type:TYPE_PHONE, TYPE_PRIORITY_PHONE, TYPE_SYSTEM_ALERT, TYPE_SYSTEM_ERROR, TYPE_SYSTEM_OVERLAY; 其它类型的 Type:

需要系统签名权限:

android.Manifest.permission.INTERNAL_SYSTEM_WINDOW

而申请该权限需要系统签名,所以我们是无法获取权限的。

TYPE_PHONE

/** * Window type: phone. These are non-application windows providing * user interaction with the phone (in particular incoming calls). * These windows are normally placed above all applications, but behind * the status bar. * In multiuser systems shows on all users' windows. */ public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;

TYPE_PHONE 类型的窗口可以显示在其它 APP 的上面,但不能显示在锁屏的上面,所以 PASS。

TYPE_PRIORITY_PHONE

/** * Window type: priority phone UI, which needs to be displayed even if * the keyguard is active. These windows must not take input * focus, or they will interfere with the keyguard. * In multiuser systems shows on all users' windows. */ public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7;

TYPE_PRIORITY_PHONE 类型的窗口可以显示在其它 APP 的上面,但不能显示在锁屏的上面,所以 PASS。而且实际的行为和注释并不相符,该类型的窗口是可以获取交互事件的,具体原因待查。

TYPE_SYSTEM_ALERT

/** * Window type: system window, such as low power alert. These windows * are always on top of application windows. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;

TYPE_SYSTEM_ALERT 类型的窗口可以显示在其它 APP 的上面,但不能显示在锁屏的上面,所以 PASS。

TYPE_SYSTEM_OVERLAY

/** * Window type: system overlay windows, which need to be displayed * on top of everything else. These windows must not take input * focus, or they will interfere with the keyguard. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6;

TYPE_SYSTEM_OVERLAY 类型的窗口可以显示在所有其它窗口的上面,包括锁屏,而且不会影响它下面窗口的交互事件响应,但是该属性窗口不能获得焦点,无法进行交互(如果该窗口可以获取焦点,那么就可以用来抓取用户的锁屏密码,出于安全考虑,系统是不会允许的),所以只能用来简单的展示内容,如果需要交互的锁屏弹窗,那么该属性 PASS。

TYPE_SYSTEM_ERROR

/** * Window type: internal system error windows, appear on top of * everything they can. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10;

在原生 ROM 5.1 下试验是可以显示出来的,但根据注释来看(appear on top of everything they can)不是在所有情况下都可以显示在锁屏上面的,而且像 MIUI 和 Flyme 等 ROM 默认是屏蔽浮窗权限的,考虑到这点,利用 WindowManager 添加浮窗的方式实现锁屏弹窗的方案基本 PASS。

使用 Activity 的方式实现

首先需要对 Activity 进行如下设置

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Window win = getWindow(); win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); }

其中最主要也是必须要设置的就是:FLAG_SHOW_WHEN_LOCKED,顾名思义就是锁屏下显示该 Activity。而其它几个 Flag 包括:解锁、保持屏幕常亮、点亮屏幕可以根据具体的需求选择设置。

在 AndroidManifest.xml 中声明 Activity

同样该 Activity 也需要在 AndroidManifest.xml 中声明,声明时需注意添加 android:excludeFromRecents="true" 属性,是为了将该 Activity 从最近任务列表中去除,否则用户会觉得很奇怪。还有因为这个 Activity 会整个盖在锁屏上面,而且就算设置成背景透明,锁屏界面也不会显示在下面(系统主要是出于安全考虑),所以需要考虑下该 Activity 的背景,这里为了显示不要太突兀将主题设为壁纸。

<activity android:name=".LockScreenActivity" android:launchMode="singleInstance" android:excludeFromRecents="true" android:theme="@android:style/Theme.Wallpaper.NoTitleBar"/>

启动 Activity

由于该 Activity 是为了在锁屏的情况下显示的,所以启动 Activity 时不要忘了判断手机是否处于锁屏状态,可以通过下面这种方式判断锁屏状态:

KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); if (km.inKeyguardRestrictedInputMode()) { // 处于锁屏状态 }

总结

以上就是在Android中实现锁屏状态下弹窗效果的全部内容,希望本文的内容对大家开发Android的时候能有所帮助,如果有疑问欢迎大家留言讨论。

时间: 2024-10-22 05:05:44

Android如何实现锁屏状态下弹窗的相关文章

Android如何实现锁屏状态下弹窗_Android

前言 想在锁屏上面实现弹窗,第一个想法就是利用 WindowManager 设置 Window 的 Flag,通过设置 Flag 的显示优先级来让窗口显示在锁屏的上面. 接下来就是试验可能相关的 Window Type 属性,验证该方案是否可行. 在尝试各个 Window Type 属性之前需要明确各个 Type 所需要的权限,下面是 com.android.internal.policy.impl.PhoneWindowManager.checkAddPermission 的源码: publi

屏幕状态-android 锁屏状态下唤醒一个activity 无法让屏幕常亮

问题描述 android 锁屏状态下唤醒一个activity 无法让屏幕常亮 最近在做一个闹钟应用,系统收到闹钟的广播后,启动一个activity.关于锁屏状态和让屏幕常亮这一块出现了一些困惑,想请教各位前辈.先贴上图片 代码中设置了锁屏状态下可唤醒屏幕,并使屏幕常亮. 而测试的时候出现这样一个问题:如果当前手机并没有处于锁屏状态,此时activity被启动了,屏幕会保持常亮,(activity销毁,屏幕过了待机时间也会锁屏)这没有问题:但如果手机处于锁屏状态,广播收到了,也确实能唤醒屏幕,可是

Android Activity组件正常以及锁屏状态下的启动流程

前言: Activity是android的四大组件之一,它主要负责管理android应用程序的用户界面. 本文主要从framework的角度去分析activity的启动过程.activity的启动过程根据不同的情况会有一些差别,比如锁屏与非锁屏状态下的区别,activity依附的应用程序进程不存在与已经存在的区别等. 目录: 一.KK4.4从Launcher启动Activity的流程 二.应用内启动子Activity的流程 三.锁屏状态下Activity启动的流程 文章中含有大量的时序图,请直接

Windows 10在锁屏状态下打开某种应用程序的操作技巧

在Win10的锁屏界面,右下角有三个图标,中间有个像时钟的图标就是所谓的"轻松使用"按钮,里面有讲述人.放大镜.屏幕键盘等功能,这些功能我们可以修改成我们常用的应用程序,这样将大大的方便我们的操作,那么该如何修改呢? 默认情况下在锁屏界面点击右下角中间的图标会弹出"轻松使用"菜单 具体方法如下: 1.在Cortana搜索栏输入regedit,按回车键进入注册表编辑器; 2.定位到:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windo

iPhone锁屏状态下怎样挂断电话

在未锁屏状态下,iPhone来电可以通过点击红色的挂断按钮来挂断电话,但是锁屏状态下想要挂电话该怎么操作呢?这个问题其实难倒了不少苹果用户,其实方法很简单,小编来教大家一下. 如上所示在iphone5s及之前的版本电源都上上面,只要连续按两下就可以拒绝接电话了,但在iphone6及plus中在左边了,同样也是按二次挂断电话了,按一下是静音.

红米手机设置锁屏状态下可以拉出通知栏

1.红米手机默认状态下在手机锁屏状态下是无法接现通知栏的 2.现在我们来开始设置点击手机中"设置"按钮. 3.在此找到"通知栏设置",我们点击它进入,如下图所示. 4.在打开通知栏设置界面我们会看到有一个"下拉显示设置"如下图所示. 5.接着我们再点击"锁屏时显示"后面的"开启"按钮,我们把打开. 6.(设置后):按两下手机侧面的"电源键",使之处于锁屏状态,然后用手指肚向下再次滑动通知

5s ios7.1.2如何挂电话?苹果5s锁屏状态下拒接电话方法

在锁屏状态下来电应该怎么才能拒接呢?其实很简单,你只要 连续按两次电源键 就可以挂断电话. 友情提示 不管是以后iphone6还是ios8在锁屏状态下我们要拒接电脑都可以使用此方法来解决哦.

三星Galaxy S4锁屏状态下,如何取消 “心意合一”(9500)

击[应用程序]. 2.点击[设定]. 3.点击[我的设备],并点击[锁定屏幕]. 4.点击[锁屏小组件].   5.点击[时钟],然后点击[储存].   以上操作完成后,即可取消文字(心意合一)的显示.

锁屏状态接网络电话,Skype商务 iOS 版推重要功能更新

据外媒消息,微软今天宣布Skype商务iOS版有重大功能更新,将能在手机锁屏状态下接通Skype商务版电话.这受益于最新的iOS10版本,对第三方网络电话软件的功能优化带来的利好. Skype商务版的前身,为办公即时通讯软件Lync 2013.这一应用为大公司员工提供内部的交流,远程电话会议和视频会议等提供移动办公解决方案.Skype商务的iOS版在去年的早些时候上线. 类似的网络电话应用并不少,国外有Messenger.WhatsApp和监控软件TrueCaller.国内的主流社交软件QQ.微