本文目录导读:

  1. 实现原理
  2. 核心代码实现
  3. 关键配置
  4. 优化建议
  5. 调试技巧

实现原理

  1. 触发条件:车辆停止(手刹拉起) + 用户无操作超时
  2. 退出条件:触摸屏幕/车辆启动(手刹释放)
  3. 功能特性
    • 全屏沉浸式显示
    • 显示时间/日期/车辆信息
    • 低功耗处理
    • 防止系统休眠

核心代码实现

屏保Activity (ScreensaverActivity.kt)

class ScreensaverActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_screensaver)
        // 全屏沉浸模式
        window.apply {
            addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            decorView.systemUiVisibility = (
                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN
            )
        }
        // 触摸退出
        root_layout.setOnClickListener { finish() }
        // 初始化显示
        updateDisplay()
        // 每秒更新一次时间
        Handler(Looper.getMainLooper()).postDelayed(updateRunnable, 1000)
    }
    private val updateRunnable = object : Runnable {
        override fun run() {
            updateDisplay()
            Handler(Looper.getMainLooper()).postDelayed(this, 1000)
        }
    }
    private fun updateDisplay() {
        val time = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date())
        val date = SimpleDateFormat("yyyy/MM/dd EEEE", Locale.getDefault()).format(Date())
        tv_time.text = time
        tv_date.text = date
    }
    override fun onDestroy() {
        super.onDestroy()
        // 清除定时器
        Handler(Looper.getMainLooper()).removeCallbacks(updateRunnable)
    }
}

屏保布局 (activity_screensaver.xml)

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000"
    android:clickable="true">
    <!-- 时间显示 -->
    <TextView
        android:id="@+id/tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textColor="#FFFFFF"
        android:textSize="80sp"
        android:fontFamily="sans-serif-light"/>
    <!-- 日期显示 -->
    <TextView
        android:id="@+id/tv_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_time"
        android:layout_centerHorizontal="true"
        android:textColor="#CCCCCC"
        android:textSize="24sp"
        android:layout_marginTop="16dp"/>
</RelativeLayout>

屏保管理服务 (ScreensaverService.kt)

class ScreensaverService : Service() {
    private val idleHandler = Handler(Looper.getMainLooper())
    private val idleRunnable = Runnable { startScreensaver() }
    private val idleTimeout = 5 * 60 * 1000L // 5分钟无操作
    // 监听车辆状态(需替换为实际车机SDK)
    private val vehicleStateReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "com.vehicle.HANDBRAKE_CHANGED") {
                val isHandbrakeOn = intent.getBooleanExtra("is_on", false)
                if (!isHandbrakeOn) {
                    // 手刹释放时关闭屏保
                    stopScreensaver()
                }
            }
        }
    }
    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        resetIdleTimer()
        registerVehicleReceiver()
        return START_STICKY
    }
    private fun resetIdleTimer() {
        idleHandler.removeCallbacks(idleRunnable)
        idleHandler.postDelayed(idleRunnable, idleTimeout)
    }
    private fun startScreensaver() {
        if (!isScreensaverActive()) {
            val intent = Intent(this, ScreensaverActivity::class.java).apply {
                flags = Intent.FLAG_ACTIVITY_NEW_TASK
            }
            startActivity(intent)
        }
    }
    private fun stopScreensaver() {
        // 通过ActivityManager关闭屏保Activity
        (getSystemService(ACTIVITY_SERVICE) as ActivityManager).apply {
            getRunningTasks(10).forEach { task ->
                if (task.topActivity?.className == ScreensaverActivity::class.java.name) {
                    // 发送关闭广播(Activity内接收后finish)
                    sendBroadcast(Intent("CLOSE_SCREENSAVER"))
                }
            }
        }
    }
    private fun isScreensaverActive(): Boolean {
        // 检测屏保是否已在前台
    }
    private fun registerVehicleReceiver() {
        registerReceiver(vehicleStateReceiver, IntentFilter("com.vehicle.HANDBRAKE_CHANGED"))
    }
    override fun onBind(intent: Intent) = null
}

用户操作监听(在BaseActivity中)

open class BaseActivity : AppCompatActivity() {
    override fun onUserInteraction() {
        super.onUserInteraction()
        // 通知服务重置计时器
        sendBroadcast(Intent("RESET_IDLE_TIMER"))
    }
}

关键配置

AndroidManifest.xml 配置

<!-- 屏保Activity -->
<activity
    android:name=".ScreensaverActivity"
    android:theme="@style/FullScreenTheme"
    android:excludeFromRecents="true"
    android:showOnLockScreen="true"
    android:turnScreenOn="true"/>
<!-- 全屏主题 -->
<style name="FullScreenTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowBackground">@android:color/black</item>
</style>
<!-- 后台服务 -->
<service android:name=".ScreensaverService" />

权限申请

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

优化建议

  1. 硬件加速:在布局中使用android:hardwareAccelerated="true"
  2. 能耗控制:使用PARTIAL_WAKE_LOCK保持CPU运行
  3. :添加天气预报/音乐封面等动态元素
  4. 车辆数据集成
    // 示例:获取车速(需车机SDK支持)
    val speed = VehicleApi.getSpeed() 
    if (speed > 5) stopScreensaver() // 行驶中关闭屏保
  5. 动画效果:使用属性动画实现平滑的时间刷新

调试技巧

  1. 使用adb shell dumpsys activity检查Activity栈
  2. 模拟车辆状态:
    adb shell am broadcast -a com.vehicle.HANDBRAKE_CHANGED --ez is_on true
  3. 强制触发屏保:
    startService(Intent(this, ScreensaverService::class.java))

注意事项:实际开发中需替换车辆状态API为车机厂商提供的SDK接口,不同车型的车辆信号获取方式可能不同。

免责声明

本网站内容仅供参考,不构成专业建议。使用本网站内容造成的损失,本网站不承担责任。

网站内容来源于网络,如有侵权请联系我们删除!

相关推荐