android 锁屏界面处理
锁屏相关的文件在android对应package:com.android.internal.policy.impl。
phoneWindowManager.java可以派发各种物理key,如Power,Home,Vol+和Vol-等等。那么,这个类是由谁启动的?
在package下Policy.java中
public PhoneWindowManager makeNewWindowManager() {
return new PhoneWindowManager();
}
这个方法实现创建这个类。而在PolicyManager.java下调用这个方法实现对PhoneWindowManager的创建。
但是,PhoneWindowManager.java中有一个init()方法,这个是这个类的初始化方法,它调用PowerManager、windowManager、KeyguardViewMediator等等实现对PhoneWindowManager。这个Init()是在WindowManagerService.java下 的PolicyThread类下得Run方法中调用mPolicy.init(mContext, mService, mPM)。
PhoneWindowManager.java这个类是非常重要的,这里注册了一个Orientation变化的监听类:
MyOrientationListener extends WindowOrientationListener,但是,它不能够自动进行更新,它的更新主要是依据接收广播进行的,此处大概就是JNI根据驱动获取相关Sensor消息然后发送消息。这里仅仅粗略说明在这个文件中有屏幕旋转的处理方法。
下面是锁屏的处理流程:
在PhoneWindowManager.java中:
public void systemReady() {
// tell the keyguard
mKeyguardMediator.onSystemReady();
android.os.SystemProperties.set("dev.bootcomplete", "1");
synchronized (mLock) {
updateOrientationListenerLp();
mSystemReady = true;
mHandler.post(new Runnable() {
public void run() {
updateSettings();
}
});
}
}
这个方法在开机时启动调用,然后mKeyguardMediator.onSystemReady()
在KeyGuardViewMeditor.java是一个非常重要的类,它用来响应电源键的处理(黑亮屏),查询解锁屏等等。
public void onSystemReady() {
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
mSystemReady = true; //系统准备好了
doKeyguard(); //判断是否设定了锁
}
}
private void doKeyguard()主要功能:Enable the keyguard if the settings are appropriate.意思就是如果在Setting里面设置了密码就激活keyguard。
1.如果设置了屏幕锁,黑屏后,在onScreenTurnedOff中doKeyguard()调用一次;
2.如果有SIM卡,且设置了PIN或PUK锁,那么调用doKeyguard();
3.TIMEROUT时调用doKeyguard();
4.接收到消息;DELAYED_KEYGUARD_ACTION或者TelephonyManager.ACTION_PHONE_STATE_CHANGED可能会调用
doKeyguard().
doKeyguard()方法最后调用了showLocked();
private void showLocked() {
if (DEBUG) Log.d(TAG, "showLocked");
// ensure we stay awake until we are finished displaying the keyguard
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW);
mHandler.sendMessage(msg);
}
实际上就是发送消息显示SHOW
当Handler接收到SHOW这个Message时,进行相关处理:
进入KeyguardViewManager.java:
在public synchronized void show()方法中:
if (mKeyguardView == null) {
if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
mKeyguardView.setId(R.id.lock_screen);
……
}
mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this)这个就是KeyguardViewBase创建一个KeyguardViewBase的对象,也就是管理Lock、Unlock画面的类实例。
在Setting里面设置各种锁屏之后,在按power键重新开启时会产生lock或者unlock界面,需要输入密码或者绘出Pattern等操作后才能进入界面。这个锁定和解锁界面是由LockPatternKeyguardView这个类实现的。下面便是这个class的构造函数。
public LockPatternKeyguardView(
Context context,
KeyguardUpdateMonitor updateMonitor,
LockPatternUtils lockPatternUtils,
KeyguardWindowController controller)
重要实现:
mConfiguration = context.getResources().getConfiguration();
这个函数是用来获取系统的一些配置,在此用来决定是横屏还是竖屏。
mMode = getInitialMode();
这个则是获取系统的mode了。
mMode是这样的类型:
enum Mode {
LockScreen,
UnlockScreen
}
可以初步判断是lock还是unlock状态的flag枚举。获取这个状态是非常重要的,它决定初始化时究竟是显示unlock 界面还是lock界面。
private Mode getInitialMode() {
boolean isPukRequired = false;
for (int i = 0; i < TelephonyManager.getPhoneCount(); i++) {
isPukRequired = isPukRequired || isSimPukLocked(i);
if (isPukRequired) break;
}
//这里是判断sim是否加入PUK锁或者sim卡不存在
if (stuckOnLockScreenBecauseSimMissing() || isPukRequired) {
return Mode.LockScreen;
} else {
// Show LockScreen first for any screen other than Pattern unlock.
final boolean usingLockPattern =
mLockPatternUtils.getKeyguardStoredPasswordQuality()== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
if (isSecure() && usingLockPattern) {
return Mode.UnlockScreen;
} else {
return Mode.LockScreen;
}
}
}
对于isSecure这个函数,定义如下:
private boolean isSecure() {
UnlockMode unlockMode = getUnlockMode();
boolean secure = false;
switch (unlockMode) {
case Pattern:
secure = mLockPatternUtils.isLockPatternEnabled();
break;
case SimPin:
for (int i = 0; i < TelephonyManager.getPhoneCount(); i++) {
// Check if subscription is PIN/PUK locked.
// isPinLocked returns true if the state is PIN_REQUIRED/PUK_REQUIRED.
secure = secure || getSimState(i).isPinLocked();
if (secure) break;
}
break;
case Account:
secure = true;
break;
case Password:
secure = mLockPatternUtils.isLockPasswordEnabled();
break;
default:
throw new IllegalStateException("unknown unlock mode " + unlockMode);
}
return secure;
很显然是判断,是否设置了解锁屏方式。是则返回true,否则false。
而usingLockPattern是判断是否是用pattern模式的。具体判断后面研究。
在获取相关初始状态后,就是一些回调函数的实现:
mKeyguardScreenCallback = new KeyguardScreenCallback(),这个是十分容易解决的。
在之后是:
// create both the lock and unlock screen so they are quickly available
// when the screen turns on
mLockScreen = createLockScreen();
addView(mLockScreen);
final UnlockMode unlockMode = getUnlockMode();
if (DEBUG) Log.d(TAG,
"LockPatternKeyguardView ctor: about to createUnlockScreenFor; mEnableFallback="
+ mEnableFallback);
mUnlockScreen = createUnlockScreenFor(unlockMode);
mUnlockScreenMode = unlockMode;
maybeEnableFallback(context);
addView(mUnlockScreen);
updateScreen(mMode);
由注释可知:其实就是创建lock和unlock界面,这样切换时就可以直接显示而不必先创建在切换,造成时间的缓冲。那么究竟显示lock还是unlock界面就是最后那个调用。具体函数:
private void updateScreen(final Mode mode) {
if (DEBUG_CONFIGURATION) Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode
+ " last mode=" + mMode, new RuntimeException());
mMode = mode;
// Re-create the unlock screen if necessary. This is primarily required to properly handle
// SIM state changes. This typically happens when this method is called by reset()
if ((mode == Mode.UnlockScreen && mCurrentUnlockMode != getUnlockMode()) ||
(getUnlockMode() == UnlockMode.SimPin)) {
recreateUnlockScreen();
}
final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
// do this before changing visibility so focus isn't requested before the input
// flag is set
mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput());
if (DEBUG_CONFIGURATION) {
Log.v(TAG, "Gone=" + goneScreen);
Log.v(TAG, "Visible=" + visibleScreen);
}
if (mScreenOn) {
if (goneScreen.getVisibility() == View.VISIBLE) {
((KeyguardScreen) goneScreen).onPause();
}
if (visibleScreen.getVisibility() != View.VISIBLE) {
((KeyguardScreen) visibleScreen).onResume();
}
}
goneScreen.setVisibility(View.GONE);
visibleScreen.setVisibility(View.VISIBLE);
requestLayout();
if (!visibleScreen.requestFocus()) {
throw new IllegalStateException("keyguard screen must be able to take "
+ "focus when shown " + visibleScreen.getClass().getCanonicalName());
}
}
这里mMode = mode;之后
final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
很显然,这是根据mode决定显示lock还是unlock的。
关于在Unlock界面输入错误密码的提示流程:
当用户输入密码时,若不正确,此时就会报告错误:
在PasswordUnlockScreen.java中有一个函数verifyPasswordAndUnlock,如下:
private void verifyPasswordAndUnlock() {
String entry = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(entry)) {
mCallback.keyguardDone(true);
mCallback.reportSuccessfulUnlockAttempt();
} else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
mCallback.reportFailedUnlockAttempt();
//在这里,也就是输入次数是5的整数倍时,弹出报错对话框:
if (0 == (mUpdateMonitor.getFailedAttempts()
% LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
handleAttemptLockout(deadline);
}
}
mPasswordEntry.setText("");
}
那么这个错误如何显示的?
上面代码有一处: mCallback.reportFailedUnlockAttempt()
reportFailedUnlockAttempt()函数是在LockPatternKeyguardView.java中,
public void reportFailedUnlockAttempt() {
mUpdateMonitor.reportFailedAttempt();
final int failedAttempts = mUpdateMonitor.getFailedAttempts();
final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
if (usingLockPattern && mEnableFallback && failedAttempts ==
(LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
showAlmostAtAccountLoginDialog();
} else if (usingLockPattern && mEnableFallback
&& failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
mLockPatternUtils.setPermanentlyLocked(true);
updateScreen(mMode);
} else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)
== 0) {
showTimeoutDialog();
}
mLockPatternUtils.reportFailedPasswordAttempt();
}
showAlmostAtAccountLoginDialog和showTimeoutDialog()决定显示什么样的Message:
private void showTimeoutDialog() {
//Get time to lock screen
int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
//Announce a message
String message = "";
//Get unlock mode
UnlockMode unlockMode = getUnlockMode();
if (unlockMode == UnlockMode.password) {
message = mContext.getString(
R.string.lockscreen_too_many_failed_attempts_dialog_message,
mUpdateMonitor.getFailedAttempts(),
timeoutInSeconds);
}
else {
message = mContext.getString(
R.string.lockscreen_too_many_failed_attempts_dialog_message,
mUpdateMonitor.getFailedAttempts(),
timeoutInSeconds);
}
final AlertDialog dialog = new AlertDialog.Builder(mContext)
.setTitle(null)
.setMessage(message)
.setNeutralButton(R.string.ok, null)
.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
if (!mContext.getResources().getBoolean(
com.android.internal.R.bool.config_sf_slowBlur)) {
dialog.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
}
dialog.show();
}
android 锁屏界面处理相关推荐
- android锁屏界面快捷键,Funtouch新特性 锁屏快捷键可以自定义
凤凰数码讯 5月1日 vivo的Funtouch OS系统日前曝出新特性,用户可以自定义锁屏快捷键,大大提升了锁屏界面的易用性. 中关村在线消息,由于设计风格华丽.UI特色鲜明,vivo基于Andro ...
- android 锁屏显示音乐播放器,Android锁屏界面控制音乐播放
目前,在锁屏界面控制音乐播放有两种常用方式. 第一种方式:原生Android系统及自带音乐播放器. 锁屏界面端: 原生Android中,锁屏界面相关的UI由KeyguardHostView提供,Key ...
- android 锁屏界面弹出qq,Android锁屏状态下弹出activity,如新版qq的锁屏消息提示
Android锁屏状态下弹出activity,如新版qq的锁屏消息提示 发布时间:2020-06-26 21:27:13 来源:51CTO 阅读:1643 作者:lp5345 在接收消息广播的onRe ...
- Android 锁屏界面自定义
1.创建个Activity <activity android:excludeFromRecents="true"android:exported="false&q ...
- android 锁屏 home,android 锁屏界面禁用长按home 和menu(recent apps)
android 5.1 系统中 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int polic ...
- Android锁屏界面监听按键,Android 监听锁屏/开屏事件
1. 两种方案 (1) 监听BroadcastReceiver (2)获取PowerManager事件 2. BroadcastReceiver 2.1. 事件 总共有3个事件: Intent.AC ...
- android 锁屏界面 sim卡,注意!手机的这个密码比锁屏密码更重要,赶紧设置!攻略→...
视频加载中,请稍候... 自动播放 近日,一名网友分享了自己的亲身经历,因为手机被盗,不法分子通过手机上的App,窃取他的个人信息,进而申请网贷,造成财产损失.该文章通过互联网大量转发,引发网民对手机 ...
- android锁屏显示应用程序,今日应用:微软又给 Android 做了一款锁屏应用
微软又做了一款 Android 锁屏应用,质量还不错.如果你已经设置了锁屏,Picturesque可能让你再解锁一次你真的需要在锁屏就处理这么多任务吗? 微软又来给 Android 提供应用了,他们昨 ...
- android 原生分享界面_手机资讯:省时省力!直接在锁屏界面打开应用App
如今使用IT数码设备的小伙伴们是越来越多了,那么IT数码设备当中是有很多知识的,这些知识很多小伙伴一般都是不知道的,就好比最近就有很多小伙伴们想要知道省时省力!直接在锁屏界面打开应用App,那么既然现 ...
最新文章
- 计算机设备板块超跌,半导体全线拉升,沪指强势突破3600点,午后A股会再次冲高回落吗...
- Hadoop vs Spark性能对比
- 《梦断代码》阅读笔记01
- lstm中look_back的大小选择_基于机器学习检测僵尸网络中的域名生成算法
- 关于10g RAC监听设置,tnsnames.ora设置,VIP及客户端配置问题
- android调用oncreate,Android - 每次启动时都会调用onCreate
- mysql数据库实战_主题:MySQL数据库操作实战
- pytorch测试用例(查看tensor维度)
- Linux常见目录含义及功能
- C++ 限定名称查找
- 我为什么要放弃RESTful,选择拥抱GraphQL?
- Managing Configuration Data Programmatically in ASP.NET 2.0
- 用微信名片制作软件打造专属的电子名片
- 【犯二记录】链表结点换位引发的思维僵化,太可怕,智商 == 0
- 通过任意数量点拟合曲线
- zblog php 调用缩略图,zblog调用文章缩略图的方法
- 关于 移动硬盘数据丢失问题 的解决方法
- 计算机用鼠标画图,在电脑上用鼠标画画用那个软件好
- Network Battery for mac(实时网速显示和电池健康) 教程
- SQL语言_3 模糊查询和聚合函数