1

I build my app as a "release" build (with signing and all) to publish it to PlayStore. I get a lot of crash reports from the "Pre-launch report" within PlayStore which all look like this:

Crash java.lang.RuntimeException: Unable to instantiate activity 
ComponentInfo{com.domain/com.domain.MainActivity}: java.lang.ClassNotFoundException: Didn't find 
class "com.domain.MainActivity" on path: DexPathList[[zip file "/data/app/com.domain-1/base.apk", zip 
file "/data/app/com.domain-1/split_config.arm64_v8a.apk", zip file "/data/app/com.domain- 
1/split_config.xxhdpi.apk"],nativeLibraryDirectories=[/data/app/com.domain-1/lib/arm64, 
/data/app/com.domain-1/base.apk!/lib/arm64-v8a, /data/app/com.domain- 
1/split_config.arm64_v8a.apk!/lib/arm64-v8a, /data/app/com.domain- 
1/split_config.xxhdpi.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]]

The build process, however, worked as expected without any failure. Also, the debug build and split-by-abi build is working without any problems or crashes.

This is the folder structure of the Android app (Originally I used another folder structure "app/main/kotlin/com/domain/MainActivity.kt" but with the same result):

enter image description here

This is the gradle.build which is on the androids folder level:

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') {
        reader -> localProperties.load(reader)
    }
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
logger.info("DEBUG - FLUTTER ROOT: " + flutterRoot)
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

buildscript {
    ext.kotlin_version = '1.3.50'
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.3.3'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}

/*
task clean(type: Delete) {
    delete rootProject.buildDir
}
*/

def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    compileSdkVersion 28
    packagingOptions {
        exclude ("META-INF/shared_core_release.kotlin_module")
    }
    defaultConfig {
        applicationId "com.domain"
        minSdkVersion 25
        targetSdkVersion 28
        compileSdkVersion 28
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            signingConfig signingConfigs.release
            sourceSets {

                main {
                    manifest.srcFile 'app/src/main/AndroidManifest.xml'
                    res.srcDirs = ['app/src/main/res']
                }
            }
        }
    }
}

flutter {
    source '..'
}

dependencies {
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

And this is the referenced AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.domain">
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="App"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            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">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- 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>
    <!-- omitted -->
</manifest>

This is the content of app/src/main/kotlin/com.domain/MainActivity.kt:

package com.domain

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);
    }
}

This is the excerpt from flutter doctor:

[√] Flutter (Channel stable, v1.17.5, on Microsoft Windows [Version 10.0.18362.900], locale de-DE)
    • Flutter version 1.17.5 at C:\flutter
    • Framework revision 8af6b2f038 (9 days ago), 2020-06-30 12:53:55 -0700
    • Engine revision ee76268252
    • Dart version 2.8.4

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at C:\Users\xxx\AppData\Local\Android\Sdk
    • Platform android-29, build-tools 29.0.3
    • ANDROID_HOME = C:\Users\xxx\AppData\Local\Android\Sdk
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    X Android license status unknown.
      Try re-installing or updating your Android SDK Manager.
      See https://developer.android.com/studio/#downloads or visit visit
      https://flutter.dev/docs/get-started/install/windows#android-setup for detailed instructions.

[√] Android Studio (version 4.0)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 46.0.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] IntelliJ IDEA Ultimate Edition (version 2019.3)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4
    • Flutter plugin version 44.0.3
    • Dart plugin version 193.6911.31

[√] Connected device (1 available)
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 10 (API 29) (emulator)

Any help would be highly welcome to resolve this problem.

EDIT #1:

After turning off modification, it seems that the com.domain.MainActivity is not present in the dex.

But I don't understand why it's not included.

enter image description here

Alex
  • 1,857
  • 3
  • 36
  • 51
  • didn't you have any Dex related problem when developing your app? – Payam Asefi Jul 09 '20 at 20:24
  • The deployment to the PlayStore itself works without problems. I already looked into the AAB file (and the .dex file) but it's obfuscated. I already tried to build with `--no-shrink` and `--no-obfuscate` but this does not work for some reason. – Alex Jul 09 '20 at 20:30
  • then its probably related to flutter itself. maybe it would be better to ask in in flutter github – Payam Asefi Jul 09 '20 at 20:32
  • Did you try to set `minifiedEnabled` to `false` to turn of ProGuard for your release builds? I would guess that your `MainActivity` class gets obfuscated by Proguard. The entry in the manifest may keep the original class name -> MainActivity cannot be found. To check this, you could use the analyze APK feature built-in in Android Studio. – muetzenflo Jul 12 '20 at 21:39
  • @muetzenflo I've updated my post. It seems that the `MainActivity` is not present in the package. Any idea why it's not present? – Alex Jul 13 '20 at 08:50
  • Maybe the package name format cannot differ from `com.domain.company` in your AndroidManifest and MainActivity. Also check that it is the same as in your pubspec.yaml – Tom Rivoire Jul 13 '20 at 09:13
  • @TomRivoire: It's all in the `com.domain` package. So it's all according to the `AndroidManifest.xml` – Alex Jul 13 '20 at 10:43
  • @Alex okay but the "Cannot find class" error makes me think it comes from the package name and/or the folder structure. And I'm pretty sure that the package name must be 3 words separated by dots `com.domain.appname` and the folder structure `app/src/main/kotlin/com/domain/appname/MainActivity.kt` – Tom Rivoire Jul 13 '20 at 11:40
  • @TomRivoire Changing the package name to 3 segments would be a real pain as I'd also need to create a new app in PlayStore. I also looked up the docs and can't find the requirement for three segments at all. The only requirement I found was "it has to have two segments" (https://stackoverflow.com/a/49069178/1365061). – Alex Jul 13 '20 at 17:34
  • @Alex I understand. Thanks for pointing this, I didn't know a two segments package name was allowed. I think the folder structure with the slash instead of a point is the correct one, but if you tried it before then I don't have any other ideas – Tom Rivoire Jul 15 '20 at 11:48
  • Have a try with `flutter create .` it can be used to get files straighened out after flutter changes some things, it may help you get the files in their proper places. This is odd behavior. Also, seems like you could have caught this error if you built and ran a release version of the app. Never skip that, even if for a quick 2 minutes test. – Fabio Jul 18 '20 at 02:45
  • The problem might be with R8/proguard removing the class . Try adding a proguard rule for excluding the activity . – Manohar Jul 18 '20 at 17:35

1 Answers1

1

I was finally able to resolve the problem to some extend.

After trying all the solutions offered as comments (non of them working) I created a brand new project and copied over the parts that I assumed might cause the problem to try to replicate the problem.

After nothing worked (nothing broke the build or the app for the new project) I copied over everything and just adapt the newly created project. From what I can see, there are no changes and even GIT does not find any remarkable changes.

It's now working even if the solution for this is far behind what I'd hoped for. As there are also no remarkable changes in the project, I can not contribute with deeper insights or what might have caused the problem.

Alex
  • 1,857
  • 3
  • 36
  • 51