I was asked permission from the user in runtime but I need to ask MULTIPLE permissions for example phone, contact, SMS, etc so I'm stuck on that how to call this method one after another is there any way to ask after one permission completed another popup open?
import 'package:permission_handler/permission_handler.dart';
class PermissionService{
final PermissionHandler _permissionHandler = PermissionHandler();
Future<bool> _requestPermissionContact(PermissionGroup permission) async {
var result = await _permissionHandler.requestPermissions([permission]);
if (result[PermissionGroup.contacts] == PermissionStatus.granted) {
print("sfhalsjfhas fasdhufaiusfh aloifahdf oalsifu");
}
}
Future<bool> requestContactPermission({Function onPermissionDenied}) async {
var granted = await _requestPermissionContact(PermissionGroup.contacts);
if (!granted) {
onPermissionDenied();
}
return granted;
}
Future<bool> hasContactPermission() async {
return hasPermission(PermissionGroup.contacts);
}
Future<bool> _requestPermissionSms(PermissionGroup permission) async {
var result = await _permissionHandler.requestPermissions([permission]);
if (result[permission] == PermissionStatus.granted) {
print("sfhalsjfhas fasdhufaiusfh aloifahdf oalsifu");
return true;
}
return false;
}
Future<bool> requestSmsPermission({Function onPermissionDenied}) async {
var granted = await _requestPermissionSms(PermissionGroup.sms);
if (!granted) {
onPermissionDenied();
}
return granted;
}
Future<bool> hasSmsPermission() async {
_requestPermissionPhone(PermissionGroup.phone);
return hasPermission(PermissionGroup.sms);
}
Future<bool> _requestPermissionPhone(PermissionGroup permission) async {
var result = await _permissionHandler.requestPermissions([permission]);
if (result[permission] == PermissionStatus.granted) {
return true;
}
return false;
}
Future<bool> requestPhonePermission({Function onPermissionDenied}) async {
var granted = await _requestPermissionPhone(PermissionGroup.phone);
if (!granted) {
onPermissionDenied();
}
return granted;
}
Future<bool> hasPhonePermission() async {
return hasPermission(PermissionGroup.phone);
}
Future<bool> hasPermission(PermissionGroup permission) async {
var permissionStatus =
await _permissionHandler.checkPermissionStatus(permission);
return permissionStatus == PermissionStatus.granted;
}
}
this is my permission class i want to call this three permission and in initState i was called this like
#override
initState() {
permissionAcess();
permissionAcessSms();
permissionAcessPhone();
super.initState();
}
Future permissionAcess() {
PermissionService().requestContactPermission(onPermissionDenied: () {
print('Permission has been denied');
});
}
Future permissionAcessSms() {
PermissionService().requestSmsPermission(onPermissionDenied: () {
print('Permission has been denied');
});
}
Future permissionAcessPhone() {
PermissionService().requestPhonePermission(onPermissionDenied: () {
print('Permission has been denied');
});
}
but it called only one permission so how to call all these three permission in runtime?
yes you can ask multiple permission at same time just update your code like this
your PermissionServices file will be
import 'package:permission_handler/permission_handler.dart';
class PermissionService{
final PermissionHandler _permissionHandler = PermissionHandler();
Future<bool> _requestPermission() async {
var result = await _permissionHandler.requestPermissions([PermissionGroup.phone,PermissionGroup.contacts,PermissionGroup.sms]);
if (result == PermissionStatus.granted) {
return true;
}
return false;
}
Future<bool> requestPermission({Function onPermissionDenied}) async {
var granted = await _requestPermission();
if (!granted) {
onPermissionDenied();
}
return granted;
}
Future<bool> hasPhonePermission() async {
return hasPermission(PermissionGroup.phone);
}
Future<bool> hasPermission(PermissionGroup permission) async {
var permissionStatus =
await _permissionHandler.checkPermissionStatus(permission);
return permissionStatus == PermissionStatus.granted;
}
}
and your initState will be
#override
initState(){
permissionAcessPhone();
super.initState();
}
Future permissionAcessPhone() {
PermissionService().requestPermission(onPermissionDenied: () {
print('Permission has been denied');
});
}
In earliar version of permission handler we can hande multiple permission at a same time permission_handler 10.2.0
List<Permission> statuses = [
Permission.location,
Permission.camera,
Permission.sms,
Permission.storage,
];
Future<void> requestPermission() async {
try {
for (var element in statuses) {
if ((await element.status.isDenied ||
await element.status.isPermanentlyDenied)) {
await statuses.request();
}
}
} catch (e) {
debugPrint('$e');
} finally {
await requestPermission();
}
}
#override
void initState() {
requestPermission();
super.initState();
}
Related
All the available solutions online tell me one thing: downgrade permission_handler. But how can I update this code so I can keep the current version of permission_handler?
The code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
UserProvider auth = Provider.of<UserProvider>(context);
// Check if the location permission has been granted
_checkLocationPermission() async {
PermissionStatus permission = await Permission.location.status;
if (permission != PermissionStatus.granted) {
// Location permission is not granted, request it
Map<PermissionGroup, PermissionStatus> permissions =
await PermissionHandler()
.requestPermissions([PermissionGroup.location]);
if (permissions[PermissionGroup.location] != PermissionStatus.granted) {
// Location permission was denied
return false;
}
}
return true;
}
switch (auth.status) {
case Status.Uninitialized:
return Splash();
case Status.Unauthenticated:
case Status.Authenticating:
return LoginScreen();
case Status.Authenticated:
// Request location permission before showing the home screen
return FutureBuilder(
future: _checkLocationPermission(),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data) {
// Location permission was granted
return MyHomePage();
} else {
// Location permission was denied or is still being checked
return Container();
}
},
);
default:
return LoginScreen();
}
}
}
I'm working with emailJs flutter package and for some reason the code gets called just the first time after app launch. Subsequent calls to the function does nothing.
I need it to run as much as I call the function in the app
Here is the code
final EmailJS emailJS = EmailJS();
#override
void initState() {
super.initState();
getPermission().then((value) async {
void sendMail() async {
EmailJS.send(
'****',
'***',
{
'user_subject': 'From xenox forge',
'from': sender,
'message': sms,
'time': time,
'reply_to': 'email#mail'
},
Options(
publicKey: 'my key',
privateKey: 'my key',
),
);
}
if (value) {
_plugin.read();
_plugin.smsStream.listen((event) async {
sms = event.body;
sender = event.sender;
time = event.timeReceived.toString();
sendMail();
});
}
});
}
Future<bool> getPermission() async {
if (await Permission.sms.status == PermissionStatus.granted) {
return true;
} else {
if (await Permission.sms.request() == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}
#override
void dispose() {
super.dispose();
_plugin.dispose();
}
i have been trying to solve this error , after i login i was getting type 'Null' is not a subtype of type 'String' for about 5 seconds and after that the app successfully login, i do not know why this happen, i already add null check to the User but i still get the error . Below is my code, tell me if you need more info, Thanks for helping
class _controState extends State<contro> {
_controState();
User? user = FirebaseAuth.instance.currentUser;
UserModel loggedInUser = UserModel();
var role;
var email;
var id;
#override
void initState() {
super.initState();
FirebaseFirestore.instance
.collection("users") //.where('uid', isEqualTo: user!.uid)
.doc(user!.uid)
.get()
.then((value) {
this.loggedInUser = UserModel.fromMap(value.data());
}).whenComplete(() {
CircularProgressIndicator();
setState(() {
email = loggedInUser.email.toString();
role = loggedInUser.role.toString();
id = loggedInUser.uid.toString();
});
});
}
routing() {
if (role == 'Freelancer') {
return JobScreen(
id: id,
);
} else {
return JobScreenClient(
id: id,
);
}
}
#override
Widget build(BuildContext context) {
CircularProgressIndicator();
return routing();
}
}
inside your routing, role might be null before FirebaseFirestore's result get ready, try this:
routing() {
if(role == null){
return Container(); // show empty widget like this or what widget you want
}else if (role == 'Freelancer') {
return JobScreen(
id: id,
);
} else {
return JobScreenClient(
id: id,
);
}
}
You have to add async/await to your code, because it's future functions..
void initState() async {
super.initState();
await FirebaseFirestore.instance
.collection("users") //.where('uid', isEqualTo: user!.uid)
.doc(user!.uid)
.get()
.then((value) {
this.loggedInUser = UserModel.fromMap(value.data());
}).whenComplete(() {
CircularProgressIndicator();
setState(() {
email = loggedInUser.email.toString();
role = loggedInUser.role.toString();
id = loggedInUser.uid.toString();
});
});
}
routing() {
if(role == null){
return const Center(child: CircularProgressIndicator());
}else if (role == 'Freelancer') {
return JobScreen(
id: id,
);
} else {
return JobScreenClient(
id: id,
);
}
}
I am building an application, and I would like to show a progress bar while the user is waiting to be logged-in in the platform.
How can I add a circle progress bar while I am awaiting?
Future<void> validateAndSubmit() async {
if (validateAndSave()) {
try {
final Auth auth = await AuthFactory.getAuth();
final String userId = await auth
.signInWithEmailAndPassword(_email, _password)
.whenComplete(() =>
Navigator.of(context).popAndPushNamed(RootPage.routeName));
print('Signed In:$userId');
} catch (e) {
print('Error:$e');
print(e.toString());
}
}
}
Since you use future, the best way would be to control a CircularProgressIndicator() with a boolean inside your method like this:
Future<void> validateAndSubmit() async {
setState(( {
_isLoading = true;
});
if (validateAndSave()) {
try {
final Auth auth = await AuthFactory.getAuth();
final String userId = await auth
.signInWithEmailAndPassword(_email, _password)
.whenComplete(() =>
{
setState(() {
_isLoading = false;
});
Navigator.of(context).popAndPushNamed(RootPage.routeName));
}
print('Signed In:$userId');
} catch (e) {
print('Error:$e');
print(e.toString());
}
}
}
and then somewhere in your widget tree:
_isLoading ? CircularProgressIndicator() : Other widget...
In my Flutter App I'm using Firebase Auth to authenticate the users. I have login_service with Provider and in the main.dart I check the state of the login.
My flow is:
Check if the user is logged with trackUserState()
If the user is logged I check the database: if the user exist I go to the HomeScreen, if not to the registration screen
My problem is that where I'm checking if the user is logged or not (on the main.dart, inside the routes object) generates a problem: the function is being executed all the time, nonstop.
How can I refactor this to only execute the function on init and after that notify only the changes (logout, a logged but non registered user being registered...) with notifyListeners()?
This are the codes of both files, main.dart and login_service.dart:
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<LoginState>(
create: (context) => LoginState(),
child: MaterialApp(
title: 'MyApp',
debugShowCheckedModeBanner: false,
routes: {
// ignore: missing_return
'/': (BuildContext context) {
var state = Provider.of<LoginState>(context);
state.trackUserState();
if(state.userExist() == false) {
return RegisterScreen();
}
if(state.isLoggedIn() == true) {
return HomeScreen();
}
if (state.isLoggedIn() == false) {
return LoginScreen();
}
},
...here the other routes
},
theme: brightTheme,
),
);
}
}
login_service.dart
class LoginState with ChangeNotifier {
// Instances
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
// Variables
User _user;
bool _userExist;
bool _loading = false;
bool _isLoggedIn = false;
String _userEmail;
// Functions to track
bool isLoggedIn() => _isLoggedIn;
bool isLoading() => _loading;
bool userExist() => _userExist;
User currentUser() => _user;
String getUserEmail() => _userEmail;
// Registration Flow
void goAheadAfterRegistration() async {
if (_user != null) {
var userExist = await _firestore.collection('users').where('email', isEqualTo: _user.email).get();
if (userExist.docs.length == 1) {
} else {
print('Este user aun no se ha registrado');
_userExist = false;
}
notifyListeners();
} else {
_loading = false;
notifyListeners();
}
}
void checkUserOnDatabase() async {
var userExistOnDatabase = await _firestore.collection('users').where('email', isEqualTo: _user.email).get();
if (userExistOnDatabase.docs.length == 1) {
_isLoggedIn = true;
_userExist = true;
notifyListeners();
} else {
_userExist = false;
notifyListeners();
}
notifyListeners();
}
// LogOut the user
void logout() async {
_googleSignIn.signOut();
_auth.signOut();
_loading = false;
_isLoggedIn = false;
notifyListeners();
}
// Tracking the user state
void trackUserState() {
_auth.authStateChanges()
.listen((User user) {
if (user == null) {
_isLoggedIn = false;
notifyListeners();
} else {
_user = user;
checkUserOnDatabase();
notifyListeners();
}
});
}
// Third party login providers
void googleLogin() async {
_loading = true;
notifyListeners();
_user = await _handleSignIn();
checkUserOnDatabase();
}
Future<User> _handleSignIn() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final User user = (await _auth.signInWithCredential(credential)).user;
return user;
}
// TODO on login true circular progress indicator while we check if the user exist to prevent new logins
}
Thank you very much guys!
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
*handle all that 1 trigger stuff here*
runApp(
MyApp(),
);
}