Flutter(Dart代码)中如何获取应用的实时图标?
在Flutter应用内显示当前使用的实时启动图标
因为flutter_launcher_icons插件仅负责生成各平台的图标资源,并未提供Flutter层直接获取当前启动图标的API,所以需要通过**原生通道(MethodChannel)**实现跨平台的图标获取,以下是具体实现步骤:
Android 端实现
编写原生方法获取图标
在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() } } } }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 端实现
编写原生方法获取图标
在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) } }Flutter 端复用代码
Android端的Flutter代码可直接在iOS上使用,无需额外修改。
注意事项
- 若应用支持动态切换图标(如Android组件切换、iOS
setAlternateIconName),需在图标切换后重新调用_fetchAppIcon()刷新显示。 - 替换代码中的
com.yourapp/icon_channel为自定义通道名称,避免冲突。 - 原生代码修改后需重新运行应用,热重载无法生效。
内容的提问来源于stack exchange,提问作者C. Lyman
相关产品推荐
相关产品推荐

