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

Flutter中如何检查并启用应用内通知、弹窗及通知音效设置?

Flutter通知细分设置检查与处理方案

一、Flutter层面的基础处理

permission_handler仅能获取通知总权限,无法直接检查细分项(弹窗、音效等),需要通过MethodChannel调用原生平台代码实现细分检查与设置引导。

Flutter端MethodChannel封装

import 'package:flutter/services.dart';

class NotificationSettingsManager {
  static const MethodChannel _channel = MethodChannel('notification_settings');

  // 检查通知细分设置状态
  static Future<Map<String, bool>> checkNotificationSettings() async {
    final Map<dynamic, dynamic> result = await _channel.invokeMethod('checkSettings');
    return {
      'allowNotifications': result['allowNotifications'] ?? false,
      'hasPopup': result['hasPopup'] ?? false,
      'hasSound': result['hasSound'] ?? false,
    };
  }

  // 尝试启用细分设置(部分平台仅能引导)
  static Future<bool> enableNotificationSettings() async {
    return await _channel.invokeMethod('enableSettings') ?? false;
  }

  // 跳转到应用通知设置页
  static Future<void> openNotificationSettings() async {
    await _channel.invokeMethod('openSettings');
  }
}

二、Android原生实现(Kotlin)

Android的通知设置分为通知渠道的重要性、弹窗、音效,需针对当前应用的通知渠道进行检查与配置。

1. 检查通知细分设置

import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationManagerCompat

class NotificationSettingsHandler(private val context: Context) {

    fun checkSettings(): Map<String, Boolean> {
        val notificationManager = NotificationManagerCompat.from(context)
        val result = mutableMapOf<String, Boolean>()

        // 总通知权限
        result["allowNotifications"] = notificationManager.areNotificationsEnabled()

        // 获取默认通知渠道(若未自定义渠道,用系统默认)
        val defaultChannel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            notificationManager.getNotificationChannel("default")
        } else null

        // 弹窗(悬浮通知):对应渠道的重要性 >= IMPORTANCE_HIGH
        result["hasPopup"] = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            defaultChannel?.importance ?: NotificationManager.IMPORTANCE_DEFAULT >= NotificationManager.IMPORTANCE_HIGH
        } else {
            // Android 7及以下:检查是否允许弹窗
            android.provider.Settings.System.getInt(context.contentResolver, "notification_popup", 1) == 1
        }

        // 通知音效:渠道是否启用声音
        result["hasSound"] = defaultChannel?.sound != null || (Build.VERSION.SDK_INT < Build.VERSION_CODES.O &&
                android.provider.Settings.System.getInt(context.contentResolver, "notification_sound", 1) == 1)

        return result
    }

2. 尝试启用细分设置(仅Android 8+可修改渠道配置)

fun enableSettings(): Boolean {
        val notificationManager = NotificationManagerCompat.from(context)
        if (!notificationManager.areNotificationsEnabled()) return false

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val defaultChannel = notificationManager.getNotificationChannel("default") ?: run {
                // 创建默认渠道
                val channel = android.app.NotificationChannel("default", "默认通知", NotificationManager.IMPORTANCE_HIGH)
                channel.enableVibration(true)
                channel.enableSound(true)
                channel.setShowBadge(true)
                notificationManager.createNotificationChannel(channel)
                channel
            }

            // 修改渠道设置:启用弹窗和音效
            defaultChannel.importance = NotificationManager.IMPORTANCE_HIGH
            defaultChannel.enableSound(true)
            notificationManager.createNotificationChannel(defaultChannel)
            return true
        }
        // Android 7及以下无法通过代码修改,需引导用户手动设置
        return false
    }

3. 跳转应用通知设置页

fun openSettings() {
        val intent = android.content.Intent(android.provider.Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
            putExtra(android.provider.Settings.EXTRA_APP_PACKAGE, context.packageName)
        }
        context.startActivity(intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK))
    }
}

注册MethodChannel到MainActivity

class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "notification_settings").setMethodCallHandler { call, result ->
            val handler = NotificationSettingsHandler(this)
            when (call.method) {
                "checkSettings" -> result.success(handler.checkSettings())
                "enableSettings" -> result.success(handler.enableSettings())
                "openSettings" -> {
                    handler.openSettings()
                    result.success(null)
                }
                else -> result.notImplemented()
            }
        }
    }
}

三、iOS原生实现(Swift)

iOS的通知权限是统一申请的,细分设置(弹窗、音效)需用户在系统设置中开启,仅能检查状态,无法通过代码修改。

1. 检查通知细分设置

import UserNotifications

class NotificationSettingsHandler {
    func checkSettings(completion: @escaping ([String: Bool]) -> Void) {
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            var result = [String: Bool]()
            // 总通知权限
            result["allowNotifications"] = settings.authorizationStatus == .authorized
            // 弹窗(横幅/提醒样式)
            result["hasPopup"] = settings.alertStyle != .none
            // 通知音效
            result["hasSound"] = settings.soundSetting == .enabled
            completion(result)
        }
    }

2. 申请总通知权限(iOS必须先申请)

func requestNotificationPermissions(completion: @escaping (Bool) -> Void) {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
            completion(granted)
        }
    }

3. 跳转应用通知设置页

func openSettings() {
        guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
        UIApplication.shared.open(url, options: [:], completionHandler: nil)
    }
}

注册MethodChannel到AppDelegate

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let channel = FlutterMethodChannel(name: "notification_settings", binaryMessenger: controller.binaryMessenger)
        let handler = NotificationSettingsHandler()
        
        channel.setMethodCallHandler { call, result in
            switch call.method {
            case "checkSettings":
                handler.checkSettings { settings in
                    result.success(settings)
                }
            case "enableSettings":
                handler.requestNotificationPermissions { granted in
                    result.success(granted)
                }
            case "openSettings":
                handler.openSettings()
                result.success(nil)
            default:
                result.notImplemented()
            }
        }
        
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

四、使用流程示例

// 检查设置
final settings = await NotificationSettingsManager.checkNotificationSettings();
if (!settings['allowNotifications']!) {
  // iOS先申请权限,Android引导或启用
  await NotificationSettingsManager.enableNotificationSettings();
} else if (!settings['hasPopup']! || !settings['hasSound']!) {
  // 引导用户到设置页
  await NotificationSettingsManager.openNotificationSettings();
}

内容的提问来源于stack exchange,提问作者PandaKom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:43:16