Reputation: 2671
When I want to release a new flutter app bundle to the Playstore. I get this error: "This App Bundle contains native code, and you've not uploaded debug symbols. We recommend you upload a symbol file to make your crashes and ANRs easier to analyze and debug." I can't find any way to fix this. I'm new with flutter and releasing app's and getting a bit desperate... Any help would be fantastic.
When I add "android.defaultConfig.ndk.debugSymbolLevel = 'FULL'" (on line 1) to the app/build.gradle as suggested in https://developer.android.com/studio/preview/features#native-crash-symbolization. I get This error in the Android studio terminal. I use this command "flutter build appbundle".
Error in Terminal: FAILURE: Build failed with an exception.
Where: Build file 'C:\Users\filip\AndroidStudioProjects\ehbo\android\app\build.gradle' line: 1
What went wrong: A problem occurred evaluating project ':app'.
Could not get unknown property 'android' for project ':app' of type org.gradle.api.Project.
Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Get more help at https://help.gradle.org
BUILD FAILED in 3s Running Gradle task 'bundleRelease'... Running Gradle task 'bundleRelease'... Done 4,3s Gradle task bundleRelease failed with exit code 1
Upvotes: 266
Views: 180641
Reputation: 21
This is an update code from PravyNandas Tested in Android Studio Ladybug Feature Drop | 2024.2.2 Patch 2 with AGP version 8.8.2
Add it to build.gradle.kts(Module:app)
tasks.register<Zip>("zipNativeDebugSymbols") {
from("build/intermediates/merged_native_libs/release/mergeReleaseNativeLibs/out/lib")
exclude("armeabi*")
exclude("mips")
archiveFileName.set("native-debug-symbols.zip")
destinationDirectory.set(file("release"))
}
afterEvaluate {
tasks.named("bundleRelease") {
finalizedBy("zipNativeDebugSymbols")
}
}
This code defines a task zipNativeDebugSymbols to create a zip file of release debug symbols, excluding armeabi and mips architectures, and places it in the release directory.
It then configures the bundleRelease task to always run zipNativeDebugSymbols afterward, ensuring debug symbols are zipped after building the release bundle.
Upvotes: 0
Reputation: 2926
For Mac Users:
Go to build\app\intermediates\merged_native_libs\release\out\lib
inside your Flutter project, and compress the folders (arm64-v8a, armeabi-v7a, x86_64) into Archive.zip.
Then cd [into the folder that contains Archive.zip]
.
Then run the command
zip -d Archive.zip "__MACOSX*"
to get rid of the Mac __MACOSX files. Now upload it into the google play console. If not getting rid of the __MACOSX files, then google play console will give error on uploading -
"The native debug symbols contain an invalid directory __MACOSX"
Upvotes: 0
Reputation: 677
Update Jan, 2025.
As of today, Gabriel Logan's solution still works, but a small tweak is needed since play store is not accepting 'mips' and 'armeabi' folders. Notice the "exclude statements".
project/app/build.gradle:
tasks.register('zipNativeDebugSymbols', Zip) {
from 'build/intermediates/merged_native_libs/release/mergeReleaseNativeLibs/out/lib'
exclude 'armeabi*'
exclude 'mips'
archiveFileName = 'native-debug-symbols.zip'
destinationDirectory = file('build/outputs/bundle/release')
}
tasks.configureEach { task ->
if (task.name == 'bundleRelease') {
task.finalizedBy zipNativeDebugSymbols
}
}
Upvotes: 2
Reputation: 763
Following Gabriel's neat answer, I wanted to automate this process as well. However, that solution wasn't working for me. After two days of trial & error, I realized that that solution had in my case been silently failing (i.e. no errors logged) because the suggested from
and destinationDirectory
paths were different in my (Flutter) project. So if you are facing similar problems, the following is an expanded solution that adds some checks & logs, allowing you to easier isolate and address any issues specific to your setup now or in the future.
Note: mine is a Flutter project but the below solution should be similar in other projects.
v3.24.1
Android Studio
(didn't have to install the NDK & CMake tools)v8.5
macOS
android/app/build.gradle
fileNote: to learn about "tasks" in Gradle, check out the official docs. Also, in the below solution, as suggested by one of the comments in one of the other answers, I am checking for (and removing) some hidden files that are generated by macOS, in case you are on a Mac. That step seems redundant though when the zip is generated programmatically like I do in my solution, but I left it in as a precaution.
Add import java.nio.file.Paths
to the top of the android/app/build.gradle
file. Then add everything else after the flutter {...}
block here:
import java.nio.file.Paths
plugins {
...
}
android {
...
}
flutter {
source = "../.."
}
// STEP 1: Create and register the `zipNativeDebugSymbols` task to zip debug symbol files for manual upload to the Google Play store.
def zipNativeDebugSymbols = tasks.register('zipNativeDebugSymbols', Zip) {
// Optional: this sets some info about the task (to verify, run `./gradlew app:tasks` in the /android folder to see this task listed)
group = 'Build'
description = 'Zips debug symbol files for upload to Google Play store.'
// Set the input source directory (this is where the debug symbol files should be after the `bundleRelease` process has finished)
def libDir = file('../../build/app/intermediates/merged_native_libs/release/out/lib')
from libDir
// Include all subfiles and directories
include '**/*'
// Set the name for the output zip file
archiveFileName = 'native-debug-symbols.zip'
// Set the destination directory for the output zip file
def destDir = file('../../build/app/outputs/bundle/release')
destinationDirectory = destDir
doFirst {
// Ensure the paths are correct for the required directories and that they indeed were created / exist (the preceding task `bundleRelease` creates these directories)
checkDirectoryExists(libDir, 'Library directory')
checkDirectoryExists(destDir, 'Destination directory')
}
doLast {
println '✅ zipNativeDebugSymbols: created native-debug-symbols.zip file'
// Optional: if running on macOS, clean up unwanted files like '__MACOSX' and '.DS_Store' in the now created zip file
// The '__MACOSX' and '.DS_Store' files seem to be added only when manually creating ZIPs on macOS, not programmatically like here. Nevertheless, no harm in leaving this in as a precaution.
if (System.properties['os.name'].toLowerCase().contains('mac')) {
println ' running on Mac...'
// Combine destination path and zip file name
def zipPath = Paths.get(destinationDirectory.get().asFile.path, archiveFileName.get()).toString()
// Ensure the zip file exists
if (new File(zipPath).exists()) {
println " removing any '__MACOSX' and '.DS_Store' files from the zip..."
checkAndRemoveUnwantedFiles(zipPath, '__MACOSX*')
checkAndRemoveUnwantedFiles(zipPath, '*.DS_Store')
} else {
println '❌ zip file does not exist: $zipPath'
}
}
println '✅ zipNativeDebugSymbols: finished creating & cleaning native-debug-symbols.zip'
}
// Optional: force the task to run even if considered up-to-date
outputs.upToDateWhen { false }
println '✅ zipNativeDebugSymbols: task registered and configured'
}
// STEP 2: Configure the `zipNativeDebugSymbols` task to run after `bundleRelease`
tasks.whenTaskAdded { task ->
if (task.name == 'bundleRelease') {
// `finalizedBy` ensures `zipNativeDebugSymbols` runs after `bundleRelease` is complete
task.finalizedBy zipNativeDebugSymbols
}
}
//// ----------- HELPER METHODS -------------- ////
// Helper method to check if a directory exists
def checkDirectoryExists(File dir, String description) {
if (dir.exists()) {
println '✅ zipNativeDebugSymbols: found ${description} ${dir}'
} else {
println '❌ ${description} does not exist: ${dir}'
}
}
// Helper method to check for unwanted files and remove them
def checkAndRemoveUnwantedFiles(String zipPath, String pattern) {
def output = new ByteArrayOutputStream()
exec {
commandLine 'sh', '-c', "zipinfo $zipPath | grep '$pattern'"
standardOutput = output
errorOutput = new ByteArrayOutputStream()
ignoreExitValue = true
}
if (output.toString().trim()) {
println "✅ zipNativeDebugSymbols: found '$pattern' in the zip. Removing it..."
exec {
commandLine 'sh', '-c', "zip -d $zipPath '$pattern' || true"
}
}
}
flutter clean && flutter build appbundle
.def destDir = ...
. In my case, it is in [project_name]/build/app/outputs/bundle/release
. You should have two files in there: app-release.aab
and native-debug-symbols.zip
.app-release.aab
) to Google Play store.native-debug-symbols.zip
) as well. If you don't know how, follow the instructions here in the section Step 2: Upload a deobfuscation or symbolication file
.Voila! That is it. Hope this saves you days of scratching your head like I did.
In case you want to play around a little to understand Gradle and the above tasks better, here are some useful CLI commands. Note that they have to be run from your android/
directory. Also, for a Flutter project the base command here is ./gradlew
but I'm guessing it is e.g. just gradlew
for other projects.
./gradlew --help
displays all available commands./gradlew --version
displays what Gradle version you are using, i.e. what you have set in your android/gradle/wrapper/gradle-wrapper.properties
> distributionUrl=...
../gradlew tasks
lists all available Gradle tasks for the project (android/build.gradle
), showing which tasks can be executed../gradlew app:tasks
lists all available Gradle tasks specifically for the app module (android/app/build.gradle
)../gradlew clean
cleans the build directory by removing all generated files, forcing a fresh build the next time tasks are run. Note: flutter clean
achieves this as well../gradlew bundleRelease
builds the Android App Bundle (aab
) in release mode, which is the app bundle that you upload to Google Play../gradlew help --task bundleRelease
Displays detailed information about the bundleRelease
task, including its description, inputs, outputs, and other task properties../gradlew zipNativeDebugSymbols --rerun-tasks --quiet
runs the given task, e.g. the zipNativeDebugSymbols
here, forcing it to rerun all tasks without showing any output unless there are errors../gradlew zipNativeDebugSymbols --rerun-tasks --info
runs the given task, e.g. the zipNativeDebugSymbols
here, forcing it to rerun all tasks and displaying detailed information about the build process../gradlew --scan
creates a build scan with detailed performance and diagnostic data.Upvotes: 6
Reputation: 21
As skyllet already answered, this procedure works, if you want to automate the process so you don't have to do it manually every time
You can add this code below in android/app/build.gradle
task zipNativeDebugSymbols(type: Zip) {
from 'build/intermediates/merged_native_libs/release/mergeReleaseNativeLibs/out/lib'
archiveFileName = 'native-debug-symbols.zip'
destinationDirectory = file('build/outputs/bundle/release')
}
tasks.whenTaskAdded { task ->
if (task.name == 'bundleRelease') {
task.finalizedBy zipNativeDebugSymbols
}
}
Under dependencies at the end of your build.gradle
This will do what the guy showed, but automatically, and will send the zip along with the aab
Upvotes: 1
Reputation: 11
I created a windows batch file to build and zip the native libraries.
This DOES NOT work
Compress-Archive -Path .\build\app\intermediates\merged_native_libs\release\out\lib\* -DestinationPath .\native_symbols.zip
Using a 3rd party app works
C:\<your path>\7-Zip\7z.exe a native_symbols.zip .\build\app\intermediates\merged_native_libs\release\out\lib\*
The only difference I can see is that "Compress-Archive" discards the "a" archive file attribute.
Upvotes: 1
Reputation: 3041
Reproduce the next steps and this warning will disappear.
[YOUR_PROJECT]\build\app\intermediates\merged_native_libs\release\out\lib
For some the path might be
[YOUR_PROJECT]\app\build\....
and not[YOUR_PROJECT]\build\app\....
like mentioned above.
Note that 3 folders exist inside
[PLEASE NOTE THAT I HAVEN'T COMPRESSED THE ./lib FOLDER]
.
The newest update, for us (8-Nov 2023) the folder exists in [YOUR_PROJECT]\build\app\intermediates\merged_native_libs\release\out\lib
Upvotes: 280
Reputation: 1
My issue was this:
This App Bundle contains native code, and you've not uploaded debug symbols. We recommend you upload a symbol file to make your crashes and ANRs easier to analyze and debug.
Fix successfully just upload native debug symbols from the image reference directory shown.
Upvotes: -1
Reputation: 518
Instead of creating and uploading zip files, you can include the following to your app\build.gradle
file:
buildTypes {
debug {
// This is just here for local testing and is optional.
firebaseCrashlytics {
nativeSymbolUploadEnabled true
unstrippedNativeLibsDir file("build/app/intermediates/merged_native_libs/debug/out/lib")
}
ndk {
debugSymbolLevel 'SYMBOL_TABLE'
}
}
release {
// ..
firebaseCrashlytics { // Insert this
nativeSymbolUploadEnabled true
unstrippedNativeLibsDir file("build/app/intermediates/merged_native_libs/release/out/lib")
}
ndk {
// replace with 'FULL' if you need more info,
// but note that it will increase the file size of your appbundle dramatically.
debugSymbolLevel 'SYMBOL_TABLE'
}
}
}
Here is some documentation for reference: https://firebase.google.com/docs/crashlytics/ndk-reports#upload-symbols-external-dependencies
And if you're unclear about how to set up automatic uploading of native symbols, try adding this:
buildTypes { ... } // Your build types from the above snippet.
tasks.whenTaskAdded { task ->
if (task.name.startsWith('assemble') && task.name != "assembleReleaseAndroidTest"
&& task.name != "assembleDebugAndroidTest") {
String taskName = "uploadCrashlyticsSymbolFile" + task.name.substring('assemble'.length())
task.finalizedBy taskName
doFirst {
println "Running Gradle task '$taskName'..."
}
}
}
More info for building gradle tasks here: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html
Also, ensure that you have NDK and CMAKE installed in your IDE's SDK Manager.
Hope that helps!
Upvotes: 8
Reputation: 466
Simple approach, go to \build\app\intermediates\merged_native_libs\release\out\lib , you will find 3/4 folders , zip those , upload this ZIP from release option ( upload Symbol File ). Warning will be gone after bundle review.
Upvotes: 7
Reputation: 1052
I just upgraded ndk from 21.4.7075529 to 22.1.7171670, and now I get the debug symbols.
I'm using com.android.tools.build:gradle:7.1.1 and React Natvive 0.69 BTW.
Upvotes: 3
Reputation: 685
you can make these zip file by go to build\app\intermediates\merged_native_libs\release\out\lib
inside your Flutter project
and compress the folders into symbols.zip
, now upload it into the google play console
Upvotes: 30
Reputation: 1408
Before you can upload debug symbols files, you must be using Android Gradle plugin version 4.1 or higher.
Looks like it will come only with Android Studio 4.1, because I can only get Gradle 4.0.0 automatically now.
So I suggest you to return classic Play console and it will let you through :)
UPDATE: So just use an updated Gradle and add NDK debug symbols to the build now
Upvotes: 50
Reputation: 1408
If talking about Flutter, looks like the Flutter team needs to change some source files for the NDK, because it does not see where from to generate debug symbols.
Here is an issue thread: https://github.com/flutter/flutter/issues/60240
Setup steps are so:
Upvotes: 76
Reputation: 143
I had a similar problem. What really helped me:
ndkVersion <ndkVersion>
ndk {
debugSymbolLevel 'FULL'
}
to app/build.gradle
My final build.gradle
:
...
android {
compileSdkVersion 30
defaultConfig {
applicationId "com.example.app"
minSdkVersion 21
targetSdkVersion 30
versionCode 28
versionName "1.0.59"
ndkVersion "23.1.7779620"
ndk {
debugSymbolLevel 'FULL'
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
configurations {
compile.exclude group: 'com.google.zxing'
}
}
...
I hope this will help you and save you time
Upvotes: 10
Reputation: 777
For fixing it in the Visual Studio Code: you should first download the NDK from the android's website.
Extract the zip file to a folder named ndk
and place it under your - already installed - Android SDK folder. Like this: Android/sdk/ndk
Then open app/build.gradle
.
Under the Android
section. Add ndkPath
property as follows: ndkPath = <ndk-dir>
app/build.gradle ndkPath property
At the end of app/build.gradle
add android.buildTypes.release.ndk.debugSymbolLevel = 'full'
The next appbundle, built by flutter build appbundle
command should not give any errors on the play store about native debug symbols.
a more thorough explanation is here
Upvotes: 2
Reputation: 530
I was able to get Flutter to build native debug symbols using Android Gradle Plugin (AGP) 4.1.0, installing corresponding NDK version and adding the appropriate config to android/app/build.gradle
on macOS (but it should also work on Windows/Linux).
flutter build appbundle
and take note of the .aab
file sizeandroid/build.gradle
by looking in dependencies e.g. com.android.tools.build:gradle:4.1.0
is 4.1.0
4.1.0
the NDK version you want to install is 21.1.6352462
(for other AGP versions check mappings here)sdkmanager
and the CLI: $ANDROID_HOME/tools/bin/sdkmanager --install "ndk;21.1.6352462"
android/app/build.gradle
, under android.defaultConfig
add ndk { debugSymbolLevel 'FULL' }
aka set android.defaultConfig.ndk.debugSymbolLevel = 'FULL'
as per thisflutter build appbundle
. The .aab
should now contain native debug symbols and be larger than the previous build in step 0Troubleshooting: If you get any errors around CMake I didn't explicitly install it but you might need to, especially if you're using Windows, and you can do so using Android Studio.
Upvotes: 0
Reputation: 277
If you want to solve this warning error: This App Bundle contains native code, and you've not uploaded debug symbols. We recommend you upload a symbol file to make your crashes and ANRs easier to analyze and debug. Make sure also to install CMake
This will happen if your gradle version is higher than 4.0
Place this code into your build.gradle
file
android {
compileSdkVersion 28
defaultConfig {
applicationId 'com.example.myproject'
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0.0"
ndk {
debugSymbolLevel 'FULL'
}
}
Upvotes: 8
Reputation: 1033
I have the exact same issue.
Possible solutions:
Upvotes: 1
Reputation: 62419
The Answer was given by Shakle will be not useful as per the following message on Play Console.
The old version of Play Console will be discontinued from November 2, 2020 You’re already using the new Play Console, so you don’t need to do anything. A few features are going away if you want to check them one last time.
It's just a warning, nothing else. Just go ahead.
If you don't want any warning, Go to this link and follow the steps:
https://support.google.com/googleplay/android-developer/answer/9848633?hl=en
You can use the new version of the play store as it is.
Upvotes: 27