Skip to content

[Bug]: MapView moveCamera() or setZoomLevel() not working in Android #531

@hamedhemmati

Description

@hamedhemmati

Is there an existing issue for this?

  • I have searched the existing issues

Description of the bug

moveCamera() and setZoomLevel() methods report success but do not actually change the camera position on Android. The camera remains at default position (lat: 0, lng: 0, zoom: 2).

Platform: Android only (iOS works correctly)
SDK Version: @googlemaps/react-native-navigation-sdk@0.13.0

Reproduction

const handleMapViewControllerCreated = async (controller) => {
  // This reports success but doesn't work
  await controller.moveCamera({
    target: { lat: 37.7749, lng: -122.4194 },
    zoom: 16
  });
  
  // Still returns default position
  const position = await controller.getCameraPosition();
  console.log(position); 
  // Android: { target: { lat: 0, lng: 0 }, zoom: 2 }
  // iOS: { target: { lat: 37.7749, lng: -122.4194 }, zoom: 16 }
};

What We've Tried

  • ✅ Calling in onMapViewControllerCreated
  • ✅ Calling in onMapReady
  • ✅ Calling in onLayout (after layout completes per Android SDK docs)
  • ✅ Various delays (100ms to 2s)
  • ✅ Using setZoomLevel() separately
  • ✅ Adding markers before calling moveCamera()

Console Output

Android (Broken):

✅ moveCamera() completed successfully
Actual position: { target: { lat: 0, lng: 0 }, zoom: 2 }

iOS (Working):

✅ moveCamera() completed successfully  
Actual position: { target: { lat: 37.7749, lng: -122.4194 }, zoom: 16 }

Impact

Cannot set initial camera positions or programmatically navigate the map on Android.

Related

  • Android SDK Camera Docs - Native SDK supports this
  • Methods exist and can be called without errors, but have no effect

React Native version

0.82.0

React version

19.1.1

Package version

0.13.0

Native SDK versions

  • I haven't changed the version of the native SDKs

React Native Doctor Output

✓ Node.js - Required to execute JavaScript code
✓ yarn - Required to install NPM dependencies
✓ Watchman - Used for watching changes in the filesystem when in development mode
✓ Metro - Required for bundling the JavaScript code

Android
✓ Adb - Required to verify if the android device is attached correctly
✓ JDK - Required to compile Java code
✓ Android Studio - Required for building and installing your app on Android
✓ ANDROID_HOME - Environment variable that points to your Android SDK installation
✓ Gradlew - Build tool required for Android builds
✓ Android SDK - Required for building and installing your app on Android

iOS
✓ Xcode - Required for building and installing your app on iOS
✓ Ruby - Required for installing iOS dependencies
✓ CocoaPods - Required for installing iOS dependencies
✓ .xcode.env - File to customize Xcode environment

Errors: 0
Warnings: 0

Steps to reproduce

  1. Create a MapView component using @googlemaps/react-native-navigation-sdk
  2. In onMapViewControllerCreated, call controller.moveCamera() with a target location (e.g., San Francisco: lat 37.7749, lng -122.4194, zoom 16)
  3. After the map loads, call controller.getCameraPosition() to verify the camera position
  4. Result: On Android, the camera position remains at default { target: { lat: 0, lng: 0 }, zoom: 2 } instead of the specified location
  5. Expected: Camera should move to the specified location (works correctly on iOS)

Expected vs Actual Behavior

Expected Behavior:
moveCamera() should move the camera to the specified location and zoom level
getCameraPosition() should return the new camera position matching the parameters passed to moveCamera()
The map should visually display the specified location (e.g., San Francisco) instead of the default globe view
Behavior should match iOS, where moveCamera() works correctly
Actual Behavior:
moveCamera() completes without errors (no exceptions thrown, Promise resolves if applicable)
getCameraPosition() returns the default position: { target: { lat: 0, lng: 0 }, zoom: 2 } instead of the requested position
The map visually shows the default globe view (centered at 0,0 with zoom level 2)
setZoomLevel() also reports success but does not change the zoom level
This issue occurs only on Android; iOS works correctly
Error Messages/Logs:
No errors are thrown. The methods report success but have no effect:
[TestMapView] Map controller created[TestMapView] ✅ Initial camera set to San Francisco (37.7749, -122.4194) at zoom 16[TestMapView] Map ready[TestMapView] ✅ Camera FORCED in onMapReady to San Francisco (37.7749, -122.4194) at zoom 16[TestMapView] Current camera position: { "target": { "lng": 0, "lat": 0 }, "zoom": 2, "tilt": 0, "bearing": 0}
Android Logcat: No relevant errors found. The methods execute without exceptions.

