前言
想在锁屏上面实现d窗,第一个想法就是利用 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
类型的窗口可以显示在所有其它窗口的上面,包括锁屏,而且不会影响它下面窗口的交互事件响应,但是该属性窗口不能获得焦点,无法进行交互(如果该窗口可以获取焦点,那么就可以用来抓取用户的锁屏密码,出于安全考虑,系统是不会允许的),所以只能用来简单的展示内容,如果需要交互的锁屏d窗,那么该属性 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
添加浮窗的方式实现锁屏d窗的方案基本 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中实现锁屏状态下d窗效果的全部内容,希望本文的内容对大家开发AndroID的时候能有所帮助,如果有疑问欢迎大家留言讨论。
总结以上是内存溢出为你收集整理的Android如何实现锁屏状态下d窗全部内容,希望文章能够帮你解决Android如何实现锁屏状态下d窗所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)