Debugging and troubleshooting
In this section you can find effective debugging and troubleshooting techniques, common issues, and instructions how to generate insightful logs.
Common issues
When you run into trouble, be sure to check first the minimum requirements, supported devices, and the list of known issues in the changelog.
- Unsupported Flutter version. If your current Flutter version does not match the supported versions, you may experience an error when building the app. When you need to downgrade, it is recommended to specify the desired Flutter version. Navigate to your Flutter installation directory and execute
git checkout <supported-flutter-version>and thenflutter doctor. Then navigate to your app directory and make sure to runflutter cleanbefore rebuilding your project. - Xcode does not compile my project for simulators. I am using a computer with a M1 chip. You are using a HERE SDK version below 4.9.2.0. Try to use a newer HERE SDK version or run in Rosetta mode by excluding the ARM64 architecture for "Any iOS Simulator SDK" in the
Build Settings/Architectures/Excluded Architectures/Debugsetting within Xcode. Select this option in the "TARGETS" settings. Note that this may slightly slow down the performance when running the simulator. - I see only a blank white map: Make sure that your HERE credentials are valid and set as described in the Get started section. Also, make sure that your device is able to make an internet connection. With slower internet connections, it may take a while until you see the first map tiles loaded. Please also make sure that your device time is set correctly. In rare cases, a wrongly set device time can lead to authentication issues with some backend services.
- I see only a blank white map and logs show "Could not create root isolate.": This issue is unrelated to the HERE SDK and it may happen after you tried to downgrade to an older Flutter version. Try to clean your Flutter installation with:
$ rm -rf path/to/flutter/sdk/bin/cache/artifacts/engine/ios*
$ flutter clean
$ flutter run
- In the logs I see "ios/Runner/GeneratedPluginRegistrant.m:12:9: Module 'here_sdk' not found": This may be related to this Flutter issue. Try to clean the project and podfile like so, then build again:
$ flutter clean
$ rm ios/Podfile && flutter build ios
- In the logs I see "No map content will be displayed until valid config is provided.": Make sure that your code is really calling
loadScene(). - The app crashes and in the logs I see "CL_magma - Couldn't load the default shader.": Your device must support OpenGL ES 3.0. If you are running a simulator, edit your emulator settings via Settings -> Advanced -> ES OpenGLAPI level. If it is set to "Autoselect", try to change it to "Renderer Maximum". This happens mostly on Windows machines.
- I see a blank map after reopening an app on Android Emulator: This is a known issue with Android Emulator 34.2.14 and 34.2.13. Please use Android Emulator 34.1.20 or earlier from the stable channel until Google fixes the issue. Sometimes, this issue may also appear with Android emulators using an image with API Level 28.
- I see visual glitches or the map does not load with Flutter 3.27.x: When building apps with Flutter 3.27.x, UI glitches may occasionally appear, and in rare cases, the map view may fail to load. This issue is caused by Flutter's new
Impellerrendering engine, which is enabled by default and affects only certain Android and iOS devices. As a workaround switch to Flutter's legacySkiarendering engine instead ofImpeller. Information on how to disableImpellercan be found here. - I am getting "No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi": This happens when you have a NDK version installed that is incompatible with the Gradle version of your app. Either uninstall or downgrade your NDK version or change the Gradle classpath to a newer version. For example, change the classpath from:
classpath 'com.android.tools.build:gradle:3.5.4'toclasspath 'com.android.tools.build:gradle:4.1.3'. - I am seeing the following in a crash log: "Exception was thrown in Java and it was not handled.": The HERE SDK cannot handle runtime exceptions that are thrown on app side inside a callback. In such a case you will see this error log. It means that your code throws an exception in one of the HERE SDK callbacks that are handled by your application.
- I am getting a crash due to a cache lock: If an application crashes due to a
Storage.LevelDBerror or aFAILED_TO_LOCK_CACHE_FOLDERerror, follow this instruction to prevent such a crash from happening again. - I see a gray screen: If the logs repeatedly say "dequeueBuffer failed", then this is caused by a Flutter issue that might get fixed by a new Flutter version, eventually Flutter 1.20.3.
- I see no map and/or my HERE SDK calls do nothing: If you see the following log message "These credentials do not authorize access" then your credentials are not valid. Make sure you use a working set of credentials. Credentials from the 3.x versions are not compatible. Credentials from Explore are not compatible with Navigate.
- I see graphical glitches on the map view: For some Android versions this may happen and it can be fixed by using the
MapRenderMode.texture. Find more details in the maps guide. - I see graphical glitches on the map view after screen orientation changes and the map tiles don't show up: For some Android versions this may happen and it can be fixed by using Flutter's Hybrid Composition render mode. Find more details in the maps guide.
- When I build for iOS release, the build fails: If you see in the logs that
-embed-bitcodeis executed, make sure to explicitly disable bitcode optimization. Apple deprecated bitcode and the HERE SDK no longer supports it. AddENABLE_BITCODE = NOto your config. For example, in yourios/Podfileadd the following:
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
- On exiting app with back button,
HereMapwidget on Android turns blank on resume: The user exits the app using back button on Android while the map is displayed, and on resuming the app, the map turns blank. This issue is observed on Flutter v3.22.0 (on Android 6, Android 14). This Flutter issue has been fixed in Flutter 3.22.2. - Android Studio does not compile my app and I get this build error Your project's Gradle version is incompatible with the Java version that Flutter is using for Gradle. Such an error can happen when you are switching to a newer Android Studio version. Either build a new app from scratch following the Get started guide, or update Gradle via
gradle-wrapper-propertiesby setting a newerdistributionURLand update AGP viasettings.gradleby setting a newerid "com.android.application" versionin your project's settings. Make sure that the AGP plugin and Gradle versions do match. - When I compile for release I get an error regarding R8: The error may look like "Missing classes detected while running R8". Such a message is a known AGP issue for newer Android Gradle Plugin versions. The example apps show how to fix this in two steps. First, add four new
dontwarnexclusions to<your_app_dir>/android/app/proguard-rules.pro. If the file does not exist, create it. Secondly, use that file in<your_app_dir>/android/app/build.gradlelike shown here underbuildTypes.release. - During turn-by-turn navigation the screen seems to freeze: (only applicable for Navigate) When using the
VisualNavigatoron selected Google phones, you can use theMapRenderMode.texturerendering mode to prevent the screen from freezing or displaying visual glitches. Note that this is not the default rendering mode. By default, the map view usesMapRenderMode.surface. However, thetexturemode may not be appropriate for all use cases. For example, if your app requires fast rendering updates, consider to use the hybrid composition mode viaHereMap(NativeViewMode.hybridComposition). For more information, see the Flutter documentation. - I see graphical glitches and the log message "Modifying properties of a view's layer off the main thread is not allowed": Flutter version 3.24.x for iOS suffers from a bug that can interfere with map rendering. This bug produces the aforementioned log and references
FlutterViewandFlutterViewController. When this happens, there is a risk of corruption in the displayed map and UI elements, potentially leading to graphical glitches or, in the worst case, rendering the app completely unresponsive and unusable. The likelihood of corruption increases with higher GPU load. This issue is not present in Flutter version 3.27.0 and later. - Platform view stops rendering after screen lock/unlock on Android: When using a platform view with virtual-display mode on top of an Android
SurfaceView(for example, OpenGL ES rendering), the view may turn black or stop updating after locking/unlocking the screen or returning from background on Android 13–15 with Flutter 3.32.0 and later. Changing screen orientation may temporarily recover rendering. As a workaround, use hybrid composition, which is not affected. More details can be found in the Flutter issue #172641. - Why does the map freeze or stop updating during navigation in Flutter apps? Freezes are often linked to Flutter version mismatches, hybrid composition, or background/foreground lifecycle transitions. Most often, downgrading or aligning Flutter versions with the supported HERE SDK versions will resolve the issue. More version information here. Alternatively, use an
AppLifecycleListeneras shown in the example apps or utilize theMapViewLifecycleListener. - How should offline maps be handled to avoid large updates and storage spikes? When using the Navigate license, you can query installed
Regionswith theMapDownloaderto monitor downloaded regions, estimate update sizes, and avoid unnecessary downloads. Try to compare existing region sizes before triggering updates. If you want more control, avoid automatic updates. You can find more information here.
How to destroy a locking process
In rare cases an application using the HERE SDK may crash due to a Storage.LevelDB error or the initialization of the HERE SDK may fail with a failedToLockCacheFolder error.
This may happen when a second instance of a SDKNativeEngine is created with the same access_key_id as an existing one. Then the local map cache directory is locked by the current process.
This locked cache folder crash can be fixed by setting the following option before initializing the HERE SDK:
AuthenticationMode authenticationMode = AuthenticationMode.withKeySecret(accessKeyId, accessKeySecret);
SDKOptions sdkOptions = SDKOptions.withAuthenticationMode(authenticationMode);
// Defaults to SDKOptions.ActionOnCacheLock.waitLockingAppFinish.
sdkOptions.actionOnCacheLock = SDKOptionsActionOnCacheLock.killLockingApp;
// Now, use these options to initialize the HERE SDK and destroy a locking process (if any).
try {
await SDKNativeEngine.makeSharedInstance(sdkOptions);
} on InstantiationException {
throw Exception("Failed to initialize the HERE SDK.");
}If there is a cache lock, this will kill the locking process and the app can start normally. If no cache lock occurred, the code will only initialize the HERE SDK. Beside killLockingApp, also the following values can be set:
noAction: Nothing will be done.waitLockingAppFinish: The app will wait until the locking process has ended. Note that this may happen never. This is the default behavior.
Alternatively, the following snippet can be used to detect and to prevent the cache lock issue. This has the same effect as killLockingApp as makeSharedInstance() calls internally destroyLockingProcess() when this flag is set, but it provides more flexibility:
// Check if there is a lock on the cache.
Integer processID = LockingProcess.getLockingProcessId(sdkOptions);
if (processID != null) {
// Warning: The cache is locked.
// This may kill another process that is trying to attempt to lock the current map cache.
// If this happens, the method will try to gracefully repair the cache.
// If no problem was detected, the method will do nothing.
long maxTimeoutInMilliseconds = 300;
LockingProcess.destroyLockingProcess(sdkOptions, maxTimeoutInMilliseconds);
}
// Now, proceed to initialize the HERE SDK.getLockingProcessId() provides the process ID of the locking process from the Android OS. If no lock occurred, the method will return null.
By calling destroyLockingProcess() the problem will be gone. You can keep this code to solve sporadic crashes at application start. If no cache lock is detected, destroyLockingProcess() will do nothing.
Specify the log level
The LogControl class allows to log HERE SDK messages for various predefined LogLevel values - even for release builds of your app. Make sure to call the LogControl after calling SdkContext.init(IsolateOrigin.main) and before initializing the HERE SDK:
// Disable any logs from HERE SDK.
LogControl.disableLoggingToConsole();The above allows to silence all HERE SDK related console logs. Note that this is not recommended for debug builds, as you may miss important log messages when you want to investigate issues.
A log level can be specified like so:
LogControl.enableLoggingToConsole(LogLevel.logLevelInfo);When you provide a LogLevel, you set a minimal level of messages which will be reported, based on the below hierarchy:
logLevelInfologLevelWarninglogLevelErrorlogLevelFatal
For example, if you set logLevelError, then logLevelInfo and logLevelWarning will be excluded from the logs. All others will be logged.
Setting logLevelOff silences all logs.
All log messages are prefixed with "hsdk-" to help you easily identify messages originating from the HERE SDK.
You can also use the LogAppender interface to insert your own logging class to the LogControl class. This enables you to filter log messages based on different runtime conditions. For instance, you could choose to log only errors of type logLevelError. By default, this selective logging isn’t possible, as only the log hierarchy determines which messages are allowed through, and you cannot adjust this minimum level after initializing the HERE SDK. By adding your own logging class, however, you gain complete control.
When running an iOS simulator, you can obtain logs without running Xcode by executing the following command from the terminal:
xcrun simctl spawn booted log stream --level debug
Generate Meaningful Logs on Android
For many issues, the logs you see in your IDE's console are containing already the most relevant information. For crashes and ANRs you may want to dig deeper and take a look at the device logs. When you use logcat, use a timestamp to log only the most recent logs.
Example:
adb logcat -t '06-30 16:30:00.820' > /Users/name/Desktop/log.txt
Preferably, use adb logcat -c to clear all logs before starting to reproduce the issue.
Generate Meaningful Logs on iOS
For many issues, the logs you see in Xcode are containing already the most relevant information. For crashes and ANRs you may want to dig deeper and take a look at the device logs:
- Open Xcode and connect the device.
- In Xcode click on the top-level menu bar tab for Window.
- Tap on Device and Simulation.
- Tap on View Device Logs - or in newer Xcode versions tap on Open Recent Logs or Open Console.
Symbolication of Android crash logs with Google Play Console
For apps that are deployed to Google Play Store you must upload the symbols files for each version of your app to get the crash reports as follows:
- Open Google Play Console and open your app.
- On the left menu, select Release -> App bundle explorer.
- Using the picker in the top-right-hand corner, choose the ZIP archive with debug symbols.
- Select the Downloads tab, and scroll down to the Assets section.
- Click the upload arrow for the debug symbols as applicable to upload the symbols file for the version of your app. See here for more details.
- Afterwards, crashes and ANRs will be deobfuscated. To view deobfuscated stack traces for individual crashes and ANRs on your app, go to your Crashes & ANRs page in the Google Play Console.
Symbolication of Android crash logs can be done also locally
Follow the below steps to symbolicate a native crash locally:
- Use Logcat or ADB, gather the crash log and save it to a .txt file:
adb logcat -d > your_crashlog_filename.txt
- Get the symbols
.sofile that we ship with the release package. You can find these.sofiles insidedebug-symbolsZIP file. - Depending upon your build architecture copy the file path, either
arm64-v8aorarmeabi-v7a. - Run the
ndk-stacktool command :
path-to-Andorid-sdk/Android/sdk/ndk/24.0.8215888/ndk-stack -sym path-to-directory-with-binary-of-desired-architecture -dump path-to-crash.txt
Note that for this release, please use NDK 24.0.8215888.
Updated yesterday