Android   发布时间:2022-04-28  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了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;
}

明显不适合的 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中实现锁屏状态下弹窗效果的全部内容,希望本文的内容对大家开发Android的时候能有所帮助,如果有疑问欢迎大家留言讨论。

大佬总结

以上是大佬教程为你收集整理的Android如何实现锁屏状态下弹窗全部内容,希望文章能够帮你解决Android如何实现锁屏状态下弹窗所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。