Call Firebase Cloud Functions Android - android

Hi to everyone watching this post.
I have my app, and I want to know how to call my Firebase Cloud Functions in it. I've been reading from the Firebase guides but I am really struggling to understand how it works.
I have a function where I want to create parties, and I have some values to be inserted such as address, date, owner, etc.
If anyone who knows about this can help me I would be really grateful, I can provide any more information that you could need. Thanks!

As Frank said, it is better when you ask a question on StackOveflow to include all the code you have already written.
However, from your comment, I understand you are referring to the code snippet that is in the documentation (copied/pasted below), and that you have problems with data.put.
private Task<String> addMessage(String text) {
// Create the arguments to the callable function.
Map<String, Object> data = new HashMap<>();
data.put("text", text);
data.put("push", true);
return mFunctions
.getHttpsCallable("addMessage")
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
String result = (String) task.getResult().getData();
return result;
}
});
}
This Java code snippet shows that the data that is passed (sent) to the Callable Cloud Function is contained in an HashMap, named data.
You will find a lot of tutorials on the web on how to use an HashMap, but in a nutshell:
"A Java HashMap is a hash table based implementation of Java’s Map interface. A Map, as you might know, is a collection of key-value pairs. It maps keys to values." Source: https://www.callicoder.com/java-hashmap/
A way to add new key-value pairs to the HashMap is by using the put() method. So this part of the code in the snippet is about adding data to the HashMap that will be sent to the CloudFunction.
And in the Cloud Function you will get this data as follows (as explained in the doc):
exports.addMessage = functions.https.onCall((data, context) => {
// ...
const text = data.text;
const push = data.push;
// ...
});

Related

fetch the data from firebase and populate the recyclerview through for loop if the keys of the node are stored locally [duplicate]

Basically what I am trying to do is I have a database with the name users having an attribute username. I have some usernames in one list and I want to show details of these users only whose username is present in the list. How can I write a query to fetch details of those users only whose username is found in this list? And note that there is no lexicographical ordering so i can't use startAt() and endAt() functions as well.
code snippet:
=> myList contains usernames. This code doesn't yield accurate results.
Any help would be really appreciated! Thank you!
FirebaseRecyclerOptions<MainModel> options =
new FirebaseRecyclerOptions.Builder<MainModel>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username")
.startAt(myList.get(0)).endAt(myList.get(myList.size()-1)),MainModel.class).build();
As already mentioned in the comment, the Firebase-UI library doesn't help in your case, because it doesn't allow you to pass multiple queries to the FirebaseRecyclerOptions object. So you need to perform a separate query and use the combined result.
When you are calling .get() on a Firebase Realtime Database query object, you are getting back a Task object. So the key to solving this problem is to use whenAllSuccess(Collection> tasks). In your case, it should look like this:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = db.child("users");
Query query = usersRef.orderByChild("username");
List<Task<DataSnapshot>> tasks = new ArrayList<>();
for (String username : myList) {
tasks.add(query.equalTo(username).get());
}
Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
#Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list.
for (Object object : list) {
MainModel mm = ((DataSnapshot) object).getValue(MainModel.class);
if(mm != null) {
Log.d("TAG", mm.getUsername());
}
}
}
});
Assuming that you have in your MainModel class a getter called getUsername(), the result in your logcat will be all the usernames of all returned children.

Can you explain this dart json parsing code please?

