I am developing a login system, using firebase, flutter and vscode.
I would like to know how to handle exceptions generated by Firebase.
If EMAIL is already registered.
Currently generating an error:
Exception has occurred.
PlatformException (PlatformException(ERROR_EMAIL_ALREADY_IN_USE, The email address is already in use by another account., null))
If the email is already registered, I want to inform the user.
CODE:
Future<void> signUp({#required Map<String, dynamic> userData,#required String pass,#required VoidCallback onSuccess,#required VoidCallback onFail}) async{
isLoading = true;
notifyListeners();
_auth.createUserWithEmailAndPassword(
email: userData["email"],
password: pass
).then((user) async{
firebaseUser = user;
await _saveUserData(userData);
onSuccess();
isLoading = false;
notifyListeners();
}).catchError((e){
print(e);
onFail();
isLoading = false;
notifyListeners();
});
}
If you want to perform subsequent operations when ERROR_EMAIL_ALREADY_IN_USE is emitted.
I think it's a good idea to catch a PlatformException and branch the process with code as shown below.
try {
final result = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
} on PlatformException catch (exception) {
switch (exception.code) {
case 'ERROR_EMAIL_ALREADY_IN_USE':
// do something...
default:
break;
}
use on PlatformException catch (e) and if (e.message == 'ERROR_EMAIL_ALREADY_IN_USE') to handle this case.
Related
I want to display the current user name on my app.
I tried this but got the error
Unhandled Exception: Bad state: cannot get a field on a DocumentSnapshotPlatform which does not exist
Future getUserData() async {
User? user = await FirebaseAuth.instance.currentUser;
final DocumentSnapshot doc = await FirebaseFirestore.instance
.collection("UserData")
.doc(user!.uid)
.get();
name = doc['name'];
print("name $name");
}
Then, I tried this:
Future getUserData() async {
User? user = await FirebaseAuth.instance.currentUser;
try {
final doc = await FirebaseFirestore.instance
.collection("UserData")
.doc(user!.uid)
.get();
final ds = await doc.get();
final data = ds.data() as Map<String, dynamic>;
name = data['name'];
print("name $name");
} catch (e) {
print(e.toString());
return null;
}
}
But it shows an error for the doc.get()
1 positional argument(s) expected, but 0 found.
Try adding the missing arguments
What can I do?
.get method expect a key('String') of filed/filePath.
final doc = await FirebaseFirestore.instance
.collection("UserData")
.doc(user!.uid)
.get();
final name = await doc.get("name");
print("name $name");
Also make sure the project setup is ok. More about reading data.
I tried implementing admob to my flutter app. I used open ads to show an ad on launch, but whenever I launch the app it always crashes. Maybe I implemented the code in Info.plist wrong?
enter image description here
enter image description here
AppOpenAd? openAd;
Future loadAd() async{
await AppOpenAd.load(
adUnitId: 'ca-app-pub-######',
request: const AdManagerAdRequest(),
adLoadCallback: AppOpenAdLoadCallback(
onAdLoaded: (ad){
print('ad is loaded');
openAd = ad;
openAd!.show();
},
onAdFailedToLoad: (error){
print('ad failed to load $error');
}),
orientation: AppOpenAd.orientationPortrait
);
}
void showAd() {
if(openAd==null){
print('show before loading');
loadAd();
return;
}
openAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdShowedFullScreenContent: (ad){
print('onAdShowedFullScreenContent');
},
onAdFailedToShowFullScreenContent: (ad, error){
ad.dispose();
print('failed to load $error');
openAd = null;
loadAd();
}, onAdDismissedFullScreenContent: (ad){
ad.dispose();
print('dismissed');
openAd = null;
loadAd();
}
);
openAd!.show();
}
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await MobileAds.instance.initialize();
await loadAd();
final SharedPreferences prefs = await SharedPreferences.getInstance();
runApp(WhatsTheWord());
}
I tried to share data between Safari browser and standalone PWA on iPhone12 with iOS 14.3.
The information, that this should work are here: https://firt.dev/ios-14/
I#ve tried this: https://www.netguru.com/codestories/how-to-share-session-cookie-or-state-between-pwa-in-standalone-mode-and-safari-on-ios
Without success.
Are there any suggestions to running this? Or is it not possible ...
This is the code
const CACHE_NAME = "auth";
const TOKEN_KEY = "token";
const FAKE_TOKEN = "sRKWQu6hCJgR25lslcf5s12FFVau0ugi";
// Cache Storage was designed for caching
// network requests with service workers,
// mainly to make PWAs work offline.
// You can give it any value you want in this case.
const FAKE_ENDPOINT = "/fake-endpoint";
const saveToken = async (token: string) => {
try {
const cache = await caches.open(CACHE_NAME);
const responseBody = JSON.stringify({
[TOKEN_KEY]: token
});
const response = new Response(responseBody);
await cache.put(FAKE_ENDPOINT, response);
console.log("Token saved! 🎉");
} catch (error) {
// It's up to you how you resolve the error
console.log("saveToken error:", { error });
}
};
const getToken = async () => {
try {
const cache = await caches.open(CACHE_NAME);
const response = await cache.match(FAKE_ENDPOINT);
if (!response) {
return null;
}
const responseBody = await response.json();
return responseBody[TOKEN_KEY];
} catch (error) {
// Gotta catch 'em all
console.log("getToken error:", { error });
}
};
const displayCachedToken = async () => {
const cachedToken = await getToken();
console.log({ cachedToken });
};
// Uncomment the line below to save the fake token
// saveToken(FAKE_TOKEN);
displayCachedToken();
Without success means no result, i've tried to set data in safari and get them in standalone pwa
I do not know why catch statement does not catch thrown error when I debug the app.
This is the main function:
void main() async {
final initialState = await persistor.load();
bool logged = false;
if (initialState.isLoggedIn) {
logged = await initialState.silentlyLogin(); // <---- FUNCTION THAT THROWS ERROR
}
if (!logged) {
initialState.logout();
}
}
This is the silentlyLogin function of my State class:
Future<bool> silentlyLogin() async {
try {
await globals.googleSignIn.signInSilently();
return true;
} catch (e) {
return false;
}
}
In debug the googleSignIn.signInSilently function thrown an error, in this part of code:
#override
dynamic decodeEnvelope(ByteData envelope) {
// First byte is zero in success case, and non-zero otherwise.
if (envelope.lengthInBytes == 0)
throw const FormatException('Expected envelope, got nothing');
final ReadBuffer buffer = ReadBuffer(envelope);
if (buffer.getUint8() == 0)
return messageCodec.readValue(buffer);
final dynamic errorCode = messageCodec.readValue(buffer);
final dynamic errorMessage = messageCodec.readValue(buffer);
final dynamic errorDetails = messageCodec.readValue(buffer);
if (errorCode is String && (errorMessage == null || errorMessage is String) && !buffer.hasRemaining)
throw PlatformException(code: errorCode, message: errorMessage, details: errorDetails); // <------ HERE IS THE ERROR
else
throw const FormatException('Invalid envelope');
}
In the debug mode, android studio blocks the app in the throw PlatformException line, but my catch statement is never catched, so my function always returns true.
While my catch statement is never catched.
The exception is probably thrown in native code and not passed to Dart at all. Dart can't catch Java or ObjectivC/Swift exceptions. The plugin would need to catch it in Java, send a message to Dart and in Dart an artificial exception would need to be thrown.
See also
https://github.com/flutter/flutter/issues/17677
https://github.com/flutter/flutter/issues/19748
https://github.com/flutter/flutter/issues/28430
I'm building my first Flutter application and I've run into a bit of an async issue.
When my application executes I'd like it to ask for permissions and wait until they are granted. My main() function looks like this:
import 'permission_manager.dart' as Perm_Manager;
void main() async
{
//Ensure valid permissions
Perm_Manager.Permission_Manager pm = Perm_Manager.Permission_Manager();
var res = await pm.get_permissions();
print(res);
return runApp(MyApp());
}
The Permission Manager class' get_permissions() function uses the Flutter Simple Permissions package to check and ask for permissions.
import 'package:simple_permissions/simple_permissions.dart';
import 'dart:io' as IO;
import 'dart:async';
class Permission_Manager {
/* Get user permissions */
Future<bool> get_permissions() async
{
//Android handler
if (IO.Platform.isAndroid)
{
//Check for read permissions
SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result)
{
//If granted
if (result)
return true;
//Otherwise request them
else
{
SimplePermissions.requestPermission(Permission.ReadExternalStorage)
.then((result)
{
// Determine if they were granted
if (result == PermissionStatus.authorized)
return true;
else
IO.exit(0); //TODO - display a message
});
}
});
}
else
return true;
}
}
When I run the application it does not wait for the function to complete as intended and prints the value of "res" before the Future is updated.
Launching lib\main.dart on Android SDK built for x86 in debug mode...
Built build\app\outputs\apk\debug\app-debug.apk.
I/SimplePermission(15066): Checking permission : android.permission.READ_EXTERNAL_STORAGE
I/flutter (15066): null
I/SimplePermission(15066): Requesting permission : android.permission.READ_EXTERNAL_STORAGE
The Future returns a value midway through the function! Does anyone know what I'm doing wrong?
To await something you have to call the await keyword on a future instead of .then
final result = await future;
// do something
instead of
future.then((result) {
// do something
});
If you really want to use .then then you can await the generated future:
await future.then((result) {
// do something
});
Just ensure that when using nested asynchronous calls that the async keyword is used on each:
await future.then((result) async{
// do something
await future.then((result_2) {
// do something else
});
});
Got it working. The issue seems to be resolved using a Completer:
import 'package:simple_permissions/simple_permissions.dart';
import 'dart:io' as IO;
import 'dart:async';
class Permission_Manager {
/* Get user permissions */
final Completer c = new Completer();
Future get_permissions() async
{
//Android handler
if (IO.Platform.isAndroid)
{
//Check for read permissions
SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result)
{
//If granted
if (result)
{
c.complete(true);
}
//Otherwise request them
else
{
SimplePermissions.requestPermission(Permission.ReadExternalStorage).then((result)
{
// Determine if they were granted
if (result == PermissionStatus.authorized)
{
c.complete(true);
}
else
{
IO.exit(0); //TODO - display a message
}
});
}
});
}
else
{
c.complete(true);
}
return c.future;
}
}