how can I get a button to delete a file from Firebase Storage using a URL as a reference. The URL is retrieved from a Firestore collection field called "fileUrl" using the Firebase Storage getDownloadUrl method.
When I try to delete, I receive an error and my app crashes.
Code:
onPressed: () async {
if (newsDataModel.get('fileUrl') != null) {
await FirebaseStorage.instance.refFromURL(newsDataModel.get('fileUrl')).delete();
} else {
return;
}
await newsDataModel.reference.delete().then((value) => Navigator.pop(context));
}
Error:
_AssertionError ('package:firebase_storage/src/firebase_storage.dart':
Failed assertion: line 112 pos 12: 'url.startsWith('gs://') || url.startsWith('http')':
'a url must start with 'gs://' or 'https://')
Realized that I had made a mistake. Some of the collections have fileUrl fields that are empty/null, so I was deleting collections that had null values and therefore returned an error.
New updated code:
onPressed: () async {
try {
if (hwDataModel.get('fileUrl') != null) {
await FirebaseStorage.instance.refFromURL(hwDataModel.get('fileUrl')).delete()
.then((value) => {
hwDataModel.reference.delete().then((value) =>
Navigator.pop(context))});
} else if (hwDataModel.get('fileUrl') == null) {
await hwDataModel.reference.delete().then(
(value) => Navigator.pop(context));
};
} on FirebaseException catch (error) {
Fluttertoast.showToast(
msg: error.message.toString(),
gravity: ToastGravity.TOP,
backgroundColor: Colors.red,
textColor: Colors.white);
}
},
Related
I have released my first app to google play and opened it for several test users.
I am using Firebase Authentication service for managing users.
When my test users try to signup (by email and password), they get an unknown error.
Are there any special changes I need to do before releasing my app?
My functionality is quite simple so I really don't know why they get an error.
Thank you in advance.
Error:
"[firebase_auth/unknown] There was an error while initializing the connection to the GoogleApi: java.lang.NoSuchMethodError: No static method isAtLeastR()Z in class La/d/g/a; or its super classes (declaration of 'a.d.g.a' appears in /data/app/com.omertab.appname--WeJcqqlq_1NPgpgJc96JQ==/base.apk)"
Instance:
final _auth = FirebaseAuth.instance;
My functionality:
MaterialButton(
onPressed: () async {
_showSpinner = true;
try {
final newUser = await _auth.createUserWithEmailAndPassword(email: email, password: password);
if (newUser != null) {
await _fireStore.collection('users').add({
'email': email,
'uId': _auth.currentUser.uid
});
Navigator.pushNamed(context, HomePage.screenId);
_showSpinner = false;
}
} on FirebaseAuthException catch (e) {
_showSpinner = false;
print(e.code);
if(e.code == "invalid-email") {
print("INVALID EMAIL");
setState(() {
signupError = "Invalid mail";
});
} else if(e.code == "invalid-password") {
print("INVALID PASS");
setState(() {
signupError = "Invalid password";
});
} else if(e.code == "weak-password") {
setState(() {
signupError = "Please choose a stronger password";
});
} else if(e.code == "unknown") {
setState(() {
signupError = "Unknown error occurred";
});
}
}
},
minWidth: 200.0,
height: 42.0,
child: Text(
'Signup',
style: TextStyle(color: Colors.white),
),
Issue solved.
I implemented
implementation("com.google.android.gms:play-services-base:17.6.0"){ force = true }
to build.gradle
Not the problem described, but it might help someone. I was getting a different error:
[firebase_auth/unknown] com.google.firebase.FirebaseException: An internal error has occurred. [ CONFIGURATION_NOT_FOUND ]
I've solved it by activating the authentication service in the Firebase console.
hello i am new to flutter and firebase and i have a field in the user document that is called admin and it's a boolean , i want to check this boolean in the sign in functionality .
what i came up so far is this :
onPressed: () async {
if (_formKey.currentState.validate()) {
if (!await user.signIn(_email.text, _password.text)) {
toast("Signin Faild");
} else {
if(await _firestore.collection('users').doc(_auth.currentUser.uid).get().)
changeScreenReplacement(context, HomePage());
toast("Signedin successfully");
}
}
},
i don't know what to do in this part :
if(await _firestore.collection('users').doc(_auth.currentUser.uid).get().)
i want here to check the field if it's equal to true or false how can i do this ?
If you want to check if the user return true or false, you can do as following:
onPressed: () async {
if (_formKey.currentState.validate()) {
if (!await user.signIn(_email.text, _password.text)) {
toast("Signin Faild");
} else {
FirebaseUser user = await _auth.currentUser();
DocumentReference document = await _firestore.collection('users').doc(user.uid).get()
if(document.data['admin'] == true)
changeScreenReplacement(context, HomePage());
toast("Signedin successfully");
}
}
},
You can also check the Flutter Documentation
EDITED onMessageSent function. Still the same error.
I'm trying to enable push notifications in flutter and I am using Firebase Messaging. I am encountering the following issue. There are two, namely "onCreateActivityFeedItem" & "onMessageSent".
For the first one, "onCreateActivityFeedItem", the notification feature is perfectly fine, but I could not recognize the problem with the second one. Please do help.
The problem I am facing :
onMessageSent
TypeError: Cannot read property 'androidNotificationToken' of undefined at exports.onMessageSent.functions.firestore.document.onCreate (/workspace/index.js:152:47) at process._tickCallback (internal/process/next_tick.js:68:7)
Here is the "onCreateActivityFeedItem" :
From my index.js
exports.onCreateActivityFeedItem = functions.firestore
.document("/feed/{userId}/feedItems/{activityFeedItem}")
.onCreate(async (snapshot, context) => {
console.log("Activity Feed Item Created", snapshot.data());
// 1) Get user connected to the feed
const userId = context.params.userId;
const mediaUrl=context.params.mediaUrl;
const userRef = admin.firestore().doc(`users/${userId}`);
const doc = await userRef.get();
// 2) Once we have user, check if they have a notification token; send notification, if they have a token
const androidNotificationToken = doc.data().androidNotificationToken;
const createdActivityFeedItem = snapshot.data();
if (androidNotificationToken) {
sendNotification(androidNotificationToken, createdActivityFeedItem);
} else {
console.log("No token for user, cannot send notification");
}
function sendNotification(androidNotificationToken, activityFeedItem) {
let body;
// 3) switch body value based off of notification type
switch (activityFeedItem.type) {
case "comment":
body = `${activityFeedItem.username} replied: ${
activityFeedItem.commentData
}.`;
break;
case "like":
body = `${activityFeedItem.username} booped you.`;
break;
case "follow":
body = `${activityFeedItem.username} started petting you.`;
break;
default:
break;
}
// 4) Create message for push notification
const message = {
notification: {
body:body,
image:mediaUrl
},
token: androidNotificationToken,
data: {recipient: userId,
}
};
// 5) Send message with admin.messaging()
admin
.messaging()
.send(message)
.then(response => {
// Response is a message ID string
console.log("Successfully sent message", response);
return null;
})
.catch(error => {
console.log("Successfully sent message", response);
throw Error("Could not send message.",error)});
// admin.messaging().sendToDevice(androidNotificationToken,message);
}
});
From my index.js
Here is the, "onMessageSent":
exports.onMessageSent = functions.firestore
.document('/messages/{chatId}/messageInfo/{messageFeedItem}')
.onCreate(async (snapshot, context) => {
console.log("Message Created", snapshot.data());
// 1) Get user connected to the feed
const chatId=context.params.chatId;
const userId = context.params.idTo;
const idTo =context.params.idTo;
const userRef = admin.firestore().doc(`users/${idTo}`);
const doc = await userRef.get();
const createdMessageFeedItem = snapshot.data();
// 2) Once we have user, check if they have a notification token; send notification, if they have a token
const androidNotificationToken = doc.data().androidNotificationToken;
if (androidNotificationToken) {
sendNotification(androidNotificationToken, createdMessageFeedItem);
} else {
console.log("No token for user, cannot send notification");
}
function sendNotification(androidNotificationToken,createdMessageFeedItem) {
let body;
// 3) switch body value based off of notification type
switch (messageFeedItem.type) {
case 0:
body = `${messageFeedItem.username} has sent a message : ${
messageFeedItem.content
}.`;
break;
case 1:
body = `${messageFeedItem.username} has sent an image.`;
break;
case 2:
body = `${messageFeedItem.username} has sent a gif.`;
break;
default:
break;
}
// 4) Create message for push notification
const message = {
notification:
{body:body,},
token: androidNotificationToken,
data: {recipient: idTo,}
};
// 5) Send message with admin.messaging()
admin
.messaging()
.send(androidNotificationToken,message)
.then(response => {
// Response is a message ID string
console.log("Successfully sent message", response);
return null;
})
.catch(error => {
console.log("Successfully sent message", response);
throw Error("Could not send message.",error)});
// admin.messaging().sendToDevice(androidNotificationToken,message);
}
});
Where I called/declared the onMessage, onResume :
configurePushNotifications() {
final GoogleSignInAccount user = googleSignIn.currentUser;
if (Platform.isIOS) {
getiOSPermission();
}
_firebaseMessaging.getToken().then((token) {
print("Firebase messaging token : $token");
setState(() {
currentUser.androidNotificationToken = token;
});
usersref.doc(user.id).update({"androidNotificationToken": token});
});
_firebaseMessaging.configure(
onLaunch: (Map<String, dynamic> message) async {
_firebaseMessaging.getToken().then((token) {
print("Firebase messaging token : $token");
usersref.doc(user.id).update({"androidNotificationToken": token});
});
// print("On Launch : $message\n");
// _navigateToDetail(message);
},
onResume: (Map<String, dynamic> message) async {
_firebaseMessaging.getToken().then((token) {
print("Firebase messaging token : $token");
usersref.doc(user.id).update({"androidNotificationToken": token});
});
print("On Resume : $message");
_navigateToDetail(message);
},
onMessage: (Map<String, dynamic> message) async {
print("On message : $message\n");
final String recipientId = message['data']['recipient'];
final String body = message['notification']['body'];
if (recipientId == user.id) {
//Notification shown");
SnackBar snackBar = SnackBar(
backgroundColor: Colors.blueAccent,
content: Text(
body,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
action: SnackBarAction(
label: "Go",
textColor: Colors.black,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ActivityFeed();
}),
);
}),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
//Notifications not shown.");
},
);
}
I tried different ways like getting the androidNotificationToken by updating in cloud firestore and getting it, but it didn't work.
[Users in Cloud Firestore][1]
[1] https://imgur.com/a/u5Df0zD
I'm just a beginner, trying to learn new stuff. Please do help.
Thank you,
SLN
Cannot read type error of undefined
error happens when the data dosent exist at docu.data().androidNotificationToken
Ensure the reference is correct, I prefer using this type of path for more clarity
let ref = db.collection(‘users’).doc(userID);etc
You can also catch a empty snapshot
var snapshot = await ref.get();
if(snapshot.empty){
console.log(‘snapshot is empty’);
}
I want to build a function that update the user email in firebase so this is what I did:
1- checked if there is internet.
2- do user.updateEmail with the email I got from firestore after I uploaded it in the sign Up and It can't be null because I used it down and it also prints the error :
NoSuchMethodError: The method 'updateEmail' was called on null.
I/flutter ( 9769): Receiver: null
I/flutter ( 9769): Tried calling: updateEmail("omarkaram1st#gmail.com")
see It got the email but somehow it can't send an email;
Code :
switchAccount() async {
try {
final user = await _auth.currentUser();
final result = await InternetAddress.lookup('google.com');
try {
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
user.updateEmail(email);
AwesomeDialog(
btnOkText: 'Ok',
context: context,
headerAnimationLoop: false,
dialogType: DialogType.INFO,
animType: AnimType.BOTTOMSLIDE,
title: 'Info',
desc: 'A Reset Email Has Been Sent To $email',
btnOkOnPress: () {},
)..show();
}
} catch (e) {
print(e);
}
} on SocketException catch (_) {
AwesomeDialog(
btnOkText: 'Retry',
context: context,
headerAnimationLoop: false,
dialogType: DialogType.ERROR,
animType: AnimType.BOTTOMSLIDE,
title: 'Error',
desc:
'Make Sure That You Have an Internet Connection Before Pressing Retry',
btnOkOnPress: () =>
Navigator.pushReplacementNamed(context, '/HomePage'),
)..show();
}
}
It looks like user is null in your call to user.updateEmail(email). We can't say why that is from the code you shared, but the quick way to prevent the error is to check for null after calling await _auth.currentUser().
final user = await _auth.currentUser();
if (user != null) {
final result = await InternetAddress.lookup('google.com');
try {
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
user.updateEmail(email);
...
}
} catch (e) {
print(e);
}
}
else {
... do something relevant when no user is signed in
}
I have a database where I store the ids of favorite articles and i created a function to check if the Id exist in the table Favoris here it is :
existFavoris(int idArticle) async{
final db = await database;
var res =await db.query("Favoris", where: "idArticle = ?", whereArgs: [idArticle]);
return res.isNotEmpty;
}
I created a button to add/remove the id from the table
StatefulBuilder(
builder: (BuildContext context, StateSetter setState){
return new IconButton(
icon: new Icon(
Icons.star,
color: decideColor(idArticle)
),
onPressed: (){
if(DBProvider.db.existFavoris(idArticle)){
DBProvider.db.removeFromFavoris(idArticle);
}
else {
DBProvider.db.addToFavoris(idArticle);
}
},
);
},
Here is the decideColor() code that checks if id exists in DB:
decideColor(int idArticle){
if (DBProvider.db.existFavoris(idArticle)){
return Color(0xffffD700);
}
return Colors.white;
}
I keep getting this error:
type 'Future<dynamic>' is not a subtype of type 'bool'
I see your existFavoris is async, then it at least returns Future. You have to await the response from that function.
Make onPressed async and await existFavoris
onPressed: () async {
var exists = await DBProvider.db.existFavoris(idArticle);
if(exists){
DBProvider.db.removeFromFavoris(idArticle);
} else {
DBProvider.db.addToFavoris(idArticle);
}
},