So i have this code that works somehow, however i can't really explain why.
To get this code i used an automatic json to code application called quicktype using as input a json that my company provides. The goal of the code is obtaining a Map containing polygons in this format : {(Random ID of polygon)} ==> [Lat,Lon]
class Poligoni {
Map<String, List<String>> poligoni;
Poligoni({
this.poligoni,
});
factory Poligoni.fromRawJson(String str) {
return Poligoni.fromJson(json.decode(str));
}
factory Poligoni.fromJson(Map<String, dynamic> json) {
return Poligoni(
poligoni: Map.from(json["Poligoni"]).map((k, v) {
return MapEntry<String, List<String>>(
k, List<String>.from(v.map((x) => x)));
}),
);
}
}
So the code either accepts a raw json from the (.fromRawJson) function or a decoded one from (.fromJson) function. No problems here. The part that confuses me is this one :
factory Poligoni.fromJson(Map<String, dynamic> json) {
return Poligoni(
poligoni: Map.from(json["Poligoni"]).map((k, v) {
return MapEntry<String, List<String>>(
k, List<String>.from(v.map((x) => x)));
}),
);
}
The problems i have understanding this are(.fromJson function):
Why i return a Class? example: return Poligoni(.....various code)
The use of the redirecting constructor in not very clear in this case to me poligoni:
A lot of difficulty undestanding the function after poligoni: : i know that the function parses the json key 'Poligoni' and transform this in another map of type <String>,List<String>
that contains for every key a list of points which form a polygon however i am not sure how, if you can write a step-by-step walk through it will be greatly appreciated or in alternative if you can reformat this code to make it clearer.
I tried looking through dart and flutter docs but i didn't unterstand most of it because of the nested functions that my code uses and a little bit of language barrier.
Any help is greatly aprreciated,
Best Regards.
Why i return a Class? example: return Poligoni(.....various code)
Because you are using a factory constructor. A factory constructor is like a static method but your are required to return an instance of an object that are compatible with the class it is part of.
One advantage of this pattern is that when using a normal constructor, you are not allowed to set any final variables inside the constructor body but needs to set them as part of the initializing phase.
In you case, this is really not a problem since the variable Map<String, List<String>> poligoni is not final but it can still be a nice pattern.
Read more about factory constructors here:
https://dart.dev/guides/language/language-tour#factory-constructors
The use of the redirecting constructor in not very clear in this case to me poligoni:
See my previous answer.
A lot of difficulty undestanding the function after poligoni: : i know that the function parses the json key 'Poligoni' and transform this in another map of type ,List that contains for every key a list of points which form a polygon however i am not sure how, if you can write a step-by-step walk through it will be greatly appreciated or in alternative if you can reformat this code to make it clearer.
factory Poligoni.fromJson(Map<String, dynamic> json) {
return Poligoni(
poligoni: Map.from(json["Poligoni"]).map((k, v) {
return MapEntry<String, List<String>>(
k, List<String>.from(v.map((x) => x)));
}),
);
}
As previous stated we have defined a factory constructor which must return an object which are compatible with the class it is part of. In this case we therefore creates a new Poligoni object by calling the constructor of Poligoni which takes a named argument poligoni. This is why we have poligoni:.
We are setting the named argument poligoni to the value of the following statement:
Map.from(json["Poligoni"]).map((k, v) {
return MapEntry<String, List<String>>(
k, List<String>.from(v.map((x) => x)));
})
I am not really sure why we are using Map.from but the purpose of this constructor is to create a new map based on the key-values from another map:
https://api.dart.dev/stable/2.10.4/dart-core/Map/Map.from.html
(personally, I would have used a typecast from json["Poligoni"] since this must be a Map instance)
We are then calling .map on this new Map to create another new Map but where each key-value pair is mapped to new key-value pairs by the following method:
(k, v) {
return MapEntry<String, List<String>>(
k, List<String>.from(v.map((x) => x)));
}
We can see here we are keeping the original key k but are converting the value v with:
List<String>.from(v.map((x) => x))
My guess here is that v is List<dynamic> and we want to create a new list of the type List<String> by taking each element of List v and inserting it into a new List which has been defined as List<String> from the start.
The result of this is then used as value in our new Map which are then used as value for the poligoni argument.
In short, all of this operations are really used for making your code more type safe by converting dynamic types into statically determined types.

Why is my Cloud Firestore Transaction not merging when using SetOptions.merge()?

