How to catch StorageException in flutter - firebase

I'm using Firebase storage with flutter. If the upload operation fails for whatever reason (e.g. exceeds size limits set in console), it causes a StorageException.
I want to do something like this:
try {
final uploadTask = ref.putFile(docFile);
taskSnapshot = await uploadTask.onComplete;
} on StorageException catch (err) {
// Do something
}
But there isn't any StorageException type and I can't find a way to catch any and all exceptions. Any ideas?

You can do something like the following instead.
import 'package:firebase_core/firebase_core.dart' as firebase_core;
try {
final uploadTask = ref.putFile(docFile);
taskSnapshot = await uploadTask.onComplete;
} on firebase_core.FirebaseException catch(e) {
if (e.code == 'permission-denied') {
/// Real permisssion-denied handling
print('User does not have permission to upload to this reference.');
}
if (e.code == 'the-error-code-printed-to-console') {
///the-error-code-printed-to-console handling
print('printing what you want');
}
}
This handles errors and checks if it's due to permission. If you are looking for another cause, you can just print the e.code to the console first, copy the code and check if the code copied previously from console is equal to e.code.

try catch doesnt work very well, I solved it like this:
}, onError: (e) {
debugPrint('Exception::: ==========>>>>>>> ${e.toString()}');
});
It get it that way

Related

Flutter Web Firebase storage error response storage/unkown

hope all is well.
I have been trying to upload an image or file to firebase storage from flutter web. Once I try to call put data the console just reads
Firebase Storage: An unknown error occurred, please check the error payload for server response. (storage/unknown)
I don't know how to check server response when using a plugin but this error comes from the try-catch block with on firebaseexception print error
Code: XFile? pickedImage;
_startFilePicker() async {
pickedImage = await ImagePicker().pickImage(
source: ImageSource.camera,
imageQuality: 60,
maxWidth: 250,
);
setState(() {
_hasUploaded = true;
});
uploadImageToStorage(pickedImage);
}
String uploadedPhotoUrl = '';
uploadImageToStorage(XFile? pickedFile) async {
try {
final String url = FirebaseStorage.instance.bucket;
Reference _reference = FirebaseStorage.instance
.refFromURL(
'gs://genderbasedviolence-bd860.appspot.com/') //${FirebaseAuth.instance.currentUser!.uid}
.child('images');
final bytes = await pickedFile!.readAsBytes();
await _reference.putData(bytes);
} on FirebaseException catch (e) {
print(e.code);
}
}
Please let me know if you need more info. Thanks

My function not working even if it meets the condition flutter

I have tried to add a function that allow the user to add a profile picture inside my app.
late String? profileURL = '';
late File userProfilePicture;
...
Future pickAndUploadImage() async {
final ImagePicker _picker = ImagePicker();
try {
XFile? image = (await _picker.pickImage(source: ImageSource.gallery));
print('eee');
await new Future.delayed(const Duration(seconds: 2));
userProfilePicture = File(image!.path);
print(userProfilePicture);
print(File(image.path));
if (userProfilePicture != File(image.path)) {
print('It didnt work sorry');
Navigator.pop(context);
}
else {
print('Should be startting to put file in');
var snapshot = await storage
.ref()
.child('userProfiles/$userEmail profile')
.putFile(userProfilePicture);
print('file put in!');
profileURL = await snapshot.ref.getDownloadURL();
}
setState(() {
DatabaseServices(uid: loggedInUser.uid).updateUserPhoto(profileURL!);
print(profileURL);
});
} catch (e) {
print(e);
}
}
The thing is, this line : if (userProfilePicture != File(image.path)) seen not to work. I do not know why, but here is my output :
> flutter: eee
>flutter: 2 File: '/Users/kongbunthong/Library/Developer/CoreSimulator/Devices/..../tmp/image_picker_3912CA1D-AC60-4C84-823F-EB19B630FD1C-11650-0000061E644AD3FA.jpg'
> flutter: It didnt work sorry
The second line shows that there is 2 file overlapping each other, and doesn't that means the 2 files are the same?
And if it is the same, it should print out Should be starting to put the file in. But instead, it prints out: It didn't work sorry.
Any help is VERY MUCH appreciated!
The two files are different File objects and so the equality check will fail.
You can check if the two File paths are the same like this:
if (userProfilePicture.path != image.path)

Flutter: PlatformException thrown by FireBase won't get caught

