this is the code :
DatabaseReference referenceData=FirebaseDatabase.instance.ref().child('Jobs');
referenceData.get().then((DataSnapshot dataSnapshot) {jobs.clear();
var keys=dataSnapshot.value.keys;
var values = dataSnapshot.value;
for(var key in keys){
Jobs jobs = Jobs(values[key]['JobName'],values[key]['JobDetails']);
}});
and here are the problems :
The property 'keys' can't be unconditionally accessed because the receiver can be 'null'.
The method '[]' can't be unconditionally invoked because the receiver can be 'null'.
The method '[]' can't be unconditionally invoked because the receiver can be 'null'.
I have tried using this code :
DatabaseReference referenceData=FirebaseDatabase.instance.ref().child('Jobs');
referenceData.get().then((DataSnapshot dataSnapshot) {jobs.clear();
var keys=(dataSnapshot.value! as Map<String, dynamic>).keys;
var values = dataSnapshot.value;
for(var key in keys){
Jobs jobs = new Jobs((values! as Map<String, dynamic>)[key]['JobName'],(values! as Map<String, dynamic>)[key]['JobDetails']);
}});
the errors are gone but when I try to run the app I have this message :
Invalid depfile: C:\Users\AhXoX\StudioProjects\daimond.dart_tool\flutter_build\b5bec47ddb82374feed8ecd5e7242ad4\kernel_snapshot.d
Invalid depfile: C:\Users\AhXoX\StudioProjects\daimond.dart_tool\flutter_build\b5bec47ddb82374feed8ecd5e7242ad4\kernel_snapshot.d
lib/main.dart:4:8: Error: Not found: 'dart:html'
import 'dart:html';
^
lib/main.dart:201:79: Warning: Operand of null-aware operation '!' has type 'Object' which excludes null.
'Object' is from 'dart:core'.
Jobs jobs = new Jobs((values! as Map<String, dynamic>)[key]['JobName'],(values! as Map<String, dynamic>)[key]['JobDetails']);
^
I need help, please
You are trying to get data from firestore i mentioned the work i have done. Make fromJson factory method in Job class that takes Map<String,dynamic> as paramter just like that i am fetching user from firestore.
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
uId: json["uID"],
name: json["name"],
image: json["image"],
number: json["number"],
status: json["status"],
typing: json["typing"],
online: json["online"],
);
now we will get all user from firestore.
Future<List<UserModel>> getAppContacts() async {
try {
final data = await FirebaseFirestore.instance.collection("users").get();
return data.docs.map((e) => UserModel.fromJson(e.data())).toList();
} on Exception catch (e) {
throw Exception(e.toString());
}
}
In your method i think you are passing extra [key] try to remove it that might be work.
Related
i'm new to firebase cloud function, My situation is Whenever a new article is published in the database, I need to show the notification to my app user.
my code
var functions = require('firebase-functions');
var admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/article/{articleId}')
.onWrite((event: { data: any; }) => {
var eventSnapshot = event.data;
var str1 = "Author is ";
var str = str1.concat(eventSnapshot.child("author").val());
console.log(str);
var topic = "android";
var payload = {
data: {
title: eventSnapshot.child("title").val(),
author: eventSnapshot.child("author").val()
}
};
return admin.messaging().sendToTopic(topic, payload)
.then(function (response: any) {
console.log("Successfully sent message:", response);
})
.catch(function (error: any) {
console.log("Error sending message:", error);
});
});
Here is my database structure in Firebase.
And the full Stacktrace from logcat is here.
TypeError: Cannot read property 'child' of undefined
at exports.sendNotification.functions.database.ref.onWrite (/srv/lib/index.js:17:41)
at cloudFunction (/srv/node_modules/firebase-functions/lib/cloud-functions.js:131:23)
at /worker/worker.js:825:24
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
sendNotification
Function execution took 286 ms, finished with status: 'error'
Note that onWrite() handler accepts a Change object which has before & after properties, but not data. I guess it's the cause of the problem, see onWrite() documentation. If you want to get the updated data use event.after.child('author') instead of event.data.child('author').
exports.sendNotification = functions.database.ref('/article/{articleId}').onWrite(change => {
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
const author = change.after.child('author').val();
...
});
I am trying to invoke a Firebase https callable function and I get an error in Android Studio saying "com.google.firebase.functions.FirebaseFunctionsException: Response is not valid JSON object"
Here is my code
index.ts file
import * as functions from 'firebase-functions'
const admin = require('firebase-admin')
admin.initializeApp()
export { newUserSignUp } from './userCreated'
export { userDeleted } from './userDeleted'
//this is the function that the client is unable to call
exports.sendFeedback = functions.region('asia-east2').https.onCall((data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
'unauthenticated',
'only authenticated users can add requests'
)
}
if (data.text.length > 30) {
throw new functions.https.HttpsError(
'invalid-argument',
'request must be no more than 30 characters long'
)
}
return admin.firestore().collection('Feedback').add({
Feedback : data.text,
uid: context.auth.uid
})
})
Here is the code in my .kt Activity file in Android Studio
private fun sendFeedbackViaCloudFunction() {
// Create the arguments to the callable function.
val data = hashMapOf(
"text" to write_feedback_edit_text.toString(),
"uid" to FirebaseAuth.getInstance().currentUser!!.uid
)
functions = FirebaseFunctions.getInstance()
Timber.i("Calling the cloud function")
functions
.getHttpsCallable("sendFeedback")
.call(data)
.addOnFailureListener {
//This is the line thats printing the error log statement
Timber.i("Failed to invoke the sendFeedback function: $it")
}
.continueWith { task ->
val result = task.result?.data as String
result
}
}
Error statement threw by Android Studio: com.google.firebase.functions.FirebaseFunctionsException: Response is not valid JSON object.
Ok I resolved this, So basically I was getting the "response is not valid JSON object error" repeatedly even after I set a promise to return a valid JSON in my index.ts file.
So apparently if a client is calling a function then the client also needs to specify the server region if the default us-central1 is not the preferred server location. So I had specified the 'asia-east2' as my preference on the server-side but not at the client-side.
Soon as I added the below line at the client side, works perfectly now
functions = FirebaseFunctions.getInstance("asia-east2")
so I have callable cloud function like this
exports.callableModeratorSendNotification = functions.https.onCall(async (data, context) => {
try {
const platform = data.platform
const priority = data.priority
const message = data.message
const moderatorID = context.auth.uid
// check if moderator have authorization to send notification and check if moderator is active or not
const moderatorSnapshot = await db.doc(`moderators/${moderatorID}`).get()
const moderator = moderatorSnapshot.data()
if ( !moderator.canSendNotification || !moderator.isActive) {
throw new functions.https.HttpsError('invalid-moderator', 'Moderator is invalid. only active moderator who has authorization that can verify a user.')
}
let query
const now = new Date()
const xMonthsAgo = moment().subtract(1,"months").toDate()
query = db.collection(`devices`)
.where("lastActivity","<=",now)
.where("lastActivity",">=",xMonthsAgo)
if ( platform !== "All") {
query = query.where("platform","==",platform) // iOS or Android
}
const devicesQuerySnapshot = await query.get()
devicesQuerySnapshot.docs.forEach( deviceSnapshot => {
const device = deviceSnapshot.data()
console.log(device.userID)
})
{result: 'success'}
} catch(error) {
console.log(error)
return null
}
})
at the moment, that function is just to log the user ID. and that function will return 200 code like this in console
but the problem is in the client side.... I am using Android to call that function, like this
fun sendNotification(platform: String, priority: String, message: String) : Task<String> {
// Create the arguments to the callable function.
val data = hashMapOf(
"platform" to platform,
"priority" to priority,
"message" to message
)
return functions
.getHttpsCallable("callableModeratorSendNotification")
.call(data)
.continueWith { task ->
val result = task.result?.data as String
result
}
}
and then use it like this
sendNotification(selectedPlatform,selectedPriority,message).addOnSuccessListener {
toast("successful")
}.addOnFailureListener {
toast("failed")
}
the problem is, even though the status code in the console is 200, but addOnFailureListener will always be called. I expect addOnSuccessListener will be called if the response is 200
here is the exception caught by the failure listener
java.util.HashMap cannot be cast to java.lang.String 2020-02-04
11:30:09.023 26024-26024/com.
java.lang.ClassCastException: java.util.HashMap cannot be cast to
java.lang.String
in this line ?
val result = task.result?.data as String
where does the result come from. does it represent the return on my callable function ? I assume callable function should return a promise like cloud function trigger
class Resistencia100{
int id;
double r_pos1;
double r_pos2;
double r_pos3;
double r_pos4;
double r_pos5;
Resistencia100({
this.id, this.r_pos1, this.r_pos2, this.r_pos3, this.r_pos4,
this.r_pos5
});
Map<String, dynamic> toMap() => {
"id": id,
"r_pos1": r_pos1,
"r_pos2": r_pos2,
"r_pos3": r_pos3,
"r_pos4": r_pos4,
"r_pos5": r_pos5,
};
factory Resistencia100.fromMap(Map<String, dynamic> json) => new Resistencia100(
id: json["id"],
r_pos1: json["r_pos1"],
r_pos2: json["r_pos2"],
r_pos3: json["r_pos3"],
r_pos4: json["r_pos4"],
r_pos5: json["r_pos5"],
);
}
This is my Model class Resistencia100, Now we will see how I request the data through my get method
Future<List<Resistencia100>> getAllResistencia100() async {
final db = await database;
var response = await db.query("Resistencia100");
List<Resistencia100> list = response.map((c) => Resistencia100.fromMap(c)).toList();
print("Cantidad ID: "+list[0].id.toString());
print("Cantidad r_pos1: "+list[0].r_pos1.toString());
print("Cantidad r_pos2: "+list[0].r_pos2.toString());
print("Cantidad r_pos3: "+list[0].r_pos3.toString());
print("Cantidad r_pos4: "+list[0].r_pos4.toString());
print("Cantidad r_pos5: "+list[0].r_pos5.toString());
return list;
}
The information is coming correctly to the method, now I try to extract that information and the error is coming.
List <Resistencia100> resistencia100 = new List<Resistencia100>();
Future<List<Resistencia100>> getResistencia100() async {
await ClientDatabaseProvider.db.getAllResistencia100();
}
void validate() async {
resistencia100 = await getResistencia100();
print("RESISTENCIA ID: "+resistencia100[0].id.toString());
}
The truth is that I don't understand the reason for the error very well, I hope you can understand, I will leave the textual error in the following lines, this is generated in the "print".
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: [](0)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 _ConfigConcretoState.validate (package:entremuros/vistas/configconcreto.dart:282:44)
Your method getResistencia100() is not returning anything. So at validate() your variable resistencia100 is transforming into a null after await the getResistencia100()
A solution is change the getResistencia100(), adding a return statement
Future<List<Resistencia100>> getResistencia100() async {
return await ClientDatabaseProvider.db.getAllResistencia100();
}
I’m trying to call an async Firebase function from android app and getting “INTERNAL” exception when the function returns.
Android:
private Task<String> fetchData() {
// Create the arguments to the callable function, which is just one string
Map<String, Object> data = new HashMap<>();
data.put(“id”, “abc”);
return FirebaseFunctions.getInstance()
.getHttpsCallable(“calculate”)
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
Map<String, Object> result = (Map<String, Object>) task.getResult().getData();
return (String)result.get(“data”);
}
});
}
Firebase Function:
exports.calculate = functions.https.onCall((data, context) => {
const text = data.id;
return calc.calculate( (err, response) => {
if(err) {
// handle error
} else {
const data = response.dataValue;
}
}).then(() => {
return {“data”: data};
});
});
Exception:
com.google.firebase.functions.FirebaseFunctionsException: INTERNAL
The documentation for handling errors in callable functions indicates that an instance of functions.https.HttpsError must be returned:
To ensure the client gets useful error details, return errors from a
callable by throwing (or returning a Promise rejected with) an
instance of functions.https.HttpsError... If an error other than
HttpsError is thrown from your functions, your client instead receives
an error with the message INTERNAL and the code internal.
It seems likely that your calc.calculate() call is returning an error that is not being handled correctly, resulting in a returned error status of INTERNAL.
Following the example in the document linked above, your code should be something like:
if(err) {
// handle error
throw new functions.https.HttpsError('calc-error', 'some error message');
} else {
const data = response.dataValue;
}
When you call httpCallable ,you will get an exception called FirebaseFunctionsExceptions. You have to handled this exceptions. Wrap your code with try and catch .
Example:-
try {
final result = await FirebaseFunctions.instance
.httpsCallable('deleteUser')
.call({});
} on FirebaseFunctionsException catch (error) {
print(error.message);
}
For more info follow this link.