【Android】屏幕方向检测全攻略:从基础配置到传感器融合
1. 为什么屏幕方向检测比你想象的要复杂做Android开发处理屏幕方向切换这事儿我估计大家都遇到过。一开始你可能觉得不就是个横屏竖屏吗系统不是有Configuration.orientation吗直接拿来用不就行了我刚开始也是这么想的结果在实际项目里踩了不少坑。比如用户把手机平放在桌子上或者设备进入了类似三星DeX、小米自由窗口这样的“桌面模式”你之前写好的逻辑可能就全乱套了。屏幕方向检测远不止是“竖着拿”和“横着拿”这么简单。它涉及到系统配置、显示旋转、窗口尺寸、物理传感器等多个层面。不同的应用场景对“方向”的定义和需求也完全不同。一个普通的阅读App可能只需要知道现在是横屏还是竖屏好切换布局但如果你在做相机应用或者AR游戏你就需要知道设备在三维空间里精确的旋转角度这样才能让虚拟物体稳稳地“贴”在现实世界里。所以这篇文章我想和你系统地聊聊Android里获取屏幕方向的几种主流方法。我不会只给你扔几段代码而是会结合我这些年做应用和智能硬件开发的经验告诉你每种方法的原理、适用场景、隐藏的坑以及它们之间如何配合。我们的目标不是找一个“万能”的最优解而是针对你的具体需求找到那个最合适、最可靠的“组合拳”。毕竟在复杂的Android生态里没有银弹只有最适合场景的解决方案。2. 基础篇四种核心检测方案深度剖析我们先从最基础、最常用的几种方法入手把它们彻底讲透。原始文章提到了四种方式我这里会逐一展开补充大量你在官方文档里看不到的细节和实战经验。2.1 方式一依赖系统配置Configuration.orientation—— 简单但有缺陷这是最“偷懒”的方法一行代码搞定fun isPortraitByConfig(): Boolean { return Resources.getSystem().configuration.orientation Configuration.ORIENTATION_PORTRAIT }它是怎么工作的这个方法读取的是全局的系统配置信息。当你的Activity因为屏幕旋转而重建时系统会更新这个Configuration对象里的orientation字段。所以它反映的是系统认为的当前屏幕方向。我踩过的坑和它的局限性延迟问题这个值的更新并不是实时的。在Activity生命周期回调如onConfigurationChanged被触发之前它可能还是旧的值。如果你在onCreate或onResume里立刻调用它在快速旋转设备时可能会拿到错误的方向。“桌面模式”下的失灵这是最大的坑在三星DeX、小米PC模式或华为桌面模式下你的应用窗口可能被用户拖拽成一个长方形的窗口。此时系统配置的orientation很可能依然是PORTRAIT竖屏但你的应用窗口的实际宽高比已经是横屏了。用这个方法判断布局会错乱。无法感知细微角度它只能告诉你横或竖对于0度、90度、180度、270度这些具体朝向它无能为力。注意这个方法适用于对实时性要求不高、且不考虑桌面模式的简单场景。比如一个设置页面只在启动时读取一次方向来初始化布局。但在需要动态响应方向变化的核心场景我建议你慎用。2.2 方式二查询默认显示的旋转角Display.rotation—— 最可靠的基准这是目前公认最准确、最常用的获取物理屏幕方向的方法。fun getScreenRotation(context: Context): Int { val windowManager context.getSystemService(Context.WINDOW_SERVICE) as WindowManager return windowManager.defaultDisplay.rotation } fun isPortraitByRotation(context: Context): Boolean { val rotation getScreenRotation(context) // Surface.ROTATION_0 或 Surface.ROTATION_180 代表竖屏 return rotation Surface.ROTATION_0 || rotation Surface.ROTATION_180 }核心原理Display.rotation返回的是显示硬件Display相对于其自然方向的旋转角度。这个“自然方向”通常是设备出厂时定义的竖屏方向。它的返回值是四个常量Surface.ROTATION_00度、ROTATION_9090度、ROTATION_180180度、ROTATION_270270度。它直接反映了设备物理上的握持状态。为什么它更可靠因为它绕过了“应用窗口”和“系统配置”这些可能被软件层修改的抽象直接询问显示硬件“你现在是怎么被转动的” 因此它在绝大多数情况下包括大多数平板设备上都能给出正确的物理方向。我在开发需要严格区分横竖屏的绘图App和视频播放器时一直把它作为判断的黄金标准。一个关键技巧从Rotation到Orientation我们通常更关心是横屏还是竖屏而不是具体的90度。这里有个标准的转换方法fun getOrientationFromRotation(rotation: Int): Int { return when (rotation) { Surface.ROTATION_90, Surface.ROTATION_270 - ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else - ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } }记住ROTATION_0和ROTATION_180都属于竖屏范畴手机头朝上或朝下ROTATION_90和ROTATION_270属于横屏范畴。2.3 方式三测量屏幕宽高DisplayMetrics—— 应对窗口化模式的利器当方式二在桌面模式下“失效”时它仍然返回物理竖屏但窗口是横的我们就需要方式三来救场。fun isPortraitByMetrics(): Boolean { val metrics Resources.getSystem().displayMetrics return metrics.heightPixels metrics.widthPixels }它的本质是什么这个方法不关心设备怎么拿它只关心一件事当前给应用使用的显示区域窗口是高大于宽还是宽大于高在普通的全屏模式下这个区域就是整个物理屏幕所以它的结果和方式二基本一致。但在桌面模式的窗口化环境下用户拖拽改变了窗口形状这个“显示区域”的尺寸就变了。实战中的组合策略所以一个健壮的方案往往需要方式二和方式三结合判断。我的经验是首选方式二Display.rotation因为它代表物理设备方向对于相机、游戏、需要跟随设备旋转的UI元素这是唯一真理。用方式三DisplayMetrics作为补充和修正当检测到设备可能处于某种窗口模式例如判断UI_MODE_TYPE_DESK或者当方式二的结果与方式三的结果矛盾时以方式三的宽高比为准来调整UI布局。这能确保用户在桌面模式下随意调整窗口大小时你的应用界面总能保持合理的比例。你可以这样写一个融合判断fun getEffectiveOrientation(context: Context): Int { val rotation getScreenRotation(context) val isPhysicalPortrait getOrientationFromRotation(rotation) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT val metrics Resources.getSystem().displayMetrics val isWindowPortrait metrics.heightPixels metrics.widthPixels // 如果物理方向与窗口方向不一致优先相信窗口方向桌面模式场景 // 否则使用物理方向 return if (isPhysicalPortrait ! isWindowPortrait) { if (isWindowPortrait) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE } else { if (isPhysicalPortrait) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE } }2.4 方式四使用方向传感器OrientationEventListener—— 获取连续角度的法宝前面三种方法都只能给出离散的结果横或竖或者四个固定角度。但有些场景需要更精细的数据比如相机应用需要根据设备倾斜角度实时修正取景框和照片的方向。AR应用需要获取设备在空间中的精确朝向来放置虚拟物体。指南针或水平仪应用需要连续的度数变化。这时就要请出OrientationEventListener了。它是如何工作的这个类内部封装了加速度传感器和磁力传感器如果可用的数据。通过传感器融合算法它可以计算出设备相对于地磁北极和重力方向的三个轴向的旋转角度。我们最常用的是它提供的onOrientationChanged回调里的orientation参数这个参数表示的是设备Y轴从底部到顶部与地磁北极的夹角范围是0到359度。重要细节与避坑指南0度的含义当设备竖屏持握且顶部指向地磁北极时orientation为0度。平放失效当设备屏幕朝上或朝下近乎水平放置时由于重力加速度在Z轴上系统无法准确计算绕Z轴的旋转即我们关心的朝向此时回调会传入ORIENTATION_UNKNOWN。这是传感器方案的固有局限无法避免。角度转换传感器返回的是0-359的连续值而我们需要的是0、90、180、270这样的离散方向。需要自己设定一个阈值比如原始代码里的SENSOR_ANGLE 10来进行区间判断。性能与生命周期传感器监听是持续的后台操作虽然功耗不高但也必须妥善管理。一定要在Activity/Fragment的onPause或onDestroy中及时禁用监听器否则会造成资源泄漏和不必要的电量消耗。下面是一个更加健壮、便于使用的传感器方向监听器封装示例我习惯把它做成一个Lifecycle-aware的组件class SensorOrientationHelper( private val context: Context, private val lifecycleOwner: LifecycleOwner ) : LifecycleObserver { private var orientationEventListener: OrientationEventListener? null private var lastReportedDiscreteOrientation -1 private val orientationChangeThreshold 10 // 度 interface OrientationListener { fun onRawOrientationChanged(azimuth: Int) // 原始角度0-359 fun onDiscreteOrientationChanged(orientation: Int) // 离散方向0, 90, 180, 270 } private var listener: OrientationListener? null init { lifecycleOwner.lifecycle.addObserver(this) setupSensorListener() } fun setOrientationListener(listener: OrientationListener) { this.listener listener } private fun setupSensorListener() { orientationEventListener object : OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) { override fun onOrientationChanged(orientation: Int) { if (orientation ORIENTATION_UNKNOWN) { return // 设备平放忽略 } listener?.onRawOrientationChanged(orientation) // 转换为离散方向 val discreteOrientation when (orientation) { in 0..orientationChangeThreshold, in (360 - orientationChangeThreshold)..360 - 0 in (90 - orientationChangeThreshold)..(90 orientationChangeThreshold) - 90 in (180 - orientationChangeThreshold)..(180 orientationChangeThreshold) - 180 in (270 - orientationChangeThreshold)..(270 orientationChangeThreshold) - 270 else - -1 // 处于过渡区间不触发离散变化 } if (discreteOrientation ! -1 discreteOrientation ! lastReportedDiscreteOrientation) { lastReportedDiscreteOrientation discreteOrientation listener?.onDiscreteOrientationChanged(discreteOrientation) } } } if (orientationEventListener?.canDetectOrientation() true) { orientationEventListener?.enable() } else { // 设备不支持方向检测应降级到其他方案 orientationEventListener null } } OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun pause() { orientationEventListener?.disable() } OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun resume() { if (orientationEventListener?.canDetectOrientation() true) { orientationEventListener?.enable() } } OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun destroy() { orientationEventListener?.disable() orientationEventListener null listener null lifecycleOwner.lifecycle.removeObserver(this) } }这样封装后在Activity中使用就非常清晰和安全了class CameraActivity : AppCompatActivity() { private lateinit var sensorHelper: SensorOrientationHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... sensorHelper SensorOrientationHelper(this, this) sensorHelper.setOrientationListener(object : SensorOrientationHelper.OrientationListener { override fun onRawOrientationChanged(azimuth: Int) { // 可用于平滑的UI旋转效果 updateCompassNeedle(azimuth) } override fun onDiscreteOrientationChanged(orientation: Int) { // 用于切换相机预览方向等 adjustCameraPreviewOrientation(orientation) } }) } // 无需手动管理生命周期helper会自动处理 }3. 进阶实战不同开发场景下的方案选型知道了所有工具关键是怎么用。不同的功能模块对“方向”的需求天差地别。这里我结合几个典型场景给你讲讲我的选型思路。3.1 场景一普通UI适配与布局切换这是最常见的需求。用户旋转手机你的应用界面要从单列列表切换成双列网格或者调整图片和文字的排版。核心需求准确、及时地知道当前有效的显示方向是竖长形还是横宽形以加载正确的布局资源。我的方案首选监听onConfigurationChanged在AndroidManifest.xml中为Activity配置android:configChangesorientation|screenSize并重写onConfigurationChanged方法。这是最系统、最推荐的方式。在回调内部使用“方式二方式三”融合判断。因为onConfigurationChanged触发时系统配置可能还未完全同步而Display.rotation和当前窗口的DisplayMetrics是最可靠的。绝对不要在这个场景下使用传感器方式四杀鸡用牛刀且会引入平放失效的问题。代码骨架override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) val effectiveOrientation getEffectiveOrientation(this) // 使用前面定义的融合函数 if (effectiveOrientation ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { setContentView(R.layout.activity_main_portrait) // 初始化竖屏UI } else { setContentView(R.layout.activity_main_landscape) // 初始化横屏UI } }3.2 场景二桌面模式DeX、自由窗口兼容这是现代Android开发特别是平板和折叠屏适配中必须考虑的一环。核心挑战物理设备方向竖屏与软件窗口形状可能是横屏解耦。用户期望应用能智能地适应窗口比例。我的方案核心依赖“方式三”DisplayMetrics。窗口方向就是宽高比这是铁律。动态监听窗口变化除了在配置变更时检查还需要注册ViewTreeObserver.OnGlobalLayoutListener或使用Jetpack WindowManager库来监听窗口尺寸的实时变化。当窗口被用户拖拽改变大小时你需要立即响应。UI设计采用响应式布局不要仅仅依赖layout-land和layout-port这种静态资源切换。更多地使用ConstraintLayout的比例约束、RecyclerView的GridLayoutManager动态设置列数以及通过swNdp等最小宽度限定符来定义布局。这样当窗口尺寸处于“中间状态”既不是典型横屏也不是典型竖屏时UI也能优雅地自适应。关键代码提示// 使用 Jetpack WindowManager 监听窗口特性推荐 val windowInfoRepository WindowInfoRepository.getOrCreate(this) lifecycleScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { windowInfoRepository.currentWindowMetrics.collect { windowMetrics - val bounds windowMetrics.bounds val width bounds.width() val height bounds.height() val isWindowPortrait height width updateLayoutForWindowShape(isWindowPortrait, width, height) } } }3.3 场景三相机Camera/CameraX应用开发相机应用是方向处理的重灾区因为涉及预览方向和照片/视频保存方向。核心需求预览方向让用户在屏幕上看到的画面与设备实际朝向一致。例如手机横拍时预览画面不应是竖着的。输出方向保存的照片或视频文件需要写入正确EXIF方向信息确保在其他设备上查看时是正的。我的方案预览方向使用方式四传感器获取的离散方向0,90,180,270。根据这个方向调用CameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)获取传感器本身的安装方向然后计算出需要设置给CameraPreview的旋转角度。注意这里必须用传感器方向因为用户可能锁定屏幕旋转但预览仍需跟随物理设备。输出方向同样基于传感器获取的离散方向结合设备传感器方向和设备自然方向计算出正确的JPEG方向EXIF标签并在拍照时设置。备用方案在传感器失效设备平放时回退到方式二Display.rotation。虽然用户平放时拍照场景少但代码需要健壮性。简化流程// 在传感器监听的回调中 override fun onDiscreteOrientationChanged(orientation: Int) { val sensorOrientation cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION) val displayRotation windowManager.defaultDisplay.rotation // 备用 val finalRotation if (orientation ! -1) { // 使用传感器方向计算 calculatePreviewRotation(sensorOrientation, orientation) } else { // 设备平放使用显示旋转计算 calculatePreviewRotation(sensorOrientation, displayRotation) } preview.setTargetRotation(finalRotation) imageCapture?.targetRotation finalRotation // 设置输出旋转 }3.4 场景四游戏与AR/VR应用这类应用对方向的实时性和连续性要求最高。核心需求获取设备在三维空间中的实时、连续、平滑的旋转数据偏航Yaw、俯仰Pitch、滚转Roll。我的方案完全依赖传感器且需要更底层的API放弃OrientationEventListener直接使用SensorManager注册TYPE_ROTATION_VECTOR旋转矢量传感器或融合TYPE_ACCELEROMETER和TYPE_MAGNETIC_FIELD。TYPE_ROTATION_VECTOR提供了设备相对于地球坐标系的四元数或旋转矩阵是进行3D旋转计算的黄金标准。使用低延迟模式注册传感器时使用SensorManager.SENSOR_DELAY_GAME或SENSOR_DELAY_FASTEST。传感器数据融合与滤波原始传感器数据存在噪声和抖动。你需要实现或使用库卡尔曼滤波或互补滤波算法来平滑数据避免画面抖动。注意坐标系Android传感器坐标系与OpenGL或游戏引擎如Unity的坐标系可能不同需要进行转换。简要示例private fun setupRotationVectorSensor() { sensorManager getSystemService(SENSOR_SERVICE) as SensorManager rotationVectorSensor sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) val sensorEventListener object : SensorEventListener { override fun onSensorChanged(event: SensorEvent) { if (event.sensor.type Sensor.TYPE_ROTATION_VECTOR) { // event.values 包含了旋转矢量的分量可转换为四元数或旋转矩阵 val rotationMatrix FloatArray(9) SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values) // 将rotationMatrix传递给渲染引擎如OpenGL ES updateGameCamera(rotationMatrix) } } override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} } sensorManager.registerListener(sensorEventListener, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME) }4. 避坑指南与最佳实践结合我多年的经验这里汇总几个最容易出错的地方和对应的解决方案。坑1生命周期管理混乱传感器监听、Display监听如果不和生命周期绑定会导致内存泄漏、后台耗电、回调触发时UI已销毁等问题。实践务必使用LifecycleObserver或ViewModel来管理这些监听器在onPause/onStop中注销在onResume/onStart中按需注册。坑2在主线程执行耗时操作onOrientationChanged或onSensorChanged回调可能非常频繁。如果在其中进行布局测量、文件读写等耗时操作会阻塞主线程导致界面卡顿。实践在回调中只做最简单的数据更新和状态标记将实际的UI更新或业务逻辑抛到主线程的Handler或协程中异步执行。坑3忽略屏幕旋转锁定用户可能开启了“屏幕旋转锁定”。此时Display.rotation不会改变但传感器方向会变。你的应用行为需要一致如果应用是相机/游戏应忽略系统锁定跟随传感器如果是普通UI应尊重系统锁定跟随Display.rotation。实践可以通过Settings.System.getInt(contentResolver, Settings.System.ACCELEROMETER_ROTATION, 0) 1来检查旋转锁定是否关闭从而决定你的策略。坑4折叠屏与多屏适配在折叠屏设备上有内屏、外屏、折叠、展开等多种状态。Display.rotation和窗口尺寸的变化更加复杂。实践拥抱Jetpack WindowManager库使用WindowMetricsCalculator和FoldingFeature来获取更精确的窗口信息和折叠状态从而做出更精细的布局决策。坑5测试不足方向问题在模拟器上很难完全覆盖尤其是传感器相关逻辑。实践必须使用真机进行全方位测试。包括快速旋转、缓慢旋转、平放桌面、插入桌面底座、开启桌面模式、折叠屏开合、屏幕锁定开启/关闭等组合场景。可以编写单元测试来验证你的方向计算逻辑但集成测试必须依赖真机。最后我想说屏幕方向检测是一个典型的“看起来简单做起来坑多”的功能。没有一种方法能通吃所有场景。我的经验是理解每种方法的本质它到底在测量什么然后根据你的具体场景是UI布局、是相机、还是游戏来选择和组合。在普通应用里“方式二为主方式三为辅”的组合已经非常稳健在涉及物理空间感知的应用里传感器方案是不可替代的。希望这些从实战中总结出的经验能帮你少走弯路。

相关新闻

工业物联网实战:用Python+RS485温湿度传感器搭建环境监测系统

工业物联网实战:用Python+RS485温湿度传感器搭建环境监测系统

工业物联网实战:用PythonRS485温湿度传感器搭建环境监测系统 在智能制造、智慧农业和仓储物流这些领域,环境数据的精准采集与实时监控,早已不是锦上添花,而是保障生产安全、提升产品质量和优化运营效率的生命线。想象一下&#xf…

2026/7/4 19:08:08 阅读更多 →
LabVIEW与MCU的USB中断通讯实战解析

LabVIEW与MCU的USB中断通讯实战解析

1. 为什么你的LabVIEW和MCU一通信就报错?从零理解USB中断传输 很多刚开始玩LabVIEW和单片机(MCU)通信的朋友,估计都踩过和我一样的坑:照着串口通信的例子,用VISA写、VISA读,结果一运行就蹦出来一…

2026/7/4 4:56:29 阅读更多 →
中小公司AI人才招聘白皮书:他们真正想要的是什么样的人

中小公司AI人才招聘白皮书:他们真正想要的是什么样的人

一、核心人才画像:中小公司最想要的三类 AI 人​ ​1. 业务落地型(最核心)​ 核心特质:懂业务>懂前沿,能用成熟 AI 技术解决具体业务痛点,不盲目追求模型精度。​ 关键能力:拆解业务场景、设计低成本方案、平衡实时性 / 成本 / 精度,打通 “技术 - 业务” 最后一公里。…

2026/7/3 22:06:09 阅读更多 →

最新新闻

基于A89307和PIC18F4620的BLDC电机FOC控制方案

基于A89307和PIC18F4620的BLDC电机FOC控制方案

1. 项目背景与核心需求在工业自动化、无人机和电动汽车等领域,无刷直流电机(BLDC)因其高效率、高功率密度和长寿命等优势,正逐步取代传统有刷电机。然而,要实现BLDC的高性能控制并非易事——这需要精确的磁场定向控制&…

2026/7/5 7:50:14 阅读更多 →
GLM-5.2 火了以后,Cursor、Claude Code、Codex 怎么统一配置 API?

GLM-5.2 火了以后,Cursor、Claude Code、Codex 怎么统一配置 API?

GLM-5.2 火了以后,Cursor、Claude Code、Codex 该怎么统一配置 API? 最近一段时间,很多人开始把注意力放到 GLM-5.2、DeepSeek、Kimi、豆包、Claude、Gemini 这类模型的实际接入上。 但真正开始配置以后,会发现问题并不只是“哪个…

2026/7/5 7:50:14 阅读更多 →
Nginx配置防御PDF文件XSS攻击:安全响应头实战指南

Nginx配置防御PDF文件XSS攻击:安全响应头实战指南

1. 项目概述:PDF里的XSS,一个被忽视的Web安全盲区 很多Web开发者,包括我自己在早期,都曾有过一个天真的想法:用户上传的PDF文件是“安全”的。毕竟,它不像HTML或JavaScript文件那样能被浏览器直接解析执行…

2026/7/5 7:48:14 阅读更多 →
WSEN-ISDS三轴MEMS传感器与PIC18F47K42的6DOF运动跟踪方案

WSEN-ISDS三轴MEMS传感器与PIC18F47K42的6DOF运动跟踪方案

1. 项目背景与硬件选型解析在机器人导航、工业自动化控制、无人机飞控等需要精确空间定位的领域,三轴运动跟踪一直是核心挑战。传统方案往往需要分别使用加速度计和陀螺仪,再通过复杂的传感器融合算法计算姿态,不仅增加了系统复杂度&#xff…

2026/7/5 7:48:14 阅读更多 →
OpenAI-compatible API 网关实践:Claude API、GPT、Gemini 重试与备用模型切换

OpenAI-compatible API 网关实践:Claude API、GPT、Gemini 重试与备用模型切换

# OpenAI-compatible API 网关实践:Claude/GPT/Gemini 的重试和备用模型切换在真实业务里接入 Claude API、GPT 或 Gemini,最容易低估的不是单次请求怎么写,而是失败时系统会不会稳住。小团队如果只有一个模型、一个 key、一个固定 endpoint&…

2026/7/5 7:46:13 阅读更多 →
BetterJoy终极指南:让Switch手柄在PC上完美工作的5个关键步骤

BetterJoy终极指南:让Switch手柄在PC上完美工作的5个关键步骤

BetterJoy终极指南:让Switch手柄在PC上完美工作的5个关键步骤 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitco…

2026/7/5 7:46:13 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