Code Sample

import React, { useState, useCallback } from 'react';
import { View, StyleSheet, Platform, Text } from 'react-native';
import { MapView } from '@googlemaps/react-native-navigation-sdk';

const TestMapView = () => {
  const [mapViewController, setMapViewController] = useState(null);
  const [cameraPosition, setCameraPosition] = useState(null);

  const handleMapViewControllerCreated = useCallback(async (controller) => {
    console.log('[TestMapView] Map controller created');
    setMapViewController(controller);

    // Attempt to set camera to San Francisco
    try {
      console.log('[TestMapView] Calling moveCamera()...');
      const result = controller.moveCamera({
        target: {
          lat: 37.7749,
          lng: -122.4194
        },
        zoom: 16
      });

      // Handle both Promise and non-Promise returns
      if (result && typeof result.then === 'function') {
        await result;
        console.log('[TestMapView] moveCamera() Promise resolved');
      } else {
        console.log('[TestMapView] moveCamera() called (No Promise)');
      }

      // Wait a moment for camera to update
      await new Promise(resolve => setTimeout(resolve, 1000));

      // Verify camera position
      const position = await controller.getCameraPosition();
      console.log('[TestMapView] Actual camera position:', JSON.stringify(position, null, 2));
      setCameraPosition(position);

      // On Android: position.target.lat = 0, position.target.lng = 0, position.zoom = 2
      // On iOS: position.target.lat = 37.7749, position.target.lng = -122.4194, position.zoom = 16
    } catch (err) {
      console.error('[TestMapView] Error:', err);
    }
  }, []);

  const onMapReady = useCallback(async () => {
    if (mapViewController) {
      console.log('[TestMapView] Map ready - attempting moveCamera again...');
      
      // Try again after map is ready
      try {
        await mapViewController.moveCamera({
          target: { lat: 37.7749, lng: -122.4194 },
          zoom: 16
        });
        
        const position = await mapViewController.getCameraPosition();
        console.log('[TestMapView] Position after onMapReady:', position);
        setCameraPosition(position);
      } catch (err) {
        console.error('[TestMapView] Error in onMapReady:', err);
      }
    }
  }, [mapViewController]);

  return (
    <View style={styles.container}>
      <View style={styles.infoContainer}>
        <Text style={styles.text}>Platform: {Platform.OS}</Text>
        <Text style={styles.text}>
          Camera Position: {cameraPosition 
            ? `lat: ${cameraPosition.target.lat}, lng: ${cameraPosition.target.lng}, zoom: ${cameraPosition.zoom}`
            : 'Not set'}
        </Text>
        <Text style={styles.text}>
          Expected: lat: 37.7749, lng: -122.4194, zoom: 16
        </Text>
        <Text style={styles.text}>
          {Platform.OS === 'android' 
            ? '❌ Android: Shows default position (0, 0, zoom 2)'
            : '✅ iOS: Works correctly'}
        </Text>
      </View>
      <View style={styles.mapContainer}>
        <MapView
          style={styles.map}
          mapViewCallbacks={{ onMapReady }}
          onMapViewControllerCreated={handleMapViewControllerCreated}
        />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  infoContainer: {
    padding: 16,
    backgroundColor: '#fff'
  },
  text: {
    fontSize: 14,
    marginBottom: 4
  },
  mapContainer: {
    flex: 1
  },
  map: {
    flex: 1
  }
});

export default TestMapView;

Additional Context

No response

Metadata

Metadata

Labels

triage meI really want to be triaged.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions