如何用flutter的dart语言动态改变app图标?

问题描述 投票:0回答:1

经过大量研发,我能够使用flutter的dart语言动态更改应用程序图标。

为了实现这一目标:

一开始我在寻找插件并找到了一个(flutter_dynamic_icon),但它仅适用于 iOS。但我需要同时实现两个平台(android 和 iOS),所以再次进行了一些研发,发现了一个 Blog,它实际上符合我的要求。它使用方法通道来实现这一点,我也做了同样的事情,并且成功了。

但是我发现了一个问题,当我点击功能来动态设置应用程序图标时,应用程序会自行关闭并显示应用程序图标已更改,但我不想关闭应用程序。

注意:这是我第一次使用方法通道来调用本机异步方法,并且从未使用过 kotlin 语言,所以我无法做到这一点意味着如何防止应用程序在动态设置应用程序图标后关闭。

代码:

Android端

MainActivity.kt

package com.app.demo



import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.pm.PackageManager
import androidx.annotation.NonNull
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.dynamicIcon"
   var methodChannelResult: MethodChannel.Result? = null


   @Override
   override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
       super.configureFlutterEngine(flutterEngine)

       MethodChannel(flutterEngine.dartExecutor, CHANNEL).setMethodCallHandler { call, result ->

           try {
               methodChannelResult = result;
               if (call.method.equals("launcherFirst")) {                
                   setIcon("launcherAlias.FirstLauncherAlias", 1)
                   result.success(true)
               } else if (call.method.equals("launcherSecond")) {                 
                   setIcon("launcherAlias.SecondLauncherAlias", 2)
                   result.success(true)

               }else if (call.method.equals("launcherThird")) {                 
                   setIcon("launcherAlias.ThirdLauncherAlias", 3)
                   result.success(true)

               }else if (call.method.equals("launcherFourth")) {                 
                   setIcon("launcherAlias.FourthLauncherAlias", 4)
                   result.success(true)

               }else if (call.method.equals("launcherFifth")) {                 
                   setIcon("launcherAlias.FifthLauncherAlias", 5)
                   result.success(true)

               } else {
//                   
                   setIcon("launcherAlias.DefaultLauncherAlias", 0)
                   result.success(true)
               }
           } catch (e: Exception) {
               print(e)
           }
       }
   }


   //dynamically change app icon
   private fun setIcon(targetIcon: String, index: Int) {
       try {
           val packageManager: PackageManager = applicationContext!!.packageManager
           val packageName = applicationContext!!.packageName
           val className = StringBuilder()
           className.append(packageName)
           className.append(".")
           className.append(targetIcon)

           when (index) {
               0 -> {
                   packageManager.setComponentEnabledSetting(
                       ComponentName(packageName, "$packageName.$targetIcon"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
                   )

                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.FirstLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.SecondLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.ThirdLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FourthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FifthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
               }

               1 -> {
                   packageManager.setComponentEnabledSetting(
                       ComponentName(packageName, "$packageName.$targetIcon"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
                   )

                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.DefaultLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.SecondLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.ThirdLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FourthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FifthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
               }

               2 -> {
                   packageManager.setComponentEnabledSetting(
                       ComponentName(packageName, "$packageName.$targetIcon"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
                   )

                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.DefaultLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.FirstLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.ThirdLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FourthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FifthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
               }

               3 -> {
                   packageManager.setComponentEnabledSetting(
                       ComponentName(packageName, "$packageName.$targetIcon"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
                   )

                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.DefaultLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.FirstLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.SecondLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FourthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FifthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
               }

               4 -> {
                   packageManager.setComponentEnabledSetting(
                       ComponentName(packageName, "$packageName.$targetIcon"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
                   )

                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.DefaultLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.FirstLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.SecondLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.ThirdLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )

                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FifthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
               }

               5 -> {
                   packageManager.setComponentEnabledSetting(
                       ComponentName(packageName, "$packageName.$targetIcon"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
                   )

                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.DefaultLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName!!,
                           "$packageName.launcherAlias.FirstLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.SecondLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.ThirdLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )
                   packageManager.setComponentEnabledSetting(
                       ComponentName(
                           packageName,
                           "$packageName.launcherAlias.FourthLauncherAlias"
                       ),
                       PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                       PackageManager.DONT_KILL_APP
                   )

               }

           }
       } catch (e: Exception) {
           print(e)
       }
   }
}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   package="com.app.demo">
   <uses-permission
       android:name="android.permission.READ_EXTERNAL_STORAGE"/>
   <uses-permission
       android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
   <uses-permission
       android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   <uses-permission android:name="android.permission.VIBRATE"/>
   <application
       android:label="Demo"
       android:name="${applicationName}"
       android:icon="@drawable/black_app_icon">
       <!-- tools:replace="android:icon" -->

       <activity
           android:name=".MainActivity"
           android:exported="true"
           android:enabled="false"
           android:launchMode="singleTop"
           android:theme="@style/LaunchTheme"
           android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
           android:hardwareAccelerated="true"
           android:windowSoftInputMode="adjustResize">
           <!-- Specifies an Android theme to apply to this Activity as soon as
                the Android process has started. This theme is visible to the user
                while the Flutter UI initializes. After that, this theme continues
                to determine the Window background behind the Flutter UI. -->
           <meta-data
               android:name="io.flutter.embedding.android.NormalTheme"
               android:resource="@style/NormalTheme"/>
           <intent-filter>
               <action android:name="android.intent.action.MAIN"/>
               <category android:name="android.intent.category.LAUNCHER"/>
           </intent-filter>
       </activity>

       <activity-alias
           android:name=".launcherAlias.FirstLauncherAlias"
           android:enabled="false"
           android:icon="@drawable/black_app_icon"
           android:label="Demo"

           android:targetActivity=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />

               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />


           </intent-filter>
       </activity-alias>


       <activity-alias
           android:name=".launcherAlias.SecondLauncherAlias"
           android:enabled="false"
           android:icon="@drawable/blue_app_icon"
           android:label="Demo"

           android:targetActivity=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />

               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />


           </intent-filter>
       </activity-alias>

       <activity-alias
           android:name=".launcherAlias.ThirdLauncherAlias"
           android:enabled="false"
           android:icon="@drawable/red_app_icon"
           android:label="Demo"

           android:targetActivity=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />

               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />


           </intent-filter>
       </activity-alias>

       <activity-alias
           android:name=".launcherAlias.FourthLauncherAlias"
           android:enabled="false"
           android:icon="@drawable/yellow_app_icon"
           android:label="Demo"

           android:targetActivity=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />

               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />


           </intent-filter>
       </activity-alias>

       <activity-alias
           android:name=".launcherAlias.FifthLauncherAlias"
           android:enabled="false"
           android:icon="@drawable/green_app_icon"
           android:label="Demo"

           android:targetActivity=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />

               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />


           </intent-filter>
       </activity-alias>


       <activity-alias
           android:name=".launcherAlias.DefaultLauncherAlias"
           android:enabled="true"
           android:icon="@drawable/white_app_icon"
           android:label="Demo"

           android:targetActivity=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />

               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />


           </intent-filter>
       </activity-alias>

       <!-- Don't delete the meta-data below.
            This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
       <meta-data
           android:name="flutterEmbedding"
           android:value="2"/>

   </application>
</manifest>

Flutter的dart代码端:

dynamic_launcher.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';


class DynamicLauncher extends StatefulWidget {
 const DynamicLauncher({super.key});

 @override
 State<DynamicLauncher> createState() => _DynamicLauncherState();
}

class _DynamicLauncherState extends State<DynamicLauncher> {
static const platform = MethodChannel('com.dynamicIcon');

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       backgroundColor: Theme.of(context).colorScheme.inversePrimary,
       title: const Text('Dynamic Launcher Icons'),
     ),
     body: Column(
       crossAxisAlignment: CrossAxisAlignment.center,
       mainAxisAlignment: MainAxisAlignment.center,
       children: [
         const Text('Change Launcher Icon'),
         const SizedBox(height: 50),
         TextButton.icon(
           onPressed: () async {
             try{
               var result =  await platform.invokeMethod('launcherFirst');
               debugPrint("Set Green AppIcon Success :$result");
             }catch(e){
               debugPrint("Set Black AppIcon Failed :${e.toString()}");
             }
           },
           icon: const Icon(
             Icons.android,
             color: Colors.black,
           ),
           label: const Text(
             'Set Black AppIcon',
             style: TextStyle(color: Colors.black),
           ),
         ),
         TextButton.icon(
           onPressed: () async {

             try{
               var result =   await platform.invokeMethod('launcherSecond');
               debugPrint("Set Blue AppIcon Success:$result");
             }catch(e){
               debugPrint("Set Blue AppIcon Failed :${e.toString()}");
             }
           },
           icon: const Icon(
             Icons.android,
             color: Colors.blue,
           ),
           label: const Text(
             'Set Blue AppIcon',
             style: TextStyle(color: Colors.blue),
           ),
         ),
         TextButton.icon(
           onPressed: () async {

             try{
               var result =   await platform.invokeMethod('launcherThird');
               debugPrint("Set Red AppIcon Success:$result");
             }catch(e){
               debugPrint("Set Red AppIcon Failed :${e.toString()}");
             }
           },
           icon: const Icon(
             Icons.android,
             color: Colors.red,
           ),
           label: const Text(
             'Set Red AppIcon',
             style: TextStyle(color: Colors.red),
           ),
         ),
         TextButton.icon(
           onPressed: () async {

             try{
               var result =   await platform.invokeMethod('launcherFourth');
               debugPrint("Set Yellow AppIcon Success:$result");
             }catch(e){
               debugPrint("Set Yellow AppIcon Failed :${e.toString()}");
             }
           },
           icon: const Icon(
             Icons.android,
             color: Colors.yellow,
           ),
           label: const Text(
             'Set Yellow AppIcon',
             style: TextStyle(color: Colors.yellow),
           ),
         ),
         TextButton.icon(
           onPressed: () async {

             try{
               var result =   await platform.invokeMethod('launcherFifth');
               debugPrint("Set Green AppIcon Success:$result");
             }catch(e){
               debugPrint("Set Green AppIcon Failed :${e.toString()}");
             }
           },
           icon: const Icon(
             Icons.android,
             color: Colors.green,
           ),
           label: const Text(
             'Set Green AppIcon',
             style: TextStyle(color: Colors.green),
           ),
         ),
         TextButton.icon(
           onPressed: () async {

             try{
               var result =   await platform.invokeMethod('default');
               debugPrint("Set Default appIcon Success :$result");
             }catch(e){
               debugPrint("Set Default appIcon Failed :${e.toString()}");
             }
           },
           icon: const Icon(
             Icons.restore,
             color: Colors.grey,
           ),
           label: const Text(
             'Set Default App Icon',
             style: TextStyle(color: Colors.grey),
           ),
         ),


       ],
     ),
   );
 }
}

结果:视频

android flutter dart flutter-method-channel
1个回答
0
投票

我认为你误解了,你尝试使用的包只能在 iOS 上运行。如果是这种情况,您将无法通过其方法通道调用其 Android 实现。

仅支持iOS(版本> 10.3)。

表示可能仅适用于 iOS > 10.3。

在自己调用方法通道之前,你尝试过在Android上使用它吗?

© www.soinside.com 2019 - 2024. All rights reserved.