Flutter issues with release-mode only APK builds

4,069

Solution 1

I had this exact problem. I solved it with a couple different ways:

  1. Add proguard-rules.pro to android/app/proguard-rules.pro
#Flutter Wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.**  { *; }
-keep class io.flutter.util.**  { *; }
-keep class io.flutter.view.**  { *; }
-keep class io.flutter.**  { *; }
-keep class io.flutter.plugins.**  { *; }
-keep class androidx.lifecycle.** { *; } #https://github.com/flutter/flutter/issues/58479
#https://medium.com/@swav.kulinski/flutter-and-android-obfuscation-8768ac544421
  1. add proguard to buildTypes in app level build.gradle
buildTypes {
    release {
        profile {
            matchingFallbacks = ['debug', 'release']
        }
    minifyEnabled true
    useProguard true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    signingConfig signingConfigs.release
    }
}
lintOptions {
    disable 'InvalidPackage'
    checkReleaseBuilds false
}
  1. You can also try running master channel in terminal:
flutter channel master
  1. I also migrated android to AndroidX in Android Studio by navigating to SDK manager->SDK tools->checking and downloading Google Play services

  2. I also made sure that compile SDK and target SDK is 29; there are issues with permission_handler package with SDK 30 at the moment.

  3. I also edited the kotlin main activity file:

package yourpackage
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

Solution 2

For me this solved the issue

just add proguard-rules.pro to android/app/proguard-rules.pro

and add the following line:

-keep class androidx.lifecycle.DefaultLifecycleObserver
Share:
4,069
The Tahaan
Author by

The Tahaan

My feet on a mountain, I am alive.

Updated on December 24, 2022

Comments

  • The Tahaan
    The Tahaan over 1 year

    When running the app from an installed APK I have issues but when running directly from Android studio the app works well. Tested on Both physical devices and emulators, and also with build modes debug, profile and release (where release and profile modes of course only works on physical devices)

    Summary: a) Shared Prefs, Path Provider and Permission Handler produces a MissingPluginException. b) The Android back button does not work.

    These may be separate issues but I have a strong suspicion that they are related because both of them occur only when the app is started from an APK not installed directly from Android Studio.

    To be very clear - if I "install" the app from within Android Studio, I can then continue using the app even without AS connected. However when I build an APK, install it manually, and try to run the app I get various symptoms caused by the above errors. If I then connect Logcat via Android Studio, the issues will persist until I install a new build using AS.

    Some more details:

    1. During the APK build process for release mode, gradle complains about missing "libs.jar" files, for example:
    Execution failed for task ':app:lintVitalQaRelease'.                    
    > Could not resolve all artifacts for configuration ':app:devProfileRuntimeClasspath'.
       > Failed to transform libs.jar to match attributes {artifactType=processed-jar, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
          > Execution failed for JetifyTransform: /home/johan/AndroidStudioProjects/teacher_app/build/app/intermediates/flutter/devProfile/libs.jar.
             > Transform's input file does not exist: /home/johan/AndroidStudioProjects/teacher_app/build/app/intermediates/flutter/devProfile/libs.jar. (See https://issuetracker.google.com/issues/158753935)
    
    

    Searching for solutions to the above brings up several documented cases, except that they generally don't have Flavors, so :app:lintVitalRelease in stead of :app:lintVitalQaRelease as I am getting. In addition the error will show the missing intermediates as .../flutter/Profile/libs.jar in the reported cases, again without the flavors.

    In my case the extra Qa and dev respectively are two different flavors. Where in the other cases the workaround is "build your debug and profile mode apk to fix the issue", in my case it is "Build your debug and profile AND release APKs for all the other flavors, not just the one you're trying to build".

    So I toggle between trying to build flavor "Qa" mode "release", and whichever one it complains about, over and over about until it is satisfied and produces the APK. It is annoying to have to build a bunch of unrelated flavors and modes, but at least is is a workaround that gets me an APK.

    After this I am able to install and un from the APK, but with issues. logcat shows some MissingPlugin exceptions occuring:

    MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider)

    and....

    MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)

    Finally: While investigating this all I tried the permission handler example from https://pub.dev/packages/permission_handler/example. I just added it as a new "page" into my app. On navigatign to this page I get another exception:

    MissingPluginException(No implementation found for method checkPermissionStatus on channel flutter.baseflow.com/permissions/methods)

    A lot of functionality in the app related to these plugins are not working - Photos don't display, user needs to authenticate on each restart, and so on. These are clearly dependent on the above plugins.

    I've tried to add WRITE_EXTERNAL_STORAGE to the AndroidManifest, even added it to the separate manifests for each of the flavors. (I normally add shared config to the main AndroidManifest.xml only)

    I've implemented signing for release mode just in case Android doesn't like to give permissions to unsigned APKs.

    EDIT: To eliminate the application-ID as being the cause of the issue I've changed all instances back to the original package name used when the project was created. This means only one flavor can be installed on my device at a time. It however does not make any difference.


    I've obviously done flutter-clean and flutter-get many times, each time forcing me to go through the process of building all the missing intermediates one by one.

    One other thing... The Android Back button doesn't work. It works fine if I run the app directly from Android Studio, but doesn't work (seems to be ignored) when running it from APK only.

    I'm at my wits end with this.

    EDIT #2: Progress!
    I created a new project and copied the source (lib/*) over. I also copied pubspec.yaml and the assets. I have made no changes to the build.gradle file, and only made two changes to the main AndroidManifest.xml - the Application Name and added the Internet permission.

    I also did set the app icon.

    Copying the source over was ardorous - there being many many many imports but the end result is a working build.

    SharedPrefs survives restarts Downloaded images are displayed Android back-button works Device Permissions for Storage shows as granted Opening the camera from within the app asks for permission the first time. The app can send the user to the Android App settings screen.

    Everything seems to work. I probably made a mistake somewhere because the new app shows the correct app Icon on the home screen but shows the Flutter default icon in the Android settings page for the app.

    The next steps would be to sign the APK and then to re-introduce flavors, even if just to be able to set the dart target, but hopefully also to set other properties.