Just started with Firestore and use the SetOptions.merge() in a Cloud Firestore Transaction like this nothing special I guess:
final Map<String, Object> visitorMap = new HashMap<>();
visitorMap.put(Visitor.NOTIFY_ON_CHAT_MESSAGE, true);
visitorMap.put(Visitor.TIME, FieldValue.serverTimestamp());
final DocumentReference docRefVisitor = mFirestore
.collection(VISITORS)
.document(theId)
.collection(VISITORS_USER)
.document(getCurrentUser().getUserId());
mFirestore.runTransaction(new com.google.firebase.firestore.Transaction.Function<void>() {
#Nullable
#Override
public void apply(#NonNull Transaction transaction) throws FirebaseFirestoreException {
transaction.set(docRefVisitor, visitorMap, SetOptions.merge());
}
})
The docs say:
If the document does not exist, it will be created. If the document
does exist, its contents will be overwritten with the newly provided
data, unless you specify that the data should be merged into the
existing document
I experience that Visitor.NOTIFY_ON_CHAT_MESSAGE boolean is overwriting existing boolean at Cloud Firestore database Document. I though the SetOptions.merge() would not overwrite existing values?
Maybe I missed something about how Transaction works or this is a Beta related thing since CF is Beta
Regarding SetOptions merge() method as the official documentation says:
Changes the behavior of set() calls to only replace the values specified in its data argument. Fields omitted from the set() call will remain untouched.
So SetOptions.merge() method will only replace the fields under fieldPaths. Any field that is not specified in fieldPaths is ignored and remains untouched.
As a conslusion, if the document does not exist, it will be created. If the document does exist, its contents will be overwritten with the newly provided data, unless you specify that the data should be merged into the existing document, as follows:
// Update one field, creating the document if it does not already exist.
Map<String, Object> data = new HashMap<>();
data.put("Visitor.NOTIFY_ON_CHAT_MESSAGE", true);
docRefVisitor.set(data, SetOptions.merge());

Where can I write Parse Cloud Code functions for android?

Is it possible to write a cloud code function directly into android studio? If not where could I write one? I can't find it on my parse dashboard
thanks
Cloud code is only written in the express module of your app inside cloud/main.js file, you can create cloud functions there and call them from your android app.
Example:
Parse.Cloud.define("getPosts", function(request, response){
var query = new Parse.Query("Posts");
//TODO: query constraints here
query.equalTo("key",request.params.text);
query.find().then(function(results){
response.success(results);
});
});
and you can call this function from android as below:
public static void getPosts(String text, final onSearch onSearch) {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("text", text);
ParseCloud.callFunctionInBackground("getPosts", hashMap, new
FunctionCallback<List<Post>>() {
#Override
public void done(List<Post> object, ParseException e) {
//TODO: use search results...
}
});
}
you can see other cloud functions and parameters in the docs: Cloud Code Guide

Use of GenericTypeindicator when retrieving data from Firebase android

I'm using the following code snippet to retrieve value from the Firebase database in android. The code is working but i do not understand how, can anyone explain to me why i have to use the GenericTypeindicator.
dbRef.addValueEventListener(){
public void onDataChange(DataSnapshot ds) {
GenericTypeIndicator<Map<String, String>> gType = new GenericTypeIndicator<Map<String, String>>() {
};
Map<String, String> myMap = ds.getValue(gType);
}
}
Any Help would be Appreciated :)
The Documentation for the class does a pretty good job for explaining as to why you have to use it.
https://www.firebase.com/docs/java-api/javadoc/com/firebase/client/GenericTypeIndicator.html
Due to the way that Java implements generics (type-erasure), it is necessary to use a slightly more complicated method to properly resolve types for generic collections at runtime. To solve this problem, Firebase accepts subclasses of this class in calls to getValue (DataSnapshot.getValue(GenericTypeIndicator), MutableData.getValue(GenericTypeIndicator)) and returns a properly-typed generic collection

Categories

Resources