I’m having issues upgrading my flutter solution properly. A requirement to upgrade a flutter package to a newer version led to upgrading my flutter and dart version, and eventually my gradle and kotlin version. The upgrade worked fine on emulators but my app seems to keep crashing on startup on real devices, but only on Android 14 devices. Looking at LogCat’s logs I see the following message:
E/AndroidRuntime(16431): FATAL EXCEPTION: main
E/AndroidRuntime(16431): Process: za.co.synthesis.halo.mpos.dashpay, PID: 16431
E/AndroidRuntime(16431): java.lang.NoSuchMethodError: no static method "Lkotlin/UByteArray;.get-impl([BI)B"
E/AndroidRuntime(16431): at z.b.$hdbg$E5da45fa0(Native Method)
E/AndroidRuntime(16431): at z.b.<init>(Unknown Source:7)
E/AndroidRuntime(16431): at Q.b.$hdbg$E04e79ce6(Native Method)
E/AndroidRuntime(16431): at Q.b.<init>(Unknown Source:7)
E/AndroidRuntime(16431): at za.co.synthesis.halo.sdk.c0.$hdbg$E6c1216be(Native Method)
E/AndroidRuntime(16431): at za.co.synthesis.halo.sdk.c0.<init>(Unknown Source:7)
E/AndroidRuntime(16431): at za.co.synthesis.halo.sdk.HaloSDK$Companion.onCreate(Native Method)
E/AndroidRuntime(16431): at za.co.synthesis.halo.halo_mpos_common.HaloActivity.onCreate(HaloActivity.kt:27)
E/AndroidRuntime(16431): at android.app.Activity.performCreate(Activity.java:8944)
E/AndroidRuntime(16431): at android.app.Activity.performCreate(Activity.java:8913)
E/AndroidRuntime(16431): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
E/AndroidRuntime(16431): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4146)
E/AndroidRuntime(16431): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322)
E/AndroidRuntime(16431): at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
E/AndroidRuntime(16431): at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
E/AndroidRuntime(16431): at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
E/AndroidRuntime(16431): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685)
E/AndroidRuntime(16431): at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime(16431): at android.os.Looper.loopOnce(Looper.java:230)
E/AndroidRuntime(16431): at android.os.Looper.loop(Looper.java:319)
E/AndroidRuntime(16431): at android.app.ActivityThread.main(ActivityThread.java:8893)
E/AndroidRuntime(16431): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(16431): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
E/AndroidRuntime(16431): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
This tells me that Kotlin itself is having an issue executing properly on one of my packages but I’m very new to mobile development and I don’t know where, and I can’t find any meaningful information out of the error message due to my limited experience. All I can think of is that one of my packages’ versions don’t align with my Kotlin version in my android file. Here is my build.gradle files
app/build.gradle:
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')
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 plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
android {
compileSdkVersion 34
ndkVersion "21.2.6472646"
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
flavorDimensions "tenant"
productFlavors {
dashpay {
applicationId "za.co.synthesis.halo.mpos.dashpay"
minSdkVersion 26
targetSdkVersion 34
multiDexEnabled true
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// The following argument makes the Android Test Orchestrator run its
// "pm clear" command after each test invocation. This command ensures
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
dimension "tenant"
}
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "za.co.synthesis.halo.mpos.dashpay"
minSdkVersion 26
targetSdkVersion 34
multiDexEnabled true
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// The following argument makes the Android Test Orchestrator run its
// "pm clear" command after each test invocation. This command ensures
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
useLibrary 'android.test.runner'
useLibrary 'android.test.base'
useLibrary 'android.test.mock'
signingConfigs {
releaseDashpay {
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key_dashpay.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
debug {
manifestPlaceholders = [usesCleartextTraffic:"true"]
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-debug.pro'
}
release {
// true for testing purposes
manifestPlaceholders = [usesCleartextTraffic: "false"]
// TODO: Add your own signing config for the release build.
// signingConfig signingConfigs.release
productFlavors.dashpay.signingConfig signingConfigs.releaseDashpay
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
namespace 'za.co.synthesis.halo.mpos'
lint {
checkReleaseBuilds false
disable 'InvalidPackage'
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:multidex:1.0.3'
implementation "androidx.core:core-ktx:1.3.1"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
Properties properties = new Properties()
def propertiesFile = project.rootProject.file('local.properties')
if (propertiesFile.exists()) {
properties.load(propertiesFile.newDataInputStream())
}
def localScpToolDir = properties.getProperty('scp.dir')
def systemEnvScpToolDir = System.getenv('SCP_DIR')
def scpToolDir = localScpToolDir ?: systemEnvScpToolDir
android.applicationVariants.all { variant ->
if (variant.buildType.name == "profile") {
return
}
def profileFile = "../../mpos${variant.name.capitalize()}.nwproj"
task "prepare${variant.name.capitalize()}"(type: Exec) {
group "codeProtection"
description "Convert parts of Android artifact to C, which can then be processed in the analysis, profiling and protection procedures"
commandLine "$scpToolDir/scp-tool",
"--prepare", profileFile,
"--mapping-file", "$buildDir/outputs/mapping/${variant.name}/mapping.txt"
}
task "analyse${variant.name.capitalize()}"(type: Exec) {
group "codeProtection"
description "Determines what files are compiled and how. Used for profiling and protecting"
dependsOn "prepare${variant.name.capitalize()}"
commandLine "$scpToolDir/scp-tool",
"--analyze", profileFile,
"--mapping-file", "$buildDir/outputs/mapping/${variant.name}/mapping.txt"
}
task "profile${variant.name.capitalize()}"(type: Exec) {
group "codeProtection"
description "Build a profiling application"
dependsOn "analyse${variant.name.capitalize()}"
commandLine "$scpToolDir/scp-tool",
"--build-profiling", profileFile,
"--mapping-file", "$buildDir/outputs/mapping/${variant.name}/mapping.txt"
}
task "protect${variant.name.capitalize()}"(type: Exec) {
group "codeProtection"
description "Build protected application"
dependsOn "analyse${variant.name.capitalize()}"
commandLine "$scpToolDir/scp-tool",
"--protect", profileFile,
"--mapping-file", "$buildDir/outputs/mapping/${variant.name}/mapping.txt"
}
}
build.gradle:
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.14'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
}
}
allprojects {
repositories {
google()
mavenCentral()
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor 1, 'days'
resolutionStrategy {
force 'androidx.annotation:annotation:1.3.0'
}
resolutionStrategy.dependencySubstitution {
substitute(module("androidx.core:core-ktx")).with(module("androidx.core:core-ktx:(*, 1.3.2]"))
substitute(module("org.jetbrains.kotlin:kotlin-stdlib-jdk7")).with(module("org.jetbrains.kotlin:kotlin-stdlib-jdk7:(*, 1.3.72]"))
substitute(module("org.jetbrains.kotlin:kotlin-stdlib-jdk8")).with(module("org.jetbrains.kotlin:kotlin-stdlib-jdk7:(*, 1.3.72]"))
substitute(module("androidx.window:window-java")).with(module("androidx.core:core-ktx:(*, 1.3.2]"))
substitute(module("com.google.firebase:firebase-analytics-ktx")).with(module("com.google.firebase:firebase-analytics-ktx:19.0.0"))
}
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
I double checked if my package name in my AndroidManifest matched my ApplicationId in my build.gradle. I tried messing around with the SDK versions.
I tried disabling R8 so that it does not remove any Kotlin functionality during compression.
I tried adding the following to my build.gradle:
defaultConfig {
...
multiDexEnabled true
ndk {
abiFilters 'x86', 'armeabi-v7a'
}
}
But still no luck 🙁