flutterdartgoogle-mapscameraunhandled-exception

Google map camera error : unhandled Exception: MissingPluginException(No implementation found for method camera#animate


I was implementing google maps in flutter my everything worked fine until I get this error,

The direction flow of the app is : login => Mappage =>dashboard => Mappage

after login, the map page works fine but when going to the dashboard and coming back again to the map page it shows this error :

unhandled Exception: MissingPluginException(No implementation found for method camera#animate on channel plugins.flutter.dev/google_maps_android_0)

I am using the animateCamera method in my code many times but it worked the first time (Mappage after login ) is this because of completer ? please explain

here is my code :

Mappage.dart :

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

import '../../StateManagement/MapController.dart';
import '../../drawers/bottomnavbar.dart';

class Mappage extends StatelessWidget {
   const Mappage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    MapController mapcontroller = Get.find();
    return Scaffold(
        body: Stack(
          children: [
            SizedBox(height: MediaQuery.of(context).size.height,
              child: SingleChildScrollView(
                child: SizedBox(height: MediaQuery.of(context).size.height,width: MediaQuery.of(context).size.width,
                  child: Column(
                    children: [
                      Stack(
                        children: [
                          SizedBox(
                            height: MediaQuery.of(context).size.height,
                            child: GetBuilder<MapController>(builder: (_)=>GoogleMap(initialCameraPosition:MapController.initial,
                              mapType: MapType.normal,markers:mapcontroller.markers,
                                onMapCreated: (GoogleMapController controller){
                                mapcontroller.completercontrol.complete(controller);
                                mapcontroller.googleMapController = controller;
                              },),)
                          ),
                          Positioned(
                            bottom: 50,
                            width: MediaQuery.of(context).size.width,
                            child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
                              children: [
                                ElevatedButton(
                                    style:const ButtonStyle(backgroundColor:MaterialStatePropertyAll(Colors.redAccent)) ,
                                    onPressed: () {
                                      Get.offAll(()=>Nav());
                                    },
                                    child:const Text('Go to Dashboard',style: TextStyle(color: Colors.white),)),
                                FloatingActionButton(
                                    onPressed: () {
                                      mapcontroller.getlatlong();
                                    },
                                    child:const Icon(Icons.location_on,color: Colors.white,)),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),
            GetBuilder<MapController>(builder: (_){
              if (mapcontroller.isloading == true) {
                return Container(
                  color: Colors.white.withOpacity(0.5),
                  child: const Center(
                    child: CircularProgressIndicator(backgroundColor: Colors.redAccent,color: Colors.white,),
                  ),
                );
              } else {
                return const SizedBox.shrink();
              }
            }),
          ],
        ));
  }
}

mapcontroller (using getx):

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class MapController extends GetxController{
  String locationmessage = 'currentlocation of user';
  late String lat ;
  late String long ;

  Set<Marker>markers={};

  @override
  void onInit() {
    lat = '10.228370';
    long ='76.198799';
    super.onInit();
  }

  late GoogleMapController googleMapController;

  final Completer<GoogleMapController> _controller = Completer();
  Completer<GoogleMapController> get completercontrol => _controller;

  static  CameraPosition initial =  const CameraPosition(target:LatLng(10.228370,76.198799),zoom: 15);

  //lower part

  Future<Position> getCurrentLocation() async {
    bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      return Future.error('the location is not enabled');
    }
    LocationPermission permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        return Future.error(
            'location permissions are permanantly denied, cannot grant acess');
      }
    }
    if (permission == LocationPermission.deniedForever) {
      return Future.error(
          'location permissions are permanantly denied, cannot grant acess');
    }
    return await Geolocator.getCurrentPosition();
  }

  void liveLocation() {
    loadingbar();
    LocationSettings settings = const LocationSettings(
      accuracy: LocationAccuracy.high,
      distanceFilter: 100,
    );
    Geolocator.getPositionStream(locationSettings: settings)
        .listen((Position position) {
      lat = position.latitude.toString();
      long = position.longitude.toString();
      googleMapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(target:LatLng(position.latitude,position.longitude),zoom: 15)));
      markers.clear();
      markers.add(Marker(markerId:const MarkerId('current user location'),position: LatLng(position.latitude,position.longitude)));
      update();
    });
    loadingbaroff();
  }

  void getlatlong(){
    loadingbar();
    getCurrentLocation().then((value){
      lat = '${value.latitude}';
      long = '${value.longitude}';
      googleMapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(target:LatLng(value.latitude,value.longitude),zoom: 15)));
      markers.clear();
      markers.add(Marker(markerId:const MarkerId('current user location'),position: LatLng(value.latitude,value.longitude)));
      update();
      if (kDebugMode) {
        print(lat);
      }
      if (kDebugMode) {
        print(long);
      }
      liveLocation();
    });
    loadingbaroff();
  }

  void liveLocationToUpload(){
    LocationSettings settings = const LocationSettings(
      accuracy: LocationAccuracy.high,
      distanceFilter: 100,
    );
    Geolocator.getPositionStream(locationSettings: settings)
        .listen((Position position) {
      lat = position.latitude.toString();
      long = position.longitude.toString();
      update();
    });
  }

  //MAP PAGE CONTROLLER CONTROLLS :::::::::::::;

  Future<void> fetchMap()async {
    //markers.clear();
    //markers.add(Marker(markerId:const MarkerId('current user location'),position: LatLng(position.latitude,position.longitude)));
  }





  bool isloading = false;

  void loadingbar() {
    isloading = true;
    update();
  }
  void loadingbaroff() {
    isloading = false;
    update();
  }

}

Solution

  • so after getting all errors and doing flutter clean and pub get I couldn't solve the issue finally I figured it out and it was simple :

    In my code, you can see that I used a completer (on the GoogleMap widget and on the map controller ) but that is an outdated approach most of the tutorials still have that code now the right thing to do here is ignore the completer we do not want to use the completer for google maps

    instead, just use GoogleMapController only like this

     GetBuilder<MapController>(builder: (_)=>GoogleMap(initialCameraPosition:MapController.initial,
                                  mapType: MapType.normal,markers:mapcontroller.markers,
                                    onMapCreated: (GoogleMapController controller){
                                        mapcontroller.markers.clear();
                                        mapcontroller.googleMapController = controller;
                                        mapcontroller.liveLocation();
                                  },),
                                )
    

    in map controller :

    late GoogleMapController googleMapController;
    static  CameraPosition initial =  const CameraPosition(target:LatLng(10.228370,76.198799),zoom: 15);