I have a function that is used to sign in to Firebase using firebase_auth, however, whenever an exception is thrown it isn't getting caught and still appears in the Android Studio console nor do the print statements in the catch block ever run.
How do I fix this?
signIn({String email, String password}) {
print('listened');
try {
FirebaseAuth.instance.signInWithEmailAndPassword(
email: email, password: password);
}
on PlatformException catch (signUpError) {
print(signUpError.code);
if (signUpError.code == 'ERROR_WEAK_PASSWORD') {
print('Weak Password');
}else if(signUpError.code=='ERROR_USER_NOT_FOUND'){
print('Invalid Username');
}
else{
print(signUpError.toString());
}
}
}
signInWithEmailAndPassword returns a Future<AuthResult> (it is asynchronous), therefore you need to use the catchError method to catch the error when calling an asynchronous method:
FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password).then((result) {
print(result);
})
.catchError((error) {
print("Something went wrong: ${error.message}");
});
Check the following:
https://api.dart.dev/stable/2.3.0/dart-async/Future/catchError.html
https://medium.com/firebase-tips-tricks/how-to-use-firebase-authentication-in-flutter-50e8b81cb29f
The try catch blocks will work if the Firebase call is within an async function and the await statement is used when calling Firebase.
For example, in the following code an error getting the token will be trapped by the on PlatformException catch (... block but an error writing the token to FB RTDB won't be:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - NO AWAIT STATEMENT
globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
whereas adding the await statement, as in the following code, will trap errors in writing to FB RTDB as well:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - AWAIT STATEMENT ADDED
await globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
If you don't want to or can't use await then, as per Peter's answer, the solution is to use the catchError statement instead of try catch.

How to catch DatabaseError in Flutter Firebase App

I am learning Flutter and I want to catch the exception that should be thrown ( as security rule is correctly rejecting it) at the Flutter Application/device.
Below is the code
try {
FirebaseDatabase.instance.reference().once().then((DataSnapshot snapshot) {
try {
debugPrint(snapshot.toString());
}
on DatabaseError catch (eIn1) {
debugPrint(' onRoot ' + eIn1.toString());
}
});
}on DatabaseError catch (eOut1) {
debugPrint(' on1 ' + eOut1.toString());
}
try {
FirebaseDatabase.instance.reference().child("todo").once().then((DataSnapshot snapshot) {
try {
debugPrint(snapshot.toString());
}
on DatabaseError catch (eIn2) {
debugPrint(' onNode ' + eIn2.toString());
}
});
}on Exception catch (eOut2) {
debugPrint(' on2 ' + eOut2.toString());
}
But the Exception is never thrown or catch by the Android Studio, In logCat I can see the exception,
com.example.flutterlogindemo E/flutter:
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception:
DatabaseError(-3, Permission denied, )
#0 Query.once (package:firebase_database/src/query.dart:84:41)
#1 _HomePageState.initState (package:flutter_login_demo/pages/home_page.dart:48:65)
but could not find a away to catch it in code and then act on the exception.
You can use the catchError to be able to catch the error:
FirebaseDatabase.instance.reference().child("todo").once().then((DataSnapshot snapshot) {
print(snapshot);
})
.catchError((error) {
print("Something went wrong: ${error.message}");
});
https://api.flutter.dev/flutter/package-async_async/DelegatingFuture/catchError.html
Repeating my answer to Flutter: PlatformException thrown by FireBase won't get caught here:
The try catch blocks will work if the Firebase call is within an async function and the await statement is used when calling Firebase.
For example, in the following code an error getting the token will be trapped by the on PlatformException catch (... block but an error writing the token to FB RTDB won't be:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - NO AWAIT STATEMENT
globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
whereas adding the await statement, as in the following code, will trap errors in writing to FB RTDB as well:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - AWAIT STATEMENT ADDED
await globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
If you don't want to or can't use await then, as per Peter's answer, the solution is to use the catchError statement instead of try catch.

Handling Firebase Insufficient Permissions Errors in Flutter

How can I handle insufficient permissions errors from firebase? I currently do this:
try {
DocumentSnapshot doc = await Firestore.instance.collection('SomeCollection').document('SomeDocument').get();
// Do something
} catch (error) {
print('Error: $error');
// Do something to show user
}
How ever I can't check for only Permission Errors. Sho how can I catch only insufficient permission errors?
Also when should I use .catchError(), I tried this:
DocumentSnapshot doc = await Firestore.instance.collection('Some Collection').document('Some Document').get().catchError((onError) {
// What to do here
});
I doens't seem to really catch a error, because the exception is still thrown
This is supposed to work
DocumentSnapshot doc = await Firestore.instance.collection('Some Collection').document('Some Document').get().catch((err)=>print(err));
You can recognize the permission error by the error code (which is 'permission-denied').
If it's a different error, you can throw it, or handle diffrently.
try {
DocumentSnapshot doc = await Firestore.instance.collection('SomeCollection').document('SomeDocument').get();
// Do something
} catch (error) {
if (error.code === 'permission-denied') {
// Do something to show user
}
else {
throw new Error(e); // Or do other things
}
}

Resources