Prevent App Restart When Applying Wallpaper in Flutter

Introduction

In Android 12 and above, Google implements a feature called Dynamic Colors.

It allows the system to change the colors of the app based on the wallpaper. This is a great feature, but it has a problem. When you apply wallpaper, the app restarts. This occurs because it’s a configChanges, so all activities are restarted.

In the last few days, I was working on a Flutter project that required the user to be able to change the system wallpaper. I was looking for a way to prevent the app from restarting when the wallpaper is changed. I found a solution, and I’m going to share it with you.

Solution

The solution in a Flutter project is to use a FlutterEngineCache. It’s a cache that stores FlutterEngines and this cache will prevent the app from restarting when the wallpaper is changed.

Simple Example

In the android folder of your Flutter project, create a new file called MyAppApplication.kt and add the following code:

package com.example.myapp

import android.app.Application
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor

class MyAppApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        // Create a FlutterEngine instance.
        flutterEngine = FlutterEngine(this)

        // Start executing Dart code to pre-warm the FlutterEngine.
        flutterEngine.dartExecutor.executeDartEntrypoint(
            DartExecutor.DartEntrypoint.createDefault()
        )

        // Cache the FlutterEngine to be used by FlutterActivity.
        // You can use any identifier
        FlutterEngineCache
            .getInstance()
            .put("my_engine_id", flutterEngine)
    }
}

After that, in the AndroidManifest.xml file, add the following code:


<application
    android:name=".MyAppApplication"
    ...>
    ...

Then, in your MainActivity.kt, add the following code:

class MainActivity : FlutterActivity() {

    override fun provideFlutterEngine(context: Context): FlutterEngine? {
        // The same identifier used in the MyAppApplication.kt
        return FlutterEngineCache.getInstance().get("my_engine_id")
    }

    @RequiresApi(Build.VERSION_CODES.N)
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "you_channel_name")
            .setMethodCallHandler { call, result ->
                when (call.method) {
                    "set_wallpaper" -> {/* handle wallpaper change */}
                    else -> result.notImplemented()
                }
            }
    }
}

Now, you can call the set_wallpaper method from your Flutter code and this prevents the app from restarting.

Comments

comments powered by Disqus