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

Flutter(Dart代码)中如何获取应用的实时图标?

在Flutter应用内显示当前使用的实时启动图标

因为flutter_launcher_icons插件仅负责生成各平台的图标资源,并未提供Flutter层直接获取当前启动图标的API,所以需要通过**原生通道(MethodChannel)**实现跨平台的图标获取,以下是具体实现步骤:

Android 端实现

  1. 编写原生方法获取图标
    在android/app/src/main/kotlin/[你的包名]/MainActivity.kt中添加代码:

    import android.content.pm.PackageManager
    import android.graphics.Bitmap
    import android.graphics.drawable.BitmapDrawable
    import io.flutter.embedding.android.FlutterActivity
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodChannel
    
    class MainActivity : FlutterActivity() {
        private val CHANNEL = "com.yourapp/icon_channel"
    
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
                if (call.method == "getAppIcon") {
                    try {
                        val packageManager = packageManager
                        val appIcon = packageManager.getApplicationIcon(packageName)
                        val bitmap = (appIcon as BitmapDrawable).bitmap
                        val stream = ByteArrayOutputStream()
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
                        val byteArray = stream.toByteArray()
                        result.success(byteArray)
                    } catch (e: PackageManager.NameNotFoundException) {
                        result.error("NOT_FOUND", "App icon not found", e)
                    }
                } else {
                    result.notImplemented()
                }
            }
        }
    }
    
  2. Flutter 端调用并展示
    在Flutter页面中通过MethodChannel调用原生方法,将字节流转为Image组件:

    import 'dart:typed_data';
    import 'package:flutter/services.dart';
    import 'package:flutter/widgets.dart';
    
    class AppIconDisplay extends StatefulWidget {
      const AppIconDisplay({super.key});
    
      @override
      State<AppIconDisplay> createState() => _AppIconDisplayState();
    }
    
    class _AppIconDisplayState extends State<AppIconDisplay> {
      final MethodChannel _channel = const MethodChannel('com.yourapp/icon_channel');
      Uint8List? _iconBytes;
    
      @override
      void initState() {
        super.initState();
        _fetchAppIcon();
      }
    
      Future<void> _fetchAppIcon() async {
        try {
          final Uint8List bytes = await _channel.invokeMethod('getAppIcon');
          setState(() {
            _iconBytes = bytes;
          });
        } on PlatformException catch (e) {
          print("Failed to get app icon: ${e.message}");
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return _iconBytes != null
            ? Image.memory(_iconBytes!, width: 64, height: 64)
            : const CircularProgressIndicator();
      }
    }
    

iOS 端实现

  1. 编写原生方法获取图标
    在ios/Runner/AppDelegate.swift中添加代码:

    import UIKit
    import Flutter
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      private let CHANNEL = "com.yourapp/icon_channel"
    
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger)
        channel.setMethodCallHandler { [weak self] call, result in
          guard let self = self else { return }
          if call.method == "getAppIcon" {
            if let appIcon = UIApplication.shared.icon {
              if let data = appIcon.pngData() {
                result.success(data)
              } else {
                result.error("CONVERSION_FAILED", "Failed to convert icon to PNG", nil)
              }
            } else {
              result.error("NOT_FOUND", "App icon not found", nil)
            }
          } else {
            result.notImplemented()
          }
        }
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }
    
    // 扩展UIApplication获取当前图标
    extension UIApplication {
      var icon: UIImage? {
        guard let icons = Bundle.main.infoDictionary?["CFBundleIcons"] as? [String: Any],
              let primaryIcons = icons["CFBundlePrimaryIcon"] as? [String: Any],
              let iconFiles = primaryIcons["CFBundleIconFiles"] as? [String],
              let lastIcon = iconFiles.last else { return nil }
        return UIImage(named: lastIcon)
      }
    }
    
  2. Flutter 端复用代码
    Android端的Flutter代码可直接在iOS上使用,无需额外修改。

注意事项

  • 若应用支持动态切换图标(如Android组件切换、iOSsetAlternateIconName),需在图标切换后重新调用_fetchAppIcon()刷新显示。
  • 替换代码中的com.yourapp/icon_channel为自定义通道名称,避免冲突。
  • 原生代码修改后需重新运行应用,热重载无法生效。

内容的提问来源于stack exchange,提问作者C. Lyman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:15:42