Android应用在后台/锁屏状态下如何实现自定义重复振动?
解决Android锁屏/后台状态下自定义振动不生效的问题
当应用处于后台或设备锁屏时,直接调用Vibrator的vibrate方法会被系统的后台限制策略拦截,只能触发系统默认通知振动。要实现锁屏/后台下的自定义振动,核心是将自定义振动与通知渠道绑定,让系统托管通知的振动逻辑,而非直接调用振动API。
具体解决方案步骤:
1. 声明必要权限
在AndroidManifest.xml中添加权限:
<!-- 振动权限 --> <uses-permission android:name="android.permission.VIBRATE" /> <!-- Android 13+ 通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
2. 创建带自定义振动的通知渠道
Android 8.0(API 26)及以上,通知的行为由渠道控制。创建渠道时指定自定义振动波形:
private fun createNotificationChannel(context: Context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channelId = "custom_vibration_channel" val channelName = "自定义振动通知" val channelDescription = "使用自定义振动模式的通知渠道" val importance = NotificationManager.IMPORTANCE_DEFAULT // 定义自定义振动波形:[等待时间, 振动时长, 等待时间, 振动时长], 遵循你原代码的模式 val vibrationPattern = longArrayOf(0L, 300L, 500L, 300L) val channel = NotificationChannel(channelId, channelName, importance).apply { description = channelDescription setVibrationPattern(vibrationPattern) enableVibration(true) } val notificationManager = context.getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } }
3. 发送关联该渠道的通知
当需要触发振动时,发送绑定了上述渠道的通知,系统会自动执行渠道设置的自定义振动,无论应用状态如何:
private fun sendCustomVibrationNotification(context: Context) { val channelId = "custom_vibration_channel" val notificationBuilder = NotificationCompat.Builder(context, channelId) .setSmallIcon(R.drawable.ic_notification) .setContentTitle("周期性通知") .setContentText("触发自定义振动") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setAutoCancel(true) val notificationManager = NotificationManagerCompat.from(context) // 检查Android 13+的通知权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED ) { return } notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build()) }
4. 实现周期性触发
如果需要周期性发送通知,推荐使用WorkManager(适合长期周期性任务,不受系统重启影响):
// 设置周期性任务 private fun schedulePeriodicNotification(context: Context) { val periodicWorkRequest = PeriodicWorkRequestBuilder<NotificationWorker>(15, TimeUnit.MINUTES) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "periodic_custom_vibration", ExistingPeriodicWorkPolicy.REPLACE, periodicWorkRequest ) } // 定义Worker类执行通知发送 class NotificationWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { sendCustomVibrationNotification(applicationContext) return Result.success() } }
关键注意事项:
- 振动模式的循环逻辑:
setVibrationPattern会按你定义的数组循环,若需要重复振动,可调整数组或结合通知的重复逻辑实现。 - 用户设备设置:需确保设备总振动开关开启,且对应通知渠道的振动未被手动关闭。
- 版本适配:不同Android版本的权限、通知渠道逻辑有差异,务必做好版本判断。
内容的提问来源于stack exchange,提问作者Martim Gouveia
相关产品推荐
相关产品推荐

