You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Wear OS闹钟应用:如何从AlarmManager/BroadcastReceiver启动闹钟Activity

针对Pixel Watch 2闹钟Activity无法显示的解决方案

核心问题分析

Pixel Watch 2基于Wear OS,系统低功耗策略和锁屏限制会拦截普通的Activity启动请求,尤其是应用处于后台或设备锁屏时。需要结合Wear OS特性调整权限、PendingIntent配置和通知策略。


1. 调整权限与Manifest配置

首先补充必要权限,并修正AlarmActivity的属性:

添加权限到AndroidManifest.xml

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

修改AlarmActivity的Manifest配置

<activity
    android:name=".activities.AlarmActivity"
    android:exported="true"
    android:showWhenLocked="true"
    android:showOnLockScreen="true"
    android:taskAffinity=""
    android:noHistory="true"
    android:excludeFromRecents="true"
    android:launchMode="singleTop"
    android:turnScreenOn="true"
    android:screenOrientation="portrait" />
  • android:exported="true":允许系统服务(如AlarmManager)启动该Activity,避免后台拦截
  • android:showOnLockScreen="true":适配Wear OS锁屏显示规则
  • android:screenOrientation="portrait":匹配Watch的竖屏布局

2. 重构闹钟设置逻辑,结合全屏通知

Wear OS要求闹钟类应用通过全屏通知唤起锁屏Activity,单纯依赖AlarmManager的PendingIntent无法绕过系统限制。修改setAlarm函数:

val Context.alarmManager: AlarmManager
    get() = this.getSystemService(Context.ALARM_SERVICE) as AlarmManager

fun setAlarm(context: Context, millis: Long) {
    val alarmManager = context.alarmManager
    if (!alarmManager.canScheduleExactAlarms()) {
        return
    }

    // 1. 创建启动AlarmActivity的PendingIntent
    val alarmActivityIntent = Intent(context, AlarmActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or
                Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or
                Intent.FLAG_ACTIVITY_NO_USER_ACTION
    }
    val alarmPendingIntent = PendingIntent.getActivity(
        context,
        2,
        alarmActivityIntent,
        PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )

    // 2. 创建全屏通知(Wear OS强制要求)
    val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
            "ALARM_CHANNEL",
            "Alarm Notifications",
            NotificationManager.IMPORTANCE_HIGH
        ).apply {
            description = "Trigger alarm full-screen activity"
            setSound(null, null) // 可自定义闹钟铃声
        }
        notificationManager.createNotificationChannel(channel)
    }

    val fullScreenPendingIntent = PendingIntent.getActivity(
        context,
        3,
        alarmActivityIntent,
        PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )

    val alarmNotification = NotificationCompat.Builder(context, "ALARM_CHANNEL")
        .setSmallIcon(R.drawable.ic_alarm) // 替换为你的应用图标
        .setContentTitle("闹钟已触发")
        .setContentText("点击查看闹钟")
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setCategory(NotificationCompat.CATEGORY_ALARM)
        .setFullScreenIntent(fullScreenPendingIntent, true)
        .build()

    // 3. 设置精确闹钟(适配低功耗模式)
    alarmManager.setExactAndAllowWhileIdle(
        AlarmManager.RTC_WAKEUP,
        millis,
        alarmPendingIntent
    )

    // 提前发送通知,确保系统能捕捉到全屏Intent
    notificationManager.notify(1001, alarmNotification)
}
  • setExactAndAllowWhileIdle:确保闹钟在设备低功耗空闲时也能触发
  • 全屏通知的setFullScreenIntent:触发时自动唤起AlarmActivity,绕过锁屏限制

3. 完善AlarmActivity的唤醒逻辑

在Activity中添加唤醒锁定,确保屏幕持续点亮直到用户处理:

class AlarmActivity : ComponentActivity() {
    private lateinit var wakeLock: PowerManager.WakeLock

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

        logd("on create alarm activity")

        // 申请唤醒锁定,保持屏幕点亮
        val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
        wakeLock = powerManager.newWakeLock(
            PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP,
            "AlarmApp:AlarmWakeLock"
        )
        wakeLock.acquire(10 * 60 * 1000L) // 锁定10分钟,可按需调整

        setTheme(android.R.style.Theme_DeviceDefault)

        setContent {
            MyTheme {
                Box(modifier = Modifier.fillMaxSize()) {
                    Text("Alarm!!")
                    // 在此添加贪睡、关闭按钮的UI与逻辑
                }
            }
        }

        setTurnScreenOn(true)
        setShowWhenLocked(true)
    }

    override fun onDestroy() {
        super.onDestroy()
        // 释放唤醒锁定
        if (::wakeLock.isInitialized && wakeLock.isHeld) {
            wakeLock.release()
        }
    }
}
  • PowerManager.ACQUIRE_CAUSES_WAKEUP:强制点亮屏幕
  • 主动释放唤醒锁:避免不必要的电量消耗

关键注意事项

  • 测试时需关闭应用后台,确保设备处于锁屏状态,模拟真实场景
  • Android 13+需动态申请POST_NOTIFICATIONS权限,否则通知无法发送
  • 避免使用setAlarmClock,Wear OS对该API的支持存在兼容性问题,优先用setExactAndAllowWhileIdle

内容的提问来源于stack exchange,提问作者Kevin van Mierlo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 02:20:11