关于为后台App添加本地通知振动及终止时通知处理的技术问询
Hey,这两个问题确实是本地通知开发里容易踩的坑,我给你分平台整理了具体的实现方案,亲测有效:
一、后台状态下为本地通知添加振动功能
iOS 实现
iOS后台状态下,本地通知要触发振动,关键是在创建通知请求时配置好振动相关参数,同时确保应用已经获取了通知权限(含振动权限)。
- 先完成权限申请:
import UserNotifications UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge, .criticalAlert]) { granted, error in if granted { print("通知权限已获取") } }
其中.criticalAlert是iOS 12+的特性,能确保手机静音时也会振动;普通场景用.sound配合默认振动即可。
- 创建带振动的本地通知请求:
let content = UNMutableNotificationContent() content.title = "后台通知测试" content.body = "这是一条带振动的后台通知" // 使用系统默认振动(搭配默认音效) content.sound = UNNotificationSound.default // 如需自定义振动模式(iOS 13+),可替换成以下代码: // let vibrationPattern = [0, 500, 200, 500] // 暂停、振动、暂停、振动(单位:毫秒) // content.vibrationPattern = vibrationPattern let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false) let request = UNNotificationRequest(identifier: "vibrationNotification", content: content, trigger: trigger) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("添加通知失败:\(error.localizedDescription)") } }
后台状态下只要通知正常触发,配置了振动参数就会自动生效,无需额外后台任务。
Android 实现
Android的振动需要结合通知通道(Android O及以上)和通知构建器配置,同时要提前申请振动权限。
- 在
AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.VIBRATE" />
- 创建带振动配置的通知通道:
import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build fun createNotificationChannel(context: Context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channelId = "vibration_channel" val channelName = "振动通知通道" val channelDescription = "用于发送带振动的本地通知" val importance = NotificationManager.IMPORTANCE_DEFAULT val channel = NotificationChannel(channelId, channelName, importance).apply { description = channelDescription // 设置振动模式:延迟0ms,振动500ms,暂停200ms,振动500ms vibrationPattern = longArrayOf(0, 500, 200, 500) enableVibration(true) } val notificationManager = context.getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } }
- 发送带振动的本地通知:
import android.app.NotificationManager import android.content.Context import androidx.core.app.NotificationCompat fun sendVibrationNotification(context: Context) { val channelId = "vibration_channel" val notificationBuilder = NotificationCompat.Builder(context, channelId) .setSmallIcon(R.drawable.ic_notification) .setContentTitle("后台通知测试") .setContentText("这是一条带振动的后台通知") .setPriority(NotificationCompat.PRIORITY_DEFAULT) // 兼容Android O以下版本的振动设置 .setVibrate(longArrayOf(0, 500, 200, 500)) val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(1, notificationBuilder.build()) }
后台状态下,通知触发时会自动按照配置的振动模式执行。
二、解决应用终止时无法处理本地通知的问题
iOS 实现
应用被终止后,用户点击本地通知启动应用,需要在AppDelegate(或iOS 13+的SceneDelegate)中通过启动参数获取通知信息,同时要设置UNUserNotificationCenter的代理。
- 在
AppDelegate中配置并处理:
import UIKit import UserNotifications @main class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 设置通知中心代理 UNUserNotificationCenter.current().delegate = self // 检查是否从本地通知启动应用 if let oldNotification = launchOptions?[.localNotification] as? UILocalNotification { handleLocalNotification(oldNotification) } // 处理iOS 10+的通知响应 if let notificationResponse = launchOptions?[.notificationResponse] as? UNNotificationResponse { handleNotificationResponse(notificationResponse) } return true } // 处理iOS 9及以下的旧版本地通知 private func handleLocalNotification(_ notification: UILocalNotification) { print("从终止状态启动,处理本地通知:\(notification.userInfo ?? [:])") // 这里写你的业务逻辑,比如跳转对应页面 } // 处理iOS 10+的通知响应 private func handleNotificationResponse(_ response: UNNotificationResponse) { let userInfo = response.notification.request.content.userInfo print("从终止状态启动,处理本地通知:\(userInfo)") // 业务逻辑处理 } // 应用前台时的通知展示配置(可选) func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound, .badge]) } // 应用后台时点击通知的处理 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { handleNotificationResponse(response) completionHandler() } }
如果是iOS 13+的SceneDelegate项目,需要在scene(_:willConnectTo:options:)方法中处理connectionOptions.notificationResponse。
Android 实现
应用被终止后,用户点击本地通知会启动指定Activity,需要在Activity的onCreate或onNewIntent方法中获取通知传递的数据。
- 发送通知时配置跳转和携带数据:
fun sendNotificationWithData(context: Context) { val channelId = "vibration_channel" // 创建跳转的Intent,携带通知数据 val intent = Intent(context, MainActivity::class.java).apply { putExtra("notification_type", "local") putExtra("notification_data", "这是从终止状态点击通知带来的数据") flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } val pendingIntent = PendingIntent.getActivity( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) val notificationBuilder = NotificationCompat.Builder(context, channelId) .setSmallIcon(R.drawable.ic_notification) .setContentTitle("终止状态测试通知") .setContentText("点击启动应用并处理数据") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentIntent(pendingIntent) .setAutoCancel(true) val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(2, notificationBuilder.build()) }
- 在Activity中处理通知数据:
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 处理从通知启动带来的数据 intent?.let { handleNotificationData(it) } } // 处理应用后台时点击通知的情况(Activity已存在时) override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) intent?.let { handleNotificationData(it) } } private fun handleNotificationData(intent: Intent) { val notificationType = intent.getStringExtra("notification_type") val notificationData = intent.getStringExtra("notification_data") if (notificationType == "local") { println("从终止状态启动,处理本地通知数据:$notificationData") // 你的业务逻辑,比如跳转对应页面、展示弹窗等 } } }
这样不管应用处于终止还是后台状态,点击通知都能正确获取并处理数据。
内容的提问来源于stack exchange,提问作者Geet
相关产品推荐
相关产品推荐

