尝试利用 WindowManager 添加浮窗的方式实现

想在锁屏上面实现弹窗,第一个想法就是利用 WindowManager 设置 WindowFlag,通过设置 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;
}

明显不适合的 TypeTYPE_TOAST, TYPE_INPUT_METHOD, TYPE_WALLPAPER; 可能适合的 TypeTYPE_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 开发之锁屏弹窗的更多相关文章

  1. Android简易实战教程--第五话《开发一键锁屏应用》

    转载请注明出处:http://blog.csdn.net/qq_32059827/article/details/51860900 点击打开链接 Device Administration 对于这个应 ...

  2. Android4.0+锁屏程序开发——设置锁屏页面篇

    [如何开发一个锁屏应用] 想要开发一个锁屏应用,似乎很难,其实并没有想象中那么难. 从本质上来说,锁屏界面也只是一个Activity而已,只是这个界面比较特殊,在我们点亮屏幕的时候,这个界面就会出现. ...

  3. Android端恶意锁屏勒索应用分析

    一.前言 5月12日,一场全球性互联网灾难悄然而至,一款名为WannaCRY的PC端恶意勒索软件利用NSA泄漏的危险漏洞“永恒之蓝”,给100多个国家和地区10万台电脑造成了巨大的损失.到2017年为 ...

  4. 【Android】Android 手机忘记锁屏密码的解决办法

    对于忘记Android锁屏密码的筒子们,除重新刷包或者wipe data外,还可用adb来删除密码: 方法很简单 1.手机连接电脑,不要打开数据连接,在充电模式下进行. 2.在电脑上,解压adb.zi ...

  5. android开发:全屏和退出全屏

    android开发:全屏和退出全屏 from://http://blog.csdn.net/dyllove98/article/details/8831933 2013-04-21 20:31 413 ...

  6. Android简易实战教程--第六话《开发一键锁屏应用2·完成》

    转载请注明出处:http://blog.csdn.net/qq_32059827/article/details/51885687点击打开链接 上一篇,初步开发了这个应用,功能都有了(见http:// ...

  7. Android LockScreen (锁屏弹窗)

    在要弹窗的Activity需要进行以下设置,才可以在锁屏状态下弹窗 @Override protected void onCreate(Bundle savedInstanceState) { fin ...

  8. Android平台一些流行的使用3D技术开发的锁屏

    题外话:从2007年android系统的发布开始,到2008年的第一款手机问世,再到现在击败塞班,wm,黑霉,然后遍地开花,2013年,智能机出货超过了功能机,android功不可没.一路走来,虽然a ...

  9. Android 监听锁屏、解锁、开屏 操作

    1.首先定义 ScreenListener  package com.app.lib; import android.content.BroadcastReceiver; import android ...

随机推荐

  1. Go 编码问题的解决方案

    1.首先需要mahonia 这个包 go get github.com/axgle/mahonia 然后新建一个 func src 字符串 srcCode 字符串当前编码 tagCode 要转换的编码 ...

  2. MVC:一个View显示多个Model(多个Model你可以使用ViewBag或ViewData , 或者:Model["myInfo"] as)

    MVC:一个View显示多个Model 多个Model你可以使用ViewBag或ViewData , 或者:Model["myInfo"] as. 比如: Tuple<str ...

  3. 原生ajax实现方式

    http://www.cnblogs.com/rubylouvre/archive/2013/01/08/2851051.html <!DOCTYPE html> <html lan ...

  4. c# 引用ConfigurationManager 类

    c#添加了Configuration;后,竟然找不到 ConfigurationManager 这个类,后来才发现:虽然引用了using System.Configuration;这个包,但是还是不行 ...

  5. 【Redis哨兵集群】

    目录 开始配置主从复制 开始配置Redis Sentinel @ *** 在开始之前,我们先来看看Redis的主从复制 主从复制原理: 从服务器向主服务器发送SYNC命令. 主服务器接到SYNC命令后 ...

  6. Es61

    ECMAScript和JavaScript的关系 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了.Mozilla公司将在这个标准的基础 ...

  7. Scott Hanselman的问题-3

    .Net程序员面试 中级篇 (回答Scott Hanselman的问题)   继<.Net 程序员面试 C# 语言篇 (回答Scott Hanselman的问题)>跟<.Net程序员 ...

  8. 谈谈iframe的优缺点

    iframe是一种框架,也是一种很常见的网页嵌入方式,零度今天给大家分析分析它的优缺点. iframe的优点: 1.iframe能够原封不动的把嵌入的网页展现出来. 2.如果有多个网页引用iframe ...

  9. 项目融入mongoDB

    1.pom.xml导入jar包           <!-- mongoDB -->         <dependency>           <groupId> ...

  10. Looksery Cup 2015 Editorial

    下面是题解,做的不好.下一步的目标是rating涨到 1800,没打过几次cf A. Face Detection Author: Monyura One should iterate through ...