I am trying to get the user's location from within my app by requesting for permission(shows dialog correctly) and navigating only if granted. Library being used permission_handler
in flutter. I am unable to get the location widget from the settings tile menu to turn on and permission status from library is showing permission.disabled
.
I have opened the settings tile programmatically for my app and it's listed and active like below block:
void _requestPerms () async{
Map<PermissionGroup, PermissionStatus> statuses = await PermissionHandler().requestPermissions([
PermissionGroup.locationWhenInUse, PermissionGroup.locationAlways
]);
final status = statuses[PermissionGroup.locationWhenInUse];
switch(status){
case PermissionStatus.disabled:
await PermissionHandler().openAppSettings();
break;
}
_updateStatus(status);
}
Can someone help me understand why despite getting the dialog prompt once, the phone location widget is not turning on and how to navigate to next route on condition of permission granted
or exit the app gracefully if not. Thanks.
Full Code:
import 'package:flutter/material.dart';
import 'package:eme_clone/utils/styles.dart';
import 'package:eme_clone/utils/constants.dart';
import 'package:permission_handler/permission_handler.dart';
class LocationDialog extends StatefulWidget {
@override
_LocationDialogState createState() => _LocationDialogState();
}
class _LocationDialogState extends State<LocationDialog> {
PermissionStatus _status;
@override
void initState() {
super.initState();
PermissionHandler().checkPermissionStatus(PermissionGroup.locationWhenInUse)
.then(_updateStatus);
}
@override
Widget build(BuildContext context) {
debugPrint('Location Status $_status');
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Image.asset('assets/images/perm_icon_location.png'),
Text(
locationDialogHeader,
style: locationHeaderStyle,
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
locationDialogBody,
textAlign: TextAlign.center,
style: locationTextBodyStyle,
),
),
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
width: double.infinity,
padding: EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.black,
onPressed: _requestPerms,
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: Text(
allow,
style: allowBtnTextStyle,
),
),
),
),
)
],
)),
);
}
void _updateStatus(PermissionStatus value) {
setState(() {
_status = value;
});
}
void _requestPerms () async{
Map<PermissionGroup, PermissionStatus> statuses = await PermissionHandler().requestPermissions([
PermissionGroup.locationWhenInUse, PermissionGroup.locationAlways
]);
final status = statuses[PermissionGroup.locationWhenInUse];
switch(status){
case PermissionStatus.disabled:
await PermissionHandler().openAppSettings();
break;
}
_updateStatus(status);
}
}
Thanks for the full code. It made the debug process faster.
First, you need to add the following to your android/app/src/main/AndroidManifest.xml file. (Before tag)
<!-- Permissions options for the `location` group -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Then, you can use the flutter_spinkit to build an initial loading screen while waiting for user permission. To exit the app if a user doesn't grant permission, use
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
To navigate to the next screen after the request is granted, checkout your modified full code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LocationDialog(),
);
}
}
class LocationDialog extends StatefulWidget {
@override
_LocationDialogState createState() => _LocationDialogState();
}
class _LocationDialogState extends State<LocationDialog>
with SingleTickerProviderStateMixin {
PermissionStatus _status;
@override
void initState() {
runFirst();
super.initState();
}
runFirst() async {
//await PermissionHandler()
// .checkPermissionStatus(PermissionGroup.locationWhenInUse)
// .then(_updateStatus);
/* PermissionHandle() deprecated in permission_handler: ^5.0.0+hotfix.3 */
await Permission.locationWhenInUse.status.then(_updateStatus);
await _requestPerms();
if (_status == PermissionStatus.granted) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => NextPage()));
} else if (_status == PermissionStatus.denied) {
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
}
}
@override
Widget build(BuildContext context) {
return SpinKitFadingCircle(
itemBuilder: (BuildContext context, int index) {
return DecoratedBox(
decoration: BoxDecoration(
color: index.isEven ? Colors.red : Colors.green,
),
);
},
);
}
void _requestPerms() async {
Map<Permission, PermissionStatus> statuses = await
[
Permission.locationWhenInUse,
Permission.locationAlways
].request();
if (await Permission.locationWhenInUse.serviceStatus.isEnabled) {
_updateStatus(PermissionStatus.enable);
openAppSettings();
}
// switch (status) {
// case PermissionStatus.disabled:
// await PermissionHandler().
// break;
// }
// _updateStatus(status);
// }
void _updateStatus(PermissionStatus value) {
setState(() {
_status = value;
});
}
}
class NextPage extends StatefulWidget {
@override
_NextPageState createState() => _NextPageState();
}
class _NextPageState extends State<NextPage> {
PermissionStatus _status;
@override
Widget build(BuildContext context) {
debugPrint('Location Status $_status');
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Image.asset('assets/images/perm_icon_location.png'),
Text(
"LocationDialogHelper",
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
"locationDialogBody",
textAlign: TextAlign.center,
),
),
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
width: double.infinity,
padding: EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.black,
onPressed: _requestPerms,
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: Text(
"allow",
style: TextStyle(color: Colors.white),
),
),
),
),
)
],
)),
);
}
void _requestPerms() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.locationWhenInUse,
Permission.locationAlways,
].request();
final status = Permission.locationWhenInUse.serviceStatus;
_updateStatus(status);
// switch (status) {
// case PermissionStatus.disabled:
// await PermissionHandler().openAppSettings();
// break;
// }
// _updateStatus(status);
// }
void _updateStatus(PermissionStatus value) {
setState(() {
_status = value;
});
}
}
Note:
A lot of breaking changes with the permission_handler: ^5.0.0+hotfix.3