Android SystemUI组件(07)锁屏KeyguardViewMediator分析

该系列文章总纲链接:专题分纲目录 Android SystemUI组件


本章关键点总结 & 说明:

说明:本章节持续迭代之前章节的思维导图,主要关注左侧上方锁屏分析部分即可。

为了更好理解本文的内容,优先说明下SystemUI中与Keyguard(锁屏)相关的类,主要包括:

  • KeyguardViewMediator:这是一个中介类,它负责管理锁屏的状态,包括锁屏的显示和隐藏,以及与锁屏相关的各种事件处理。它还负责在系统启动时初始化锁屏界面,并在设备准备好时启动锁屏。
  • KeyguardService:这个类是锁屏服务的入口点,它接收来自系统其他部分的请求,如启动锁屏或结束锁屏动画。
  • StatusBarKeyguardViewManager:负责管理状态栏中的锁屏视图,包括显示和隐藏锁屏界面。
  • KeyguardUpdateMonitor:监控系统的各种状态变化,如电池状态、时间变化等,并在这些变化发生时更新锁屏界面。
  • KeyguardBouncer:负责显示解锁界面,包括图案、PIN、密码等解锁方式。它处理用户的解锁尝试,并在成功或失败时提供反馈。
  • KeyguardHostView:是锁屏界面的根视图,它承载了所有的解锁方式视图。
  • KeyguardSecurityContainer:包含解锁方式的容器,如图案、PIN、密码等。
  • KeyguardPatternViewKeyguardPINViewKeyguardPasswordView:这些类分别对应不同的解锁方式,它们实现了用户与锁屏界面的交互。
  • KeyguardManager:系统服务,用于管理系统锁屏的状态,如启用或禁用锁屏。

这些类共同工作,提供了一个完整的锁屏体验,包括显示锁屏界面、处理用户解锁尝试、以及在设备准备好时启动锁屏。这些类构成了锁屏功能的核心。

接下来我们从KeyguardViewMediator.start开始分析,一直到KeyguardViewMediator的关键逻辑:doKeyguardLocked方法的内部实现,想了解为什么要从这里开始分析的,可以查看文章:Android SystemUI组件(01)SystemUIService启动。

1 KeyguardViewMediator start启动分析

锁屏KeyguardViewMediator是在systemUI中启动的,从KeyguardViewMediator.start()开始分析。对应代码实现如下:

public class KeyguardViewMediator extends SystemUI {private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;private static final boolean DEBUG = KeyguardConstants.DEBUG;private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;private final static boolean DBG_WAKE = false;private final static String TAG = "KeyguardViewMediator";//...@Overridepublic void start() {synchronized (this) {setupLocked();//初始化与锁屏相关的状态和组件}//将当前实例(this)注册到一个组件管理系统中,以便其他部分的代码可以访问和使用这个实例putComponent(KeyguardViewMediator.class, this);}//...
}

其中关于putComponent方法具体解释如下:

  1. 组件管理putComponent方法通常是一个用于注册组件的工具方法。它将当前的KeyguardViewMediator实例存储在一个全局或共享的组件容器中,使得其他类或模块可以通过这个容器来获取这个实例。

  2. 依赖注入:这种做法类似于依赖注入(Dependency Injection),允许系统中的其他部分在需要时获取KeyguardViewMediator的实例,而不需要直接创建它。这样可以减少类之间的耦合,提高代码的可维护性。

  3. 方便访问:通过将KeyguardViewMediator实例放入组件管理系统,其他类可以方便地访问锁屏的相关功能和状态。例如,其他类可能会调用getComponent(KeyguardViewMediator.class)来获取当前的锁屏管理器实例,以便进行锁屏状态的检查或更新。

接下来我们详细分析代码setupLocked的实现,具体如下:

