“Why does my Flutter app display Google Maps with incorrect styling and fail to load the user’s position despite requesting permissions, but only when launched on Pixel 7 and later devices, not on earlier versions?”
Thanks in advance for any response
I tried reinstalling the simulator and increasing the minumSdk but it didn’t help. I really don’t know what to do.
<code>`import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import '../../models/attractions.dart';
import 'package:firebase_storage/firebase_storage.dart';
import '../../UI/app_theme.dart';
import '../../UI/theme_provider.dart';
import 'dart:ui' as ui;
import 'dart:async';
import 'package:image/image.dart' as Img;
class AttractionMap extends StatefulWidget {
final List<Attraction> attractions;
final String languageCode; // Aggiungi questo parametro
const AttractionMap(
{super.key, required this.attractions, required this.languageCode});
@override
State<AttractionMap> createState() => _AttractionMapState();
}
class _AttractionMapState extends State<AttractionMap> {
late GoogleMapController mapController;
late String _mapStyle;
final Set<Marker> _markers = {};
Position? _currentPosition;
bool _isLoading = true; // Variabile per gestire il caricamento
@override
void initState() {
super.initState();
_loadMapStyle();
_loadMarkers();
_requestLocationPermission();
}
Future<void> _loadMapStyle() async {
try {
String style = await rootBundle.loadString('assets/map_style.json');
setState(() {
_mapStyle = style;
print('Map style loaded');
});
} catch (e) {
print('Error loading map style: $e');
}
}
Future<void> _loadMarkers() async {
for (Attraction attraction in widget.attractions) {
BitmapDescriptor bitmapDescriptor =
BitmapDescriptor.defaultMarker; // Default Google Maps marker
if (attraction.attractionImage != null &&
attraction.attractionImage!.isNotEmpty) {
try {
// Correctly encode the URL if necessary
String encodedUrl = Uri.encodeFull(attraction.attractionImage!);
FirebaseStorage storage = FirebaseStorage.instance;
var ref = storage.refFromURL(encodedUrl);
// Download data directly
final bytes = await ref.getData();
if (bytes != null) {
final resizedBytes = await _resizeImage(Uint8List.fromList(bytes),
200, 200); // Adjust the width and height as needed
bitmapDescriptor = BitmapDescriptor.fromBytes(resizedBytes);
}
} catch (e) {
print("Error downloading image from Firebase Storage: $e");
// If there's an error, bitmapDescriptor remains the default Google Maps marker
}
}
final marker = Marker(
markerId: MarkerId(attraction.getAttractionName(
widget.languageCode)), // Usa il metodo e il parametro languageCode
position: LatLng(attraction.latitude, attraction.longitude),
infoWindow: InfoWindow(
title: attraction.getAttractionName(
widget.languageCode), // Usa il metodo e il parametro languageCode
snippet: attraction.getAttractionDetails(
widget.languageCode), // Usa il metodo e il parametro languageCode
),
icon: bitmapDescriptor,
);
setState(() {
_markers.add(marker);
});
}
await _addUserLocationMarker();
}
Future<void> _requestLocationPermission() async {
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
if (permission != LocationPermission.always &&
permission != LocationPermission.whileInUse) {
print('Location permission denied');
return;
}
}
await _updateUserLocation();
}
Future<void> _updateUserLocation() async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
print('User position: ${position.latitude}, ${position.longitude}');
setState(() {
_currentPosition = position;
});
await _addUserLocationMarker();
} catch (e) {
print('Unable to retrieve user's location: $e');
}
}
Future<void> _addUserLocationMarker() async {
if (_currentPosition != null) {
final userIcon = await _getUserLocationIcon();
final marker = Marker(
markerId: const MarkerId('user'),
position:
LatLng(_currentPosition!.latitude, _currentPosition!.longitude),
icon: userIcon,
infoWindow: const InfoWindow(title: 'Your Location'),
);
setState(() {
_markers.add(marker);
});
}
}
Future<BitmapDescriptor> _getUserLocationIcon() async {
final ByteData bytes = await rootBundle.load('assets/icona_user.png');
final Img.Image image = Img.decodeImage(Uint8List.view(bytes.buffer))!;
final Img.Image resizedImage =
Img.copyResize(image, width: 230, height: 230);
final resizedImageData = Img.encodePng(resizedImage);
return BitmapDescriptor.fromBytes(resizedImageData);
}
Future<Uint8List> _resizeImage(Uint8List data, int width, int height) async {
ui.Codec codec = await ui.instantiateImageCodec(data,
targetWidth: width, targetHeight: height);
ui.FrameInfo fi = await codec.getNextFrame();
ui.Image image = fi.image;
final ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
return byteData!.buffer.asUint8List();
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
mapController.setMapStyle(_mapStyle);
setState(() {
_isLoading = false; // La mappa è caricata
print('Map created and style applied');
});
}
Future<void> _centerMapOnUser() async {
if (_currentPosition != null) {
mapController.animateCamera(CameraUpdate.newLatLngZoom(
LatLng(_currentPosition!.latitude, _currentPosition!.longitude),
15, // Livello di zoom
));
}
}
@override
Widget build(BuildContext context) {
return ThemeProvider(builder: (BuildContext context, AppTheme theme) {
ColorTheme colorTheme = theme.colorTheme;
return Scaffold(
body: Stack(
children: [
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(
widget.attractions.first.latitude,
widget.attractions.first.longitude,
),
zoom: 17,
tilt: 70,
),
markers: _markers,
),
if (_isLoading) // Mostra il CircularProgressIndicator se _isLoading è true
const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white)),
),
Positioned(
top: 16,
right: 16,
child: FloatingActionButton(
backgroundColor: colorTheme.primary,
onPressed: _centerMapOnUser,
child: const Icon(Icons.my_location, color: Colors.white),
),
),
],
),
);
});
}
}`
</code>
<code>`import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import '../../models/attractions.dart';
import 'package:firebase_storage/firebase_storage.dart';
import '../../UI/app_theme.dart';
import '../../UI/theme_provider.dart';
import 'dart:ui' as ui;
import 'dart:async';
import 'package:image/image.dart' as Img;
class AttractionMap extends StatefulWidget {
final List<Attraction> attractions;
final String languageCode; // Aggiungi questo parametro
const AttractionMap(
{super.key, required this.attractions, required this.languageCode});
@override
State<AttractionMap> createState() => _AttractionMapState();
}
class _AttractionMapState extends State<AttractionMap> {
late GoogleMapController mapController;
late String _mapStyle;
final Set<Marker> _markers = {};
Position? _currentPosition;
bool _isLoading = true; // Variabile per gestire il caricamento
@override
void initState() {
super.initState();
_loadMapStyle();
_loadMarkers();
_requestLocationPermission();
}
Future<void> _loadMapStyle() async {
try {
String style = await rootBundle.loadString('assets/map_style.json');
setState(() {
_mapStyle = style;
print('Map style loaded');
});
} catch (e) {
print('Error loading map style: $e');
}
}
Future<void> _loadMarkers() async {
for (Attraction attraction in widget.attractions) {
BitmapDescriptor bitmapDescriptor =
BitmapDescriptor.defaultMarker; // Default Google Maps marker
if (attraction.attractionImage != null &&
attraction.attractionImage!.isNotEmpty) {
try {
// Correctly encode the URL if necessary
String encodedUrl = Uri.encodeFull(attraction.attractionImage!);
FirebaseStorage storage = FirebaseStorage.instance;
var ref = storage.refFromURL(encodedUrl);
// Download data directly
final bytes = await ref.getData();
if (bytes != null) {
final resizedBytes = await _resizeImage(Uint8List.fromList(bytes),
200, 200); // Adjust the width and height as needed
bitmapDescriptor = BitmapDescriptor.fromBytes(resizedBytes);
}
} catch (e) {
print("Error downloading image from Firebase Storage: $e");
// If there's an error, bitmapDescriptor remains the default Google Maps marker
}
}
final marker = Marker(
markerId: MarkerId(attraction.getAttractionName(
widget.languageCode)), // Usa il metodo e il parametro languageCode
position: LatLng(attraction.latitude, attraction.longitude),
infoWindow: InfoWindow(
title: attraction.getAttractionName(
widget.languageCode), // Usa il metodo e il parametro languageCode
snippet: attraction.getAttractionDetails(
widget.languageCode), // Usa il metodo e il parametro languageCode
),
icon: bitmapDescriptor,
);
setState(() {
_markers.add(marker);
});
}
await _addUserLocationMarker();
}
Future<void> _requestLocationPermission() async {
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
if (permission != LocationPermission.always &&
permission != LocationPermission.whileInUse) {
print('Location permission denied');
return;
}
}
await _updateUserLocation();
}
Future<void> _updateUserLocation() async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
print('User position: ${position.latitude}, ${position.longitude}');
setState(() {
_currentPosition = position;
});
await _addUserLocationMarker();
} catch (e) {
print('Unable to retrieve user's location: $e');
}
}
Future<void> _addUserLocationMarker() async {
if (_currentPosition != null) {
final userIcon = await _getUserLocationIcon();
final marker = Marker(
markerId: const MarkerId('user'),
position:
LatLng(_currentPosition!.latitude, _currentPosition!.longitude),
icon: userIcon,
infoWindow: const InfoWindow(title: 'Your Location'),
);
setState(() {
_markers.add(marker);
});
}
}
Future<BitmapDescriptor> _getUserLocationIcon() async {
final ByteData bytes = await rootBundle.load('assets/icona_user.png');
final Img.Image image = Img.decodeImage(Uint8List.view(bytes.buffer))!;
final Img.Image resizedImage =
Img.copyResize(image, width: 230, height: 230);
final resizedImageData = Img.encodePng(resizedImage);
return BitmapDescriptor.fromBytes(resizedImageData);
}
Future<Uint8List> _resizeImage(Uint8List data, int width, int height) async {
ui.Codec codec = await ui.instantiateImageCodec(data,
targetWidth: width, targetHeight: height);
ui.FrameInfo fi = await codec.getNextFrame();
ui.Image image = fi.image;
final ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
return byteData!.buffer.asUint8List();
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
mapController.setMapStyle(_mapStyle);
setState(() {
_isLoading = false; // La mappa è caricata
print('Map created and style applied');
});
}
Future<void> _centerMapOnUser() async {
if (_currentPosition != null) {
mapController.animateCamera(CameraUpdate.newLatLngZoom(
LatLng(_currentPosition!.latitude, _currentPosition!.longitude),
15, // Livello di zoom
));
}
}
@override
Widget build(BuildContext context) {
return ThemeProvider(builder: (BuildContext context, AppTheme theme) {
ColorTheme colorTheme = theme.colorTheme;
return Scaffold(
body: Stack(
children: [
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(
widget.attractions.first.latitude,
widget.attractions.first.longitude,
),
zoom: 17,
tilt: 70,
),
markers: _markers,
),
if (_isLoading) // Mostra il CircularProgressIndicator se _isLoading è true
const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white)),
),
Positioned(
top: 16,
right: 16,
child: FloatingActionButton(
backgroundColor: colorTheme.primary,
onPressed: _centerMapOnUser,
child: const Icon(Icons.my_location, color: Colors.white),
),
),
],
),
);
});
}
}`
</code>
`import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import '../../models/attractions.dart';
import 'package:firebase_storage/firebase_storage.dart';
import '../../UI/app_theme.dart';
import '../../UI/theme_provider.dart';
import 'dart:ui' as ui;
import 'dart:async';
import 'package:image/image.dart' as Img;
class AttractionMap extends StatefulWidget {
final List<Attraction> attractions;
final String languageCode; // Aggiungi questo parametro
const AttractionMap(
{super.key, required this.attractions, required this.languageCode});
@override
State<AttractionMap> createState() => _AttractionMapState();
}
class _AttractionMapState extends State<AttractionMap> {
late GoogleMapController mapController;
late String _mapStyle;
final Set<Marker> _markers = {};
Position? _currentPosition;
bool _isLoading = true; // Variabile per gestire il caricamento
@override
void initState() {
super.initState();
_loadMapStyle();
_loadMarkers();
_requestLocationPermission();
}
Future<void> _loadMapStyle() async {
try {
String style = await rootBundle.loadString('assets/map_style.json');
setState(() {
_mapStyle = style;
print('Map style loaded');
});
} catch (e) {
print('Error loading map style: $e');
}
}
Future<void> _loadMarkers() async {
for (Attraction attraction in widget.attractions) {
BitmapDescriptor bitmapDescriptor =
BitmapDescriptor.defaultMarker; // Default Google Maps marker
if (attraction.attractionImage != null &&
attraction.attractionImage!.isNotEmpty) {
try {
// Correctly encode the URL if necessary
String encodedUrl = Uri.encodeFull(attraction.attractionImage!);
FirebaseStorage storage = FirebaseStorage.instance;
var ref = storage.refFromURL(encodedUrl);
// Download data directly
final bytes = await ref.getData();
if (bytes != null) {
final resizedBytes = await _resizeImage(Uint8List.fromList(bytes),
200, 200); // Adjust the width and height as needed
bitmapDescriptor = BitmapDescriptor.fromBytes(resizedBytes);
}
} catch (e) {
print("Error downloading image from Firebase Storage: $e");
// If there's an error, bitmapDescriptor remains the default Google Maps marker
}
}
final marker = Marker(
markerId: MarkerId(attraction.getAttractionName(
widget.languageCode)), // Usa il metodo e il parametro languageCode
position: LatLng(attraction.latitude, attraction.longitude),
infoWindow: InfoWindow(
title: attraction.getAttractionName(
widget.languageCode), // Usa il metodo e il parametro languageCode
snippet: attraction.getAttractionDetails(
widget.languageCode), // Usa il metodo e il parametro languageCode
),
icon: bitmapDescriptor,
);
setState(() {
_markers.add(marker);
});
}
await _addUserLocationMarker();
}
Future<void> _requestLocationPermission() async {
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
if (permission != LocationPermission.always &&
permission != LocationPermission.whileInUse) {
print('Location permission denied');
return;
}
}
await _updateUserLocation();
}
Future<void> _updateUserLocation() async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
print('User position: ${position.latitude}, ${position.longitude}');
setState(() {
_currentPosition = position;
});
await _addUserLocationMarker();
} catch (e) {
print('Unable to retrieve user's location: $e');
}
}
Future<void> _addUserLocationMarker() async {
if (_currentPosition != null) {
final userIcon = await _getUserLocationIcon();
final marker = Marker(
markerId: const MarkerId('user'),
position:
LatLng(_currentPosition!.latitude, _currentPosition!.longitude),
icon: userIcon,
infoWindow: const InfoWindow(title: 'Your Location'),
);
setState(() {
_markers.add(marker);
});
}
}
Future<BitmapDescriptor> _getUserLocationIcon() async {
final ByteData bytes = await rootBundle.load('assets/icona_user.png');
final Img.Image image = Img.decodeImage(Uint8List.view(bytes.buffer))!;
final Img.Image resizedImage =
Img.copyResize(image, width: 230, height: 230);
final resizedImageData = Img.encodePng(resizedImage);
return BitmapDescriptor.fromBytes(resizedImageData);
}
Future<Uint8List> _resizeImage(Uint8List data, int width, int height) async {
ui.Codec codec = await ui.instantiateImageCodec(data,
targetWidth: width, targetHeight: height);
ui.FrameInfo fi = await codec.getNextFrame();
ui.Image image = fi.image;
final ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
return byteData!.buffer.asUint8List();
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
mapController.setMapStyle(_mapStyle);
setState(() {
_isLoading = false; // La mappa è caricata
print('Map created and style applied');
});
}
Future<void> _centerMapOnUser() async {
if (_currentPosition != null) {
mapController.animateCamera(CameraUpdate.newLatLngZoom(
LatLng(_currentPosition!.latitude, _currentPosition!.longitude),
15, // Livello di zoom
));
}
}
@override
Widget build(BuildContext context) {
return ThemeProvider(builder: (BuildContext context, AppTheme theme) {
ColorTheme colorTheme = theme.colorTheme;
return Scaffold(
body: Stack(
children: [
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(
widget.attractions.first.latitude,
widget.attractions.first.longitude,
),
zoom: 17,
tilt: 70,
),
markers: _markers,
),
if (_isLoading) // Mostra il CircularProgressIndicator se _isLoading è true
const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white)),
),
Positioned(
top: 16,
right: 16,
child: FloatingActionButton(
backgroundColor: colorTheme.primary,
onPressed: _centerMapOnUser,
child: const Icon(Icons.my_location, color: Colors.white),
),
),
],
),
);
});
}
}`
New contributor
FbrStudio is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.