osm_flutter
osm_flutter copied to clipboard
ClassCastException and PlatformException
Looks similar to issue #115
I've upgraded from 0.26.0-rc.2 to 0.26.1
I'm running from Android Studio in debug mode, I've connected a mobile phone with Android 10. The map sometimes crashes completely (killing the app) and sometimes it's stable but a lot of error messages are printed.
It worked without issues on 0.26.0-rc.2. It is possible that this issue only happens in debug mode, I didn't try deploying a production apk to the phone.
I did flutter clean and I also deleted the local flutter cache.
Is there anything I can do to help? Can I enable additional debug logging somehow?
E/DRM/DcfDecoder(20709): decodeDrmImageIfNeeded stream caught ClassCastException
E/flutter (20709): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: PlatformException(404, Attempt to invoke virtual method 'org.osmdroid.views.MapViewRepository org.osmdroid.views.MapView.getRepository()' on a null object reference, java.lang.NullPointerException: Attempt to invoke virtual method 'org.osmdroid.views.MapViewRepository org.osmdroid.views.MapView.getRepository()' on a null object reference
E/flutter (20709): at org.osmdroid.views.overlay.infowindow.InfoWindow.<init>(InfoWindow.java:53)
E/flutter (20709): at org.osmdroid.views.overlay.infowindow.BasicInfoWindow.<init>(BasicInfoWindow.java:54)
E/flutter (20709): at org.osmdroid.views.overlay.infowindow.MarkerInfoWindow.<init>(MarkerInfoWindow.java:41)
E/flutter (20709): at org.osmdroid.views.MapViewRepository.getDefaultMarkerInfoWindow(MapViewRepository.java:55)
E/flutter (20709): at org.osmdroid.views.overlay.Marker.<init>(Marker.java:116)
E/flutter (20709): at org.osmdroid.views.overlay.Marker.<init>(Marker.java:93)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterMarker.<init>(FlutterMaker.kt:22)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterMarker.<init>(FlutterMaker.kt:55)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterOsmView.createMarker(FlutterOsmView.kt:691)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterOsmView.createMarker$default(FlutterOsmView.kt:690)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterOsmView.addMarker(FlutterOsmView.kt:622)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterOsmView.addMarker$default(FlutterOsmView.kt:611)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterOsmView.addMarkerManually(FlutterOsmView.kt:826)
E/flutter (20709): at hamza.dali.flutter_osm_plugin.FlutterOsmView.onMethodCall(FlutterOsmView.kt:456)
E/flutter (20709): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/flutter (20709): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:84)
E/flutter (20709): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:865)
E/flutter (20709): at android.os.MessageQueue.nativePollOnce(Native Method)
E/flutter (20709): at android.os.MessageQueue.next(MessageQueue.java:336)
E/flutter (20709): at android.os.Looper.loop(Looper.java:174)
E/flutter (20709): at android.app.ActivityThread.main(ActivityThread.java:7386)
E/flutter (20709): at java.lang.reflect.Method.invoke(Native Method)
E/flutter (20709): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/flutter (20709): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
E/flutter (20709): , null)
E/flutter (20709): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
E/flutter (20709): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:18)
E/flutter (20709): <asynchronous suspension>
E/flutter (20709): #2 MethodChannelOSM.addMarker (package:flutter_osm_interface/src/channel/osm_method_channel.dart:598:5)
E/flutter (20709): <asynchronous suspension>
E/flutter (20709): #3 MobileOSMController.addMarker.<anonymous closure> (package:flutter_osm_plugin/src/controller/osm/osm_controller.dart:443:9)
E/flutter (20709): <asynchronous suspension>
E/flutter (20709): #4 MobileOSMController.addMarker (package:flutter_osm_plugin/src/controller/osm/osm_controller.dart:442:7)
E/flutter (20709): <asynchronous suspension>
E/flutter (20709): #5 MapController.addMarker (package:flutter_osm_plugin/src/controller/map_controller.dart:273:5)
E/flutter (20709): <asynchronous suspension>
E/flutter (20709): #6 _MapPanelState._updateUserMarkerOnTheMap (package:nyomtass_te_is/screens/map/map_panel.dart:253:9)
E/flutter (20709): <asynchronous suspension>
E/flutter (20709):
can you provide scenario of that crash and part of your code ? because the lasts version 0.20+ doesn't support setState if you have it try to replace it with ValueNotifier or makethe map in parent widget separate from widget that show the information
you code crash in this method _updateUserMarkerOnTheMap
can you share it
Below is the sanitized version of the code. Let me know if you need the whole code (it might be difficult to read).
I have a Timer which calls the _updateUserMarkerOnTheMap() every 5 seconds. This method gets the current GPS position (based on the "location" package) and updates the marker on the map. The location of the marker is stored in the _lastLocation field. I can change this to a ValueNotifier if you think that will help.
// field inside the State object
LocationData? _lastLocation; // last place where this person was
// start a thread which updates the user's location every x seconds
onMapIsReady: (ready) {
if (_locationUpdater == null) {
developer.log("Starting location updater thread.");
_updateUserMarkerOnTheMap(); // update the first time
_locationUpdater = Timer.periodic(
Duration(seconds: settings.locationRefreshSec), _updateUserMarkerOnTheMap);
}
}
// this is the method which is invoked
Future<void> _updateUserMarkerOnTheMap([Timer? timer]) async {
var location = await _getCurrentLocation(); // GPS location from 'location' package
if (location != null) {
developer.log("Setting new location marker.");
if (_lastLocation != null) {
// remove previous marker so it looks like the person is moving
await _mapController.removeMarker(GeoPoint(
latitude: _lastLocation!.latitude!,
longitude: _lastLocation!.longitude!
));
} else {
await _mapController.goToLocation(GeoPoint(
latitude: location.latitude ?? 47.487016,
longitude: location.longitude ?? 19.057167));
await _mapController.setZoom(zoomLevel: 17);
}
// draw new marker
await _mapController.addMarker(GeoPoint( // this is line 253 from the stack trace
latitude: location.latitude ?? 47.487016,
longitude: location.longitude ?? 19.057167),
markerIcon: _osmMap.userLocationMarker?.personMarker
);
// set new location
_lastLocation = location;
final settings = context.read<Settings>();
if (_lastLocation != null && _lastLocation!.latitude != null && _lastLocation!.longitude != null) {
settings.updateLastLocation(_lastLocation!.latitude, _lastLocation!.longitude);
}
}
}
why you didn't use
await controller.currentLocation();
await controller.enableTracking();
you can listen to current location with callback in OSMFlutter onLocationChanged
i will add in the future some parameter to customizable get current user location
put _lastLocation in ValueNotifier because it make widget rebuild when that value change
or like i told you separate map widget from widget that responsible to show data
i will give later small example how to do it
Thank you @liodali I'll give it a try and let you know the results.
Moving the value into a ValueNotifier seems to have fixed the issue, thank you for your help.
I see another stack trace in the logs. It doesn't cause any errors, the marker is added correctly.
E/null (20407): java.lang.NullPointerException: Attempt to invoke virtual method 'org.osmdroid.views.MapViewRepository org.osmdroid.views.MapView.getRepository()' on a null object reference
E/null (20407): at org.osmdroid.views.overlay.infowindow.InfoWindow.<init>(InfoWindow.java:53)
E/null (20407): at org.osmdroid.views.overlay.infowindow.BasicInfoWindow.<init>(BasicInfoWindow.java:54)
E/null (20407): at org.osmdroid.views.overlay.infowindow.MarkerInfoWindow.<init>(MarkerInfoWindow.java:41)
E/null (20407): at org.osmdroid.views.MapViewRepository.getDefaultMarkerInfoWindow(MapViewRepository.java:55)
E/null (20407): at org.osmdroid.views.overlay.Marker.<init>(Marker.java:116)
E/null (20407): at org.osmdroid.views.overlay.Marker.<init>(Marker.java:93)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterMarker.<init>(FlutterMaker.kt:22)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterMarker.<init>(FlutterMaker.kt:55)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterOsmView.createMarker(FlutterOsmView.kt:691)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterOsmView.createMarker$default(FlutterOsmView.kt:690)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterOsmView.addMarker(FlutterOsmView.kt:622)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterOsmView.addMarker$default(FlutterOsmView.kt:611)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterOsmView.addMarkerManually(FlutterOsmView.kt:826)
E/null (20407): at hamza.dali.flutter_osm_plugin.FlutterOsmView.onMethodCall(FlutterOsmView.kt:456)
E/null (20407): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/null (20407): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:84)
E/null (20407): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:865)
E/null (20407): at android.os.MessageQueue.nativePollOnce(Native Method)
E/null (20407): at android.os.MessageQueue.next(MessageQueue.java:336)
E/null (20407): at android.os.Looper.loop(Looper.java:174)
E/null (20407): at android.app.ActivityThread.main(ActivityThread.java:7386)
E/null (20407): at java.lang.reflect.Method.invoke(Native Method)
E/null (20407): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/null (20407): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
D/BufferQueueProducer(20407): [SurfaceTexture-0-20407-2](this:0x7bb1af9800,id:2,api:1,p:606,c:20407) cancelBuffer: slot 0
D/BufferQueueProducer(20407): [SurfaceTexture-0-20407-2](this:0x7bb1af9800,id:2,api:1,p:606,c:20407) cancelBuffer: slot 0
D/Surface (20407): Surface::connect(this=0x7b849cf000,api=1)
D/Surface (20407): Surface::setBufferCount(this=0x7b849cf000,bufferCount=3)
D/Surface (20407): Surface::allocateBuffers(this=0x7b849cf000)
As I see it, in FlutterOsmView.kt we create a new FlutterMarker: https://github.com/liodali/osm_flutter/blob/ed7a9ea23da80b16a9148695ee5f03aa73773f1e/android/src/main/kotlin/hamza/dali/flutter_osm_plugin/FlutterOsmView.kt#L691
val marker = FlutterMarker(context, map!!, geoPoint)
and then this calls the FlutterMarker constructor: https://github.com/liodali/osm_flutter/blob/0ff439b10e99e67d2941641cc5ab3b0b43592135/android/src/main/kotlin/hamza/dali/flutter_osm_plugin/FlutterMaker.kt#L22
which then calls the InfoWindow constructor: https://github.com/osmdroid/osmdroid/blob/master/osmdroid-android/src/main/java/org/osmdroid/views/overlay/infowindow/InfoWindow.java#L53
which has this:
mMapView.getRepository().add(this);
It looks like the map!! passed in FlutterOsmView is null and this causes a NPE. I checked the code of FlutterOsmView and see this:
private fun initMap() {
map = mapView
but I don't see how is mapView set, so I don't understand why it was null.
i will make more investigation why that's happen, but what i know for now, that problem because map is reload it and we have another call use previous context of the map i will improve that,