mapbox / mapbox-maps-flutter

Interactive, thoroughly customizable maps for Flutter powered by Mapbox Maps SDK
https://www.mapbox.com/mobile-maps-sdk
Other
281 stars 112 forks source link

[Android] Location updates causing crash when using play-services-location version 21 #74

Closed ivan-ljubicic closed 1 year ago

ivan-ljubicic commented 1 year ago

Description

When using for example com.google.android.gms:play-services-location:21.0.1 or when it is a dependency from a third party package, the following error is thrown and it crashes the application.

E/Mapbox  ( 1612): [LiveTrackingClient]: Failed to start: java.lang.IncompatibleClassChangeError: Found interface com.google.android.gms.location.FusedLocationProviderClient, but class was expected (declaration of 'com.google.android.gms.location.FusedLocationProviderClient' appears in /data/app/com.example.mapbox_maps_test-7IZ9JsQGR15uGtnut8xVGQ==/base.apk)
E/Mapbox  ( 1612): [telemetry]: Unable to start location collection: Unknown(Found interface com.google.android.gms.location.FusedLocationProviderClient, but class was expected (declaration of 'com.google.android.gms.location.FusedLocationProviderClient' appears in /data/app/com.example.mapbox_maps_test-7IZ9JsQGR15uGtnut8xVGQ==/base.apk))

Reproduction steps

  1. Copy the following code to main.dart file
import 'package:flutter/material.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late final MapboxMap _map;
  bool _hasLocationPermission = false;

  void _mapCreated(MapboxMap map) {
    _map = map;
    _map.location.updateSettings(LocationComponentSettings(
      enabled: true,
      showAccuracyRing: true,
      puckBearingEnabled: true,
    ));
  }

  @override
  void initState() {
    super.initState();
    Permission.location.request().then((status) {
      if(status.isGranted) {
        setState(() {
          _hasLocationPermission = true;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Mapbox Example')),
        body: _hasLocationPermission ? MapWidget(
          resourceOptions: ResourceOptions(accessToken: <add access token>),
          onMapCreated: _mapCreated,
        ) : const SizedBox(),
      ),
    );
  }
}
  1. Add dependencies for maps, permission handler for requesting location permission, and geolocator which is using mentioned play-services-location:
dependencies:
  geolocator: ^9.0.2
  permission_handler: ^10.2.0
  mapbox_maps_flutter: ^0.4.0
  1. Add the following in AndroidManifest.xml

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  2. When app is run allow location permission and try enabling/disabling gps service which will eventually lead to crash.

Solution

Upgrading mapbox.maps dependency to v10.10.0 in which this is resolved.

yunikkk commented 1 year ago

Hi @LjubiTech-Maxko, thanks for notice, it's indeed incompatible binary Google play services update 20->21 which was worked around in 10.10 of Maps. I'll bump Maps version to the latest before the patch release.