public class KeyguardViewMediator extends SystemUI {//...private void setupLocked() {// 初始化系统服务和锁屏相关的WakeLockmPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);mWM = WindowManagerGlobal.getWindowManagerService();mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");mShowKeyguardWakeLock.setReferenceCounted(false);// 注册一个广播接收器,用于处理延迟锁屏的动作mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));// 初始化锁屏显示管理器和闹钟管理器服务mKeyguardDisplayManager = new KeyguardDisplayManager(mContext);mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);// 获取锁屏更新监控实例和锁屏图案工具mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);mLockPatternUtils = new LockPatternUtils(mContext);mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());// 根据设备设置和用户状态决定是否显示锁屏,并通知信任管理器锁屏显示状态已改变setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled());mTrustManager.reportKeyguardShowingChanged();// 创建状态栏锁屏视图管理器,用于管理锁屏界面的显示和交互mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,mViewMediatorCallback, mLockPatternUtils);// 获取内容解析器,用于访问系统设置final ContentResolver cr = mContext.getContentResolver();// 检查屏幕是否已经开启mScreenOn = mPM.isScreenOn();// 加载锁屏声音等mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);if (soundPath != null) {mLockSoundId = mLockSounds.load(soundPath, 1);}if (soundPath == null || mLockSoundId == 0) {Log.w(TAG, "failed to load lock sound from " + soundPath);}soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);if (soundPath != null) {mUnlockSoundId = mLockSounds.load(soundPath, 1);}if (soundPath == null || mUnlockSoundId == 0) {Log.w(TAG, "failed to load unlock sound from " + soundPath);}soundPath = Settings.Global.getString(cr, Settings.Global.TRUSTED_SOUND);if (soundPath != null) {mTrustedSoundId = mLockSounds.load(soundPath, 1);}if (soundPath == null || mTrustedSoundId == 0) {Log.w(TAG, "failed to load trusted sound from " + soundPath);}int lockSoundDefaultAttenuation = mContext.getResources().getInteger(com.android.internal.R.integer.config_lockSoundVolumeDb);mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);// 加载锁屏隐藏动画资源mHideAnimation = AnimationUtils.loadAnimation(mContext,com.android.internal.R.anim.lock_screen_behind_enter);}//...
}

setupLocked()方法的主要目的是为KeyguardViewMediator的正常运行做好准备,确保所有必要的组件和状态都已初始化,以便在设备锁屏和解锁时能够正确响应用户的操作和系统事件。具体来说,关键部分主要包括:

  1. 初始化系统服务:该方法会获取系统服务,如PowerManagerWindowManagerTrustManager,这些服务在锁屏和解锁过程中是必不可少的。

  2. 创建锁屏状态监控:它会实例化KeyguardUpdateMonitor,用于监控与锁屏相关的各种状态变化,如电池状态、SIM卡状态等。

  3. 设置锁屏和解锁声音setupLocked()还会加载锁屏和解锁时的声音设置,以便在用户进行解锁操作时提供反馈。

  4. 注册广播接收器:该方法会注册一些广播接收器,以便监听特定的系统事件,如延迟锁屏等。

  5. 创建视图管理器:通过SystemUIFactory创建StatusBarKeyguardViewManager,用于管理锁屏界面的显示和隐藏。

2 开机锁屏流程分析

当设备启动或用户按下电源键时,系统均显示锁屏界面。这个过程涉及KeyguardViewMediator类,它负责协调锁屏的显示和隐藏。接下来分2个部分来解读,一个是从系统的SystemServer启动到KeyguardViewMediator.onSystemReady的过程解读,另一个是SystemServer的SystemReady执行后KeyguardViewMediator具体做了哪些事情。

2.1 从SystemServer启动到KeyguardViewMediator的onSystemReady方法执行

系统SystemServer启动后执行startCoreServices,这里会执行WindowManagerService的systemReady方法,代码实现如下:

public final class SystemServer {private static final String TAG = "SystemServer";//...private void startCoreServices() {WindowManagerService wm = null;//...try {wm.systemReady();} catch (Throwable e) {reportWtf("making Window Manager Service ready", e);}//...}//...
}

这里调用了WindowManagerService的systemReady方法,代码具体实现如下:

public class WindowManagerService extends IWindowManager.Stubimplements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {static final String TAG = "WindowManager";//这里实际上mPolicy就是PhoneWindowManager对象final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();//...public void systemReady() {mPolicy.systemReady();}//...
}

这里实际上就是调用了PhoneWindowManager的systemReady方法,代码具体实现如下:

public class PhoneWindowManager implements WindowManagerPolicy {static final String TAG = "WindowManager";static final boolean DEBUG = false;//...@Overridepublic void systemReady() {mKeyguardDelegate = new KeyguardServiceDelegate(mContext);mKeyguardDelegate.onSystemReady();readCameraLensCoverState();updateUiMode();synchronized (mLock) {updateOrientationListenerLp();mSystemReady = true;mHandler.post(new Runnable() {@Overridepublic void run() {updateSettings();}});}}//...
}

这里调用了mKeyguardDelegate的onSystemReady方法,代码具体实现如下:

public class KeyguardServiceDelegate {public static final String KEYGUARD_PACKAGE = "com.android.systemui";protected KeyguardServiceWrapper mKeyguardService;//...public void onSystemReady() {if (mKeyguardService != null) {mKeyguardService.onSystemReady();} else {mKeyguardState.systemIsReady = true;}}//...
}

这里调用了KeyguardServiceWrapper的onSystemReady方法,代码具体实现如下:

public class KeyguardServiceWrapper implements IKeyguardService {private KeyguardStateMonitor mKeyguardStateMonitor;private IKeyguardService mService;private String TAG = "KeyguardServiceWrapper";//...@Override // Binder interfacepublic void onSystemReady() {try {mService.onSystemReady();} catch (RemoteException e) {Slog.w(TAG , "Remote Exception", e);}}//...
}

这里调用了KeyguardService的onSystemReady方法,代码具体实现如下:

public class KeyguardService extends Service {static final String TAG = "KeyguardService";static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;//...private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {@Override // Binder interfacepublic void addStateMonitorCallback(IKeyguardStateCallback callback) {checkPermission();mKeyguardViewMediator.addStateMonitorCallback(callback);}//...@Override // Binder interfacepublic void onSystemReady() {checkPermission();mKeyguardViewMediator.onSystemReady();}//...}
}

这里调用了KeyguardViewMediator的onSystemReady方法,代码具体实现如下:

public class KeyguardViewMediator extends SystemUI {// 默认的锁屏显示超时延迟时间(30秒)private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;// 锁屏完成挂起的超时时间(3秒)private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;//...public void onSystemReady() {mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);synchronized (this) {mSystemReady = true;// 注册更新监控的回调mUpdateMonitor.registerCallback(mUpdateCallback);// 检查是否使用弱生物识别(如指纹)且相关硬件已安装if (mLockPatternUtils.usingBiometricWeak()&& mLockPatternUtils.isBiometricWeakInstalled()) {// 如果使用弱生物识别,则禁用备用解锁方式mUpdateMonitor.setAlternateUnlockEnabled(false);} else {// 否则,启用备用解锁方式mUpdateMonitor.setAlternateUnlockEnabled(true);}// 执行锁屏逻辑doKeyguardLocked(null);}// 可能发送用户已出现的广播maybeSendUserPresentBroadcast();}//...
}

至此,执行到KeyguardViewMediator.onSystemReady的方法中。这里最关键的便是锁屏逻辑对应的doKeyguardLocked方法。接下来继续分析关键逻辑doKeyguardLocked方法。

2.2 KeyguardViewMediator关键逻辑:doKeyguardLocked方法

doKeyguardLocked的代码分析具体如下所示:

public class KeyguardViewMediator extends SystemUI {private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;//...private void doKeyguardLocked(Bundle options) {// 检查是否允许外部控制锁屏的显示if (!mExternallyEnabled) {return;}// 如果锁屏已经显示,重置状态并返回if (mStatusBarKeyguardViewManager.isShowing()) {resetStateLocked();return;}// 检查是否需要SIM卡,如果需要但SIM卡缺失或被禁用,则不显示锁屏final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);final boolean absent = SubscriptionManager.isValidSubscriptionId(mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.ABSENT));final boolean disabled = SubscriptionManager.isValidSubscriptionId(mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()|| ((absent || disabled) && requireSim);// 如果SIM卡锁定或缺失,并且设备还未完成初始设置向导,则不显示锁屏if (!lockedOrMissing && shouldWaitForProvisioning()) {return;}// 如果锁屏被禁用,并且SIM卡没有被锁定或缺失,则不显示锁屏if (mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {return;}// 如果设备设置了Vold密码,并且当前用户需要输入Vold密码,则不显示锁屏if (mLockPatternUtils.checkVoldPassword()) {setShowingLocked(false);hideLocked();return;}// 如果所有条件都满足,则显示锁屏showLocked(options);}//...//...handler 发送消息 SHOW/HIDEprivate void showLocked(Bundle options) {if (DEBUG) Log.d(TAG, "showLocked");// ensure we stay awake until we are finished displaying the keyguardmShowKeyguardWakeLock.acquire();Message msg = mHandler.obtainMessage(SHOW, options);mHandler.sendMessage(msg);}//...handler处理private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case SHOW:handleShow((Bundle) msg.obj);break;case HIDE:handleHide();break;//...}}};//handler关键处理方法handleShowprivate void handleShow(Bundle options) {synchronized (KeyguardViewMediator.this) {// 如果系统还没有准备好,忽略显示锁屏的请求if (!mSystemReady) {return;}// 标记锁屏为显示状态setShowingLocked(true);// 调用状态栏锁屏视图管理器显示锁屏mStatusBarKeyguardViewManager.show(options);// 标记锁屏不是在隐藏状态mHiding = false;// 重置锁屏完成挂起的状态resetKeyguardDonePendingLocked();// 标记没有运行隐藏动画mHideAnimationRun = false;// 更新活动锁屏状态updateActivityLockScreenState();// 调整状态栏adjustStatusBarLocked();// 用户活动事件userActivity();// 在最后执行,以免延迟锁屏显示playSounds(true);// 释放锁屏显示时持有的WakeLockmShowKeyguardWakeLock.release();}// 显示锁屏管理器mKeyguardDisplayManager.show();}

这里调用了mStatusBarKeyguardViewManager的show方法,代码具体实现如下:

public class StatusBarKeyguardViewManager {//step1 显示锁屏public void show(Bundle options) {mShowing = true; // 标记锁屏为显示状态mStatusBarWindowManager.setKeyguardShowing(true); // 通知状态栏窗口管理器锁屏正在显示reset(); // 调用reset方法来重置锁屏状态}//step2 重置锁屏状态public void reset() {if (mShowing) {if (mOccluded) {mPhoneStatusBar.hideKeyguard(); // 如果锁屏被遮挡,隐藏锁屏mBouncer.hide(false /* destroyView */); // 隐藏解锁界面(Bouncer)} else {showBouncerOrKeyguard(); // 显示解锁界面或锁屏}updateStates(); // 更新锁屏状态}}//step3 显示解锁界面或锁屏private void showBouncerOrKeyguard() {if (mBouncer.needsFullscreenBouncer()) {mPhoneStatusBar.hideKeyguard(); // 需要全屏解锁界面时,隐藏锁屏mBouncer.show(true); // 显示解锁界面(Bouncer)} else {mPhoneStatusBar.showKeyguard(); // 不需要全屏解锁界面时,显示锁屏mBouncer.hide(false); // 隐藏解锁界面(Bouncer)mBouncer.prepare(); // 准备解锁界面(Bouncer)}}
}

接下来主要解读mBouncer.show和hide的实现及相关流程。主要以show方法(加载视图)为主。接下来继续分析KeyguardBouncer的show方法和hide方法流程,代码具体实现如下:

public class KeyguardBouncer {private Context mContext;//...private final Runnable mShowRunnable = new Runnable() {@Overridepublic void run() {// 设置锁屏视图的可见性为可见mRoot.setVisibility(View.VISIBLE);// 恢复锁屏视图的活动状态mKeyguardView.onResume();// 开始锁屏视图的显示动画mKeyguardView.startAppearAnimation();// 清除锁屏即将显示的标志mShowingSoon = false;}};//...//加载及锁屏界面关键流程//step1 显示锁屏界面public void show() {// 确保锁屏视图已经创建,锁屏View的加载ensureView();// 如果锁屏视图已经是可见的或者即将显示,则不需要再次显示if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {// 更新当前的安全方法,这在锁屏已经显示但当前安全方法发生变化时是必要的mKeyguardView.show();return;}// 尝试dismiss锁屏。如果没有设置安全模式,这将dismiss整个锁屏。// 如果需要认证,则显示解锁界面(Bouncer)。if (!mKeyguardView.dismiss()) {// 设置标志,表示锁屏即将显示mShowingSoon = true;// 在多个帧上分散工作mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable,null, 48);}}//step2 确保锁屏视图已经创建private void ensureView() {//检查mRoot(锁屏界面的根视图)是否已经存在。if (mRoot == null) {//加载锁屏界面inflateView();}}//step3 加载锁屏界面private void inflateView() {// 如果之前已经添加过锁屏视图,先将其移除removeView();// 通过LayoutInflater从keyguard_bouncer布局文件中加载锁屏界面布局mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);// 从加载的布局中获取KeyguardViewBase实例mKeyguardView = (KeyguardViewBase) mRoot.findViewById(R.id.keyguard_host_view);// 为锁屏视图设置锁图案工具,用于处理锁屏图案相关逻辑mKeyguardView.setLockPatternUtils(mLockPatternUtils);// 为锁屏视图设置ViewMediatorCallback,用于处理锁屏界面的回调事件mKeyguardView.setViewMediatorCallback(mCallback);// 将锁屏视图添加到容器视图中,确保它在容器的最后面mContainer.addView(mRoot, mContainer.getChildCount());// 初始时将锁屏视图的可见性设置为不可见mRoot.setVisibility(View.INVISIBLE);// 设置系统UI可见性,禁用HOME按钮,这样用户在锁屏界面上不会看到HOME按钮mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);}//...//隐藏锁屏界面关键流程//step1 隐藏锁屏界面public void hide(boolean destroyView) {// 取消任何即将执行的显示锁屏的操作cancelShowRunnable();// 如果锁屏视图不为空,则进行清理if (mKeyguardView != null) {// 移除锁屏视图上的解散动作,即用户不再能通过这个视图解散锁屏mKeyguardView.setOnDismissAction(null);// 清理锁屏视图,这可能包括重置状态、停止动画等mKeyguardView.cleanUp();}// 如果传入的参数destroyView为true,则完全移除锁屏视图if (destroyView) {removeView();} else if (mRoot != null) {// 如果不销毁视图,只是将其设置为不可见mRoot.setVisibility(View.INVISIBLE);}}//step2 锁屏界面不显示,取消线程private void cancelShowRunnable() {// 从Choreographer中移除之前安排的动画帧更新回调mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null);// 将mShowingSoon标志设置为false,表示锁屏界面不再即将显示mShowingSoon = false;}
}

最后,总结下整个流程,具体如下:

KeyguardViewMediator类中的doKeyguardLocked方法是用来控制锁屏界面显示的核心逻辑。这个方法会根据设备的当前状态和设置来决定是否显示锁屏。以下是该方法的概要流程:

  1. 检查锁屏状态:首先,方法会检查锁屏是否已经被外部控制(例如通过setKeyguardEnabled方法)禁用。如果锁屏已被禁用,则不会显示锁屏。

  2. 检查锁屏是否已显示:如果锁屏已经显示在屏幕上,方法会重置锁屏状态并返回,不会重复显示锁屏。

  3. 检查SIM卡状态:方法会检查SIM卡是否缺失或被禁用,如果设备需要SIM卡且SIM卡状态不正常,则不会显示锁屏。

  4. 检查设备设置:如果设备还未完成初始设置向导,且SIM卡被锁定或缺失,则不会显示锁屏。

  5. 检查锁屏设置:如果锁屏被设置为禁用,或者设备设置了Vold密码,方法会隐藏锁屏并返回。

  6. 显示锁屏:如果所有条件都满足,方法会调用showLocked方法来显示锁屏界面。

StatusBarKeyguardViewManager类中的show方法负责实际显示锁屏界面。它首先将锁屏的显示状态设置为true,然后调用reset方法来重置锁屏状态。reset方法会根据锁屏是否被遮挡来决定是显示解锁界面(Bouncer)还是锁屏界面。

KeyguardBouncer类中的show方法用于显示解锁界面(Bouncer)。如果需要全屏解锁界面,它会隐藏锁屏并显示解锁界面。否则,它会显示锁屏并隐藏解锁界面,并准备解锁界面以供用户输入。

KeyguardBouncer类中的hide方法用于隐藏解锁界面。它会取消任何即将执行的显示操作,并根据传入的参数决定是销毁视图还是仅仅将其设置为不可见。

这些方法共同工作,确保了锁屏界面能够在适当的时机显示或隐藏,同时提供了用户反馈和设备安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/428947.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[已更新前两问代码+全部建模]2024华为杯C题详细思路代码文章建模分享研究生数学建模竞赛数学建模研赛

截止9.21 12点 已更新问题一二的代码和全部内容的建模 下面我们会先进行代码讲解,之后给出全部内容的建模公式 ## https://docs.qq.com/doc/DVWhyZ1NFY01XcmNw基于磁通密度数据的特征提取与分类分析。 问题一代码详解 1. 导入必要的库 import pandas as pd import numpy as…

Elastic 的 OpenTelemetry PHP 发行版简介

作者:Pawel Filipczak 宣布 OpenTelemetry PHP 的 Elastic 发行版的第一个 alpha 版本。在本篇博文中了解使用 OpenTelemetry 来检测 PHP 应用程序是多么简单。 我们很高兴推出 OpenTelemetry PHP 的 Elastic Distribution 的第一个 alpha 版本。在这篇文章中&…

十九、石英晶体振荡电路

石英晶体振荡电路 1、石英晶体的特点、等效电路、特性曲线; 2、石英晶体振动器的特点, 3、石英晶体振动器的振荡频率

【爱给网-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

滑动窗口算法专题(1)

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏: 优选算法专题 目录 滑动窗口算法的简介 209. 长度最小的子数组 3.无重复字符的最长子串 1004. 最大连续1的个数III 1658. 将减到0的最小…

Java调用数据库 笔记06 (修改篇)

1.创建Java的普通class类 2.加载驱动 Class.forName("com.mysql.jdbc.Driver"); 3.驱动管理类调用方法进行连接,得到连接对象 DriverManager.getConnection(url, user, password); 其中设置参数: static final String url "jdbc:my…

python中ocr图片文字识别样例(二)

一、说明 本次解决图片相关出现中文乱码问题,属于上篇文章的优化,前提条件依赖上篇文章的包,当然ocr的具体应用场景很多,根据自身需求进行调整 二、具体实现 2.1 代码实现: # -*- coding: utf-8 -*- import easyoc…

电气设备施工现场风险状态判断ai模型训练数据集

电气设备施工现场风险状态判断ai模型训练数据集 id:18 电气设备施工现场工人人工智能学习数据和工作环境安全数据,建立系统化管理体系,改变全球EHS范式,预防工业事故。数据集记录了387709例子电力设施建设以及施工现场相关的灾害安全环境数据…

电力行业螺钉螺帽螺丝缺失检测数据集 voc yol

电力行业螺钉螺帽螺丝缺失检测数据集 数据集描述 该数据集旨在用于电力行业中的螺钉、螺帽、螺丝等紧固件的缺失检测任务。数据集包含了大量的图像及其对应的标注信息,可用于训练计算机视觉模型,以识别和定位电力设施中的螺钉、螺帽、螺丝等部件是否存在…

【零成本】七日杀 服务器搭建 异地联机 无需公网IP、服务器

主要内容 什么是七日杀 搭建前需要准备什么 详细步骤 1.Steam中下载七日杀服务器工具 2.修改七日杀服务配置文件 3.启动七日杀服务器应用 4.运行 MoleSDN 进行异地联机 5.小伙伴打开游戏加入 鼠鼠的服务器 什么是七日杀 《七日杀》是一款沙盒生存恐怖游戏,…

【2025】儿童疫苗接种预约小程序(源码+文档+解答)

博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…

LeetCode[中等] 54.螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 思路:定义方向数组,按照顺时针顺序:右(0,1),下(1,0),左(0,-1),上(0,-1) 从矩阵的左上角开始遍历…

5. 数字证书与公钥基础设施

5. 数字证书与公钥基础设施 (1) PKI 的定义、组成及应用 PKI(Public Key Infrastructure,公钥基础设施) 是一个使用公钥技术来提供安全服务的框架。它定义了如何管理和维护公钥,以及如何通过证书来验证公钥的真实性。PKI的核心组成部分包括: 证书颁发机构(CA, Certifica…

Maven 安装

Maven 安装 Maven 下载安装 下载MAVEN 选择版本注意: IDEA 2022 兼容maven 3.8.1及之前的所用版本 IDEA 2021 兼容maven 3.8.1及之前的所用版本 IDEA 2020 兼容Maven 3.6.3及之前所有版本 IDEA 2018 兼容Maven3.6.1及之前所有版本 打开MAVEN官网 下载需要的版本 Wi…

软件设计师——操作系统

📔个人主页📚:秋邱-CSDN博客☀️专属专栏✨:软考——软件设计师🏅往期回顾🏆:C: 类和对象(上)🌟其他专栏🌟:C语言_秋邱 一、操作系统…

Qt_窗口界面QMainWindow的介绍

目录 1、菜单栏QMenuBar 1.1 使用QMainWindow的准备工作 1.2 在ui文件中设计窗口 1.3 在代码中设计窗口 1.4 实现点击菜单项的反馈 1.5 菜单中设置快捷键 1.6 菜单中添加子菜单 1.7 菜单项中添加分割线和图标 1.8 关于菜单栏创建方式的讨论 2、工具栏QToolBar …

谷歌-BERT-“bert-base-chinese ”

1 需求 需求:自动下载模型和分词器 需求:手动导入模型和分词器 需求:pipeline使用预训练模型 需求:训练和评估 需求:测试 关键词:训练数据集、评估数据集、测试数据集 需求:上线 2 接口 3 自…

[UTCTF2020]sstv

用goldwave和010editor打开均未发现线索, 网上搜索sstv,豆包回答如下: 慢扫描电视(Slow Scan Television,简称 SSTV)是一种通过无线电传输和接收静态图像的技术。 一、工作原理 SSTV 通过将图像逐行扫描并…

鸿蒙OpenHarmony【轻量系统内核通信机制(互斥锁)】子系统开发

互斥锁 基本概念 互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。 任意时刻互斥锁的状态只有两种,开锁或闭锁。当任务持有互斥锁时,该互斥锁处于闭锁状态,这个任务获得该互斥锁…

利用Metasploit进行信息收集与扫描

Metasploit之信息收集和扫描 在本文中,我们将学习以下内容 使用Metasploit被动收集信息 使用Metasploit主动收集信息 使用Nmap进行端口扫描 使用db_nmap方式进行端口扫描 使用ARP进行主机发现 UDP服务探测 SMB扫描和枚举 SSH版本扫描 FTP扫描 SMTP枚举 …