I am learning Fllutter to build a map based App. I am using the location pub.dev plugin for managing location permissions.
I have created a Location() object Location location = Location()
and when I call
await location.hasPermission()
and I don't have granted permission , it actually requests the permission , without me calling
await location.requestPermission()
This causes many problems , such as asking two permissions at once , something not permitted by Android , so the app crashes , or by removing await location.requestPermission()
, the app ask for the user's permission but it does not wait for the result.
I tested it on my Pixel 5 via adb , running Android 12
What is going on? I have not found another reference of this issue.
Here is the full Code Sample:
class Gmap extends StatefulWidget {
const Gmap({ Key? key }) : super(key: key);
@override
State<Gmap> createState() => _GmapState();
}
class _GmapState extends State<Gmap> {
String _mapStyle = "";
late GoogleMapController mapController;
late Future<LatLng> ull ;
Location location = Location();
final LatLng _center = const LatLng(37.983810, 23.727539);
LatLng _userLocation = const LatLng(37.983810, 23.727539);
Future<LatLng> userLocation() async{
PermissionStatus _permissionGranted;
bool _serviceEnabled;
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return _center;
}
}
_permissionGranted = await location.hasPermission(); //it requests permission here
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission()//it requests here again;
if (_permissionGranted != PermissionStatus.granted) {
return _center;
}
}
LocationData l = await location.getLocation();
setState((){
_userLocation = LatLng(l.latitude!, l.longitude!);
});
return _userLocation;
}
void centerLocation(){
CameraPosition userCamera = CameraPosition(
target: _userLocation,
zoom: 14.0,
);
CameraUpdate moveTo = CameraUpdate.newCameraPosition(userCamera);
mapController.animateCamera(moveTo);
}
void _onMapCreated(GoogleMapController controller) async{
mapController = controller;
mapController.setMapStyle(_mapStyle);
centerLocation();
}
@override
void initState() {
super.initState();
rootBundle.loadString('assets/style.txt').then((string) {
_mapStyle = string;
});
ull = userLocation();
}
Widget googleMap(userLocation){
return GoogleMap(
onMapCreated: _onMapCreated,
myLocationEnabled:true,
initialCameraPosition: CameraPosition(
target: userLocation,
zoom: 6.0,
),
zoomControlsEnabled: false, //dont show zoom buttons
compassEnabled: false,
myLocationButtonEnabled: false,
);
}
@override
Widget build(BuildContext context){
return Scaffold(
body: FutureBuilder<LatLng>(
future: ull,
builder: ( context , AsyncSnapshot<LatLng> snapshot){
Widget g;
if(snapshot.hasData){
g = googleMap(_userLocation);
}else if(snapshot.hasError){
g = googleMap(_center);
}else{
g = googleMap(_center);
}
return g;
}
),
floatingActionButton: Column(mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
primary: ourGreen,
shape: const CircleBorder(),
padding: const EdgeInsets.all(15),),
child: const Icon(Icons.filter_alt_rounded, size: 27, color: ourDark),),
const SizedBox(height: 9),
ElevatedButton(
onPressed: () {centerLocation(); },
style: ElevatedButton.styleFrom(
primary: const Color(0xFF1A202C),
shape: const CircleBorder(),
padding: const EdgeInsets.all(15)),
child: const Icon(Icons.location_on,
size: 27, color: Colors.greenAccent)),
]),
);
}
}
Update: I never got this to work for some reason following the documentation or the other comments. Here is what worked for me:
Future<LatLng> askPermissionAndGetLocation() async {
if (await Permission.locationWhenInUse.serviceStatus.isEnabled) { //this here checks
//if the permission is granted and if not , it requests it.
if (await Permission.location.request().isGranted) {
LocationData l = await Location().getLocation();
setState(() {
_userLocation = LatLng(l.latitude!, l.longitude!);
});
return _userLocation;
}
}
return Future.error("Location services disabled or restricted");
}
This is the only way I got it to work and I do not see a reason why. If anyone has any insight please leave a comment