Android屏幕锁屏d窗的正确姿势DEMO详解

Android屏幕锁屏d窗的正确姿势DEMO详解,第1张

概述在上篇文章给大家介绍了Android程序开发仿新版QQ锁屏下d窗功能。今天通过本文给大家分享android锁屏d窗的正确姿势。

在上篇文章给大家介绍了Android程序开发仿新版QQ锁屏下d窗功能。今天通过本文给大家分享androID锁屏d窗的正确姿势。

最近在做一个关于屏幕锁屏悬浮窗的功能,于是在网上搜索了很多安卓屏幕锁屏的相关资料,鉴于网上的资料比较零碎,所以我在这里进行整理总结。本文将从以下两点对屏幕锁屏进行解析:

1. 如何监听系统屏幕锁屏

2. 如何在锁屏界面d出悬浮窗

如何监听系统屏幕锁屏

经过总结,监听系统的锁屏可以通过以下两种方式:

1) 代码直接判定

2) 接收广播

1) 代码直接判定

代码判断方式,也有两种方法:

a) 通过PowerManager的isScreenOn方法,代码如下:

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);//如果为true,则表示屏幕“亮”了,否则屏幕“暗”了。boolean isScreenOn = pm.isScreenOn();

这里需要解释一下:

屏幕“亮”,表示有两种状态:a、未锁屏 b、目前正处于解锁状态 。这两种状态屏幕都是亮的;

屏幕“暗”,表示目前屏幕是黑的 。

b) 通过KeyguardManager的inKeyguardRestrictedinputMode方法,代码如下:

KeyguardManager mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEyguard_SERVICE);boolean flag = mKeyguardManager.inKeyguardRestrictedinputMode();

对flag进行一下说明,经过试验,总结为:

如果flag为true,表示有两种状态:a、屏幕是黑的 b、目前正处于锁屏状态 。

如果flag为false,表示目前未锁屏

注明:上面的两种方法,也可以通过反射机制来调用。

反射代码如下:

private static Method mReflectScreenState;try {mReflectScreenState = PowerManager.class.getmethod(isScreenOn,new Class[] {});PowerManager pm = (PowerManager) context.getSystemService(Activity.POWER_SERVICE);boolean isScreenOn= (Boolean) mReflectScreenState.invoke(pm);} catch (Exception e) {e.printstacktrace()}

2) 接收广播

当安卓系统锁屏或者屏幕亮起,或是屏幕解锁的时候,系统内部都会发送相应的广播,我们只需要对广播进行监听就可以了
注册广播的伪代码如下:

private ScreenbroadcastReceiver mScreenReceiver;private class ScreenbroadcastReceiver extends broadcastReceiver {private String action = null;@OverrIDepublic voID onReceive(Context context,Intent intent) {action = intent.getAction();if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁}}}private voID startScreenbroadcastReceiver() {IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_USER_PRESENT);context.registerReceiver(mScreenReceiver,filter);}

如何在锁屏界面d出悬浮窗

竟然知道了对于系统屏幕监听的方法,那么接下来就是要在屏幕锁屏的时候,d出悬浮框了,这个的实现方式有两种:

1) 使用WindowManager

2) 使用Activity

目前情况是,使用这两种方式在真机上都可以实现,如果网友们发现有问题,可以在博客中留言

1) 使用WindowManager

代码如下:

private voID init(Context mContext) {this.mContext = mContext;mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);// 更新浮动窗口位置参数 靠边displayMetrics dm = new displayMetrics();// 获取屏幕信息mWindowManager.getDefaultdisplay().getMetrics(dm);mScreenWIDth = dm.wIDthPixels;mScreenHeight = dm.heightPixels;this.mWmParams = new WindowManager.LayoutParams();// 设置window typeif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {mWmParams.type = WindowManager.LayoutParams.TYPE_TOAST;} else {mWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;}// 设置图片格式,效果为背景透明mWmParams.format = PixelFormat.RGBA_8888;// 设置浮动窗口不可聚焦(实现 *** 作除浮动窗口外的其他可见窗口的 *** 作)mWmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 调整悬浮窗显示的停靠位置为左侧置�?mWmParams.gravity = Gravity.left | Gravity.top;mScreenHeight = mWindowManager.getDefaultdisplay().getHeight();// 以屏幕左上角为原点,设置x、y初始值,相对于gravitymWmParams.x = 0;mWmParams.y = mScreenHeight / 2;// 设置悬浮窗口长宽数据mWmParams.wIDth = LayoutParams.WRAP_CONTENT;mWmParams.height = LayoutParams.WRAP_CONTENT;addVIEw(createVIEw(mContext));mWindowManager.addVIEw(this,mWmParams);mTimer = new Timer();hIDe();}

WindowManager的主要配置就是上面的那些代码,这里需要说明一下,type的类型有如下值:

应用程序窗口。public static final int FirsT_APPliCATION_WINDOW = 1; 所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。 public static final int TYPE_BASE_APPliCATION =1;普通应用功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。public static final int TYPE_APPliCATION = 2;用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。它用于让系统显示些信息,直到应用程序可以开启自己的窗口。 public static final int TYPE_APPliCATION_STARTING = 3; 应用程序窗口结束。public static final int LAST_APPliCATION_WINDOW = 99;子窗口。子窗口的Z序和坐标空间都依赖于他们的宿主窗口。public static final int FirsT_SUB_WINDOW = 1000;面板窗口,显示于宿主窗口上层。public static final int TYPE_APPliCATION_PANEL = FirsT_SUB_WINDOW;媒体窗口,例如视频。显示于宿主窗口下层。public static final int TYPE_APPliCATION_MEDIA = FirsT_SUB_WINDOW+1;应用程序窗口的子面板。显示于所有面板窗口的上层。(GUI的一般规律,越“子”越靠上)public static final int TYPE_APPliCATION_SUB_PANEL = FirsT_SUB_WINDOW +2;对话框。类似于面板窗口,绘制类似于顶层窗口,而不是宿主的子窗口。public static final int TYPE_APPliCATION_ATTACHED_DIALOG = FirsT_SUB_WINDOW +3;媒体信息。显示在媒体层和程序窗口之间,需要实现透明(半透明)效果。(例如显示字幕)public static final int TYPE_APPliCATION_MEDIA_OVERLAY = FirsT_SUB_WINDOW +4;子窗口结束。( End of types of sub-windows )public static final int LAST_SUB_WINDOW = 1999;系统窗口。非应用程序创建。public static final int FirsT_SYstem_WINDOW = 2000;状态栏。只能有一个状态栏;它位于屏幕顶端,其他窗口都位于它下方。public static final int TYPE_STATUS_bar = FirsT_SYstem_WINDOW;搜索栏。只能有一个搜索栏;它位于屏幕上方。public static final int TYPE_SEARCH_bar = FirsT_SYstem_WINDOW+1;电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。public static final int TYPE_PHONE = FirsT_SYstem_WINDOW+2;系统提示。它总是出现在应用程序窗口之上。public static final int TYPE_SYstem_ALERT = FirsT_SYstem_WINDOW +3;锁屏窗口。public static final int TYPE_KEyguard = FirsT_SYstem_WINDOW +4;信息窗口。用于显示toast。public static final int TYPE_TOAST = FirsT_SYstem_WINDOW +5;系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。public static final int TYPE_SYstem_OVERLAY = FirsT_SYstem_WINDOW +6;电话优先,当锁屏时显示。此窗口不能获得输入焦点,否则影响锁屏。public static final int TYPE_PRIORITY_PHONE = FirsT_SYstem_WINDOW +7;系统对话框。(例如音量调节框)。public static final int TYPE_SYstem_DIALOG = FirsT_SYstem_WINDOW +8;锁屏时显示的对话框。public static final int TYPE_KEyguard_DIALOG = FirsT_SYstem_WINDOW +9;系统内部错误提示,显示于所有内容之上。public static final int TYPE_SYstem_ERROR = FirsT_SYstem_WINDOW +10;内部输入法窗口,显示于普通UI之上。应用程序可重新布局以免被此窗口覆盖。public static final int TYPE_input_METHOD = FirsT_SYstem_WINDOW +11;内部输入法对话框,显示于当前输入法窗口之上。public static final int TYPE_input_METHOD_DIALOG= FirsT_SYstem_WINDOW +12;墙纸窗口。public static final int TYPE_WALLPAPER = FirsT_SYstem_WINDOW +13;状态栏的滑动面板。public static final int TYPE_STATUS_bar_PANEL = FirsT_SYstem_WINDOW +14;系统窗口结束。public static final int LAST_SYstem_WINDOW = 2999;

如果想让悬浮窗在所以锁屏之上,使用TYPE_SYstem_ERROR,因为它显示在所有内容之上。

2) 使用Activity

Activity的设置

Activity需要进行以下设置,才可以在锁屏状态下d窗。
首先是onCreate方法,需要添加4个标志,如下:

protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Window win = ge@R_403_5790@ow(); 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); // 自己的代码 } 

四个标志位顾名思义,分别是锁屏状态下显示,解锁,保持屏幕长亮,打开屏幕。这样当Activity启动的时候,它会解锁并亮屏显示。
然后在AndroIDManifest.xml文件当中,对该activity的声明需要加上以下属性:

<activity androID:name=".alarm.AlarmHandlerActivity" androID:launchMode="singleInstance" androID:excludeFromrecents="true" androID:taskAffinity="" androID:theme="@androID:style/theme.Wallpaper.NoTitlebar"/> 

而对于布局文件,要显示的vIEw居中,背景透明。由于上面已经设置了背景为壁纸的背景,所以显示的是桌面的背景。如果背景设为默认的白色,则导致d窗后面是一片白色,看起来很丑。如果背景设置为透明,则d窗后面会显示出解锁后的界面(即使有锁屏密码,也是会显示解锁后的界面的),一样很影响视觉效果。

在广播中启动锁屏d窗

我们设置的是锁屏下才d窗的,非锁屏下就不适合d出这个窗口了(你可以试一下,效果会很怪)。一般是注册一个广播接收器,在接收到指定广播之后判断是否需要d窗,所以在broadcastReceiver的接收代码中需要先判断是否为锁屏状态下:

@OverrIDe public voID onReceive(Context context,Intent intent) { Log.d(LOG_TAG,intent.getAction()); KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEyguard_SERVICE); if (km.inKeyguardRestrictedinputMode()) { Intent alarmIntent = new Intent(context,AlarmActivity.class); alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(alarmIntent); } } 

这里用到的是KeyguardManager类,用来管理锁屏的,4.1之后该类的API新增了一个iskeyguardlocked()的方法判断是否锁屏,但在4.1之前,我们只能用inKeyguardRestrictedinputMode()方法,如果为true,即为锁屏状态。需要注意的是,在广播中启动Activity的context可能不是Activity对象,所以需要添加NEW_TASK的标志,否则启动时可能会报错。我们就可以结合之前的系统发送广播后进行相应的悬浮窗的d出处理。

复写onNewIntent方法

再次亮起屏幕,如果该Activity并未退出,但是被手动按了锁屏键,当前面的广播接收器再次去启动它的时候,屏幕并不会被唤起,所以我们需要在activity当中添加唤醒屏幕的代码,这里用的是电源锁。可以添加在onNewIntent(Intent intent),因为它会被调用。也可以添加在其他合适的生命周期方法。添加代码如下:

PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE); if (!pm.isScreenOn()) { PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK,"bright"); wl.acquire(); wl.release(); } 

最后,是添加如下权限

<uses-permission androID:name="androID.permission.disABLE_KEyguard"/> <uses-permission androID:name="androID.permission.WAKE_LOCK"/> 

第一条是解锁屏幕需要的,第二条是申请电源锁需要的。

以上所说是小编给大家介绍的AndroID屏幕锁屏d窗的正确姿势DEMO详解,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的,在此也非常感谢大家对编程小技巧网站的支持!

总结

以上是内存溢出为你收集整理的Android屏幕锁屏d窗的正确姿势DEMO详解全部内容,希望文章能够帮你解决Android屏幕锁屏d窗的正确姿势DEMO详解所遇到的程序开发问题。

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1148281.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存