# 自启动与按键自定义

本页说明 Glass3 上应用开机自启动、物理按键监听和按键事件拦截的常见实现方式。

## 1. 开机自启动

### 功能说明

应用可以通过设置系统属性，让设备重启后自动拉起指定包名的应用。

适用场景：

- 巡检、安防、工业作业等专用应用。
- 设备开机后需要直接进入业务页面。
- 不希望用户手动从应用列表启动。

### 配置方式

通过反射调用 `android.os.SystemProperties` 设置系统属性：

```kotlin
fun setSystemProp(key: String?, value: String?) {
    try {
        val clazz = Class.forName("android.os.SystemProperties")
        val set = clazz.getMethod("set", String::class.java, String::class.java)
        set.invoke(clazz, key, value)
    } catch (e: Exception) {
        Log.e("SystemProp", "set system prop failed", e)
    }
}
```

将当前应用设置为开机自启动：

```kotlin
setSystemProp("persist.vendor.boot.pkg", packageName)
```

设备重启后，系统会读取该属性并拉起对应应用。

### 使用建议

- 建议在应用初始化时延迟 1–2 秒再初始化 SDK，避免系统服务尚未完全就绪。
- 请确认应用有明确的启动页。
- 若多个应用都设置自启动，以系统最终写入的包名为准。
- 该能力依赖系统支持，建议在目标系统版本上验证。

## 2. 物理按键监听

### 支持的事件

常见按键广播包括：

| 事件 | Action |
| --- | --- |
| 单击 | `com.rokid.glass3.action.button.CLICK` |
| 双击 | `com.rokid.glass3.action.button.DOUBLE_CLICK` |
| 按下 | 以当前系统提供的 `ACTION_BUTTON_DOWN` 为准 |
| 抬起 | 以当前系统提供的 `ACTION_BUTTON_UP` 为准 |

不同系统版本可能会有扩展 action，建议以 Demo 中 `MyApplication` 定义为准。

## 3. 拦截按键事件

应用可以注册高优先级广播接收器，并在需要消费事件时调用 `abortBroadcast()`。

```kotlin
private val buttonReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        when (intent?.action) {
            MyApplication.ORDER_ACTION_BUTTON_CLICK -> {
                Log.d(TAG, "single click")
                abortBroadcast()
                screenShot()
            }

            MyApplication.ORDER_ACTION_BUTTON_DOUBLE_CLICK -> {
                Log.d(TAG, "double click")
            }

            MyApplication.ACTION_BUTTON_DOWN -> {
                Log.d(TAG, "button down")
            }

            MyApplication.ACTION_BUTTON_UP -> {
                Log.d(TAG, "button up")
            }
        }
    }
}
```

注册广播：

```kotlin
private val intentFilter = IntentFilter().apply {
    addAction(MyApplication.ORDER_ACTION_BUTTON_CLICK)
    addAction(MyApplication.ORDER_ACTION_BUTTON_DOUBLE_CLICK)
    addAction(MyApplication.ACTION_BUTTON_DOWN)
    addAction(MyApplication.ACTION_BUTTON_UP)
    priority = 100
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        registerReceiver(buttonReceiver, intentFilter, RECEIVER_EXPORTED)
    } else {
        registerReceiver(buttonReceiver, intentFilter)
    }
}

override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(buttonReceiver)
}
```

## 4. 长按处理

如果业务需要识别长按，可以在 `ACTION_BUTTON_DOWN` 时延迟执行，在 `ACTION_BUTTON_UP` 时取消。

```kotlin
private val handler = Handler(Looper.getMainLooper())
private val longPressRunnable = Runnable {
    Log.d(TAG, "long press")
}

private fun onButtonDown() {
    handler.postDelayed(longPressRunnable, 1200)
}

private fun onButtonUp() {
    handler.removeCallbacks(longPressRunnable)
}
```

## 5. 注意事项

- 建议设置 `priority > 0`，确保业务接收器优先处理。
- 只有有序广播才能被 `abortBroadcast()` 拦截。
- 系统保留按键不一定允许应用拦截。
- 指环中间键长按通常会触发 `KEY_POWER`，用于亮屏/灭屏，应用层无法拦截。
- 按键行为可能随系统版本变化，正式交付前请在目标系统版本上验证。
