I'm trying to implement firebase notifications. But I have trouble finding any documentation on how to retrieve custom data from firebase notification.
But in in code how to get the custom key.
I'm using FirebaseMessagingService.onMessageReceived to get the message data.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
}
You can check your custom data using:
for (Map.Entry<String, String> entry : remoteMessage.getData().entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
Log.d(TAG, "key, " + key + " value " + value);
}
To get specific key:
String value = remoteMessage.getData().get("<YOUR_KEY>");
Let A be your key, then you can easily parse this value by using the following code.
JSONObject json = new JSONObject(remoteMessage.getData());
Iterator itr = json.keys();
while (itr.hasNext()) {
String key = (String) itr.next();
if (key.equals("A")) {
flag = json.getString(key);
}
Log.d(TAG, "..." + key + " => " + json.getString(key));
}
Related
I'm writing a Game, where the users can join a Lobby to play together. Therefore I update the Lobby and the Users, stored in Firestore. The Lobbys in the Lobby-Collection contain an Id, creator, creationDate and an array of all Members (DocumentReferences to User Objects in a Users Collection). The Users contain an Id, name, mail and an active Lobby. Now, when I update the Entries in the Firestore, in there (Firestore) they seem to be correct.. but when I receive a realtimeUpdate (by adding a SnapshotListener) the array of Members seem to be empty.. but I just inserted the Users to the Array and they ARE saved to Firestore..
Maybe nice to know: I convert the Datasets i get from Firestore to local Java-Objects for better handling with UI things
I also have a local HashMap to more or less cache the Objects so i dont have to always load the from Firestore (I know there is already a cache in the Firestore lib.. but i think i need my own)
At the moment I write the changes directly to Firestore and wait for them to come back via RealtimeUpdate to then update my local Objects. I also tried to update my local Objects and then write them to Firestore.. but then I only append my Users to the Members-Array and the array contains mulitple References of the same user..
/**
* Get a Lobby Object from a DocumentSnapshot from Firestrore
* If the Object already exists it will be loaded from the "CacheMap"
*
* #param documentSnapshot DocumentSnapshot with the data from the Firestore
* #param feedback a method to call when the Lobby was retrieved
*/
public static void getLobbyByDocSnap(DocumentSnapshot documentSnapshot, IFeedback feedback) {
final String METHOD = TAG + " #getLobbyByDocSnap";
String lobby_id = documentSnapshot.getString(FIRESTORE_DOCUMENT_ID);
if (allLoadedLobbys.containsKey(lobby_id)) {
Log.d(METHOD, "found object in map for id: " + lobby_id);
feedback.trigger(allLoadedLobbys.get(lobby_id));
return;
}
Log.d(METHOD, "Could not find in Map.. generate through data");
Lobby lobby = new Lobby();
lobby.setId(lobby_id);
lobby.setPrivateLobby(documentSnapshot.getBoolean(FIRESTORE_DOCUMENT_PRIVATELOBBY));
lobby.setCreationDate(documentSnapshot.getDate(FIRESTORE_DOCUMENT_CREATIONDATE));
allLoadedLobbys.put(lobby.getId(), lobby);
//create all Members of the Lobby as User Objects
final List<User> members = new ArrayList<>();
List<DocumentReference> docmems = (List<DocumentReference>) documentSnapshot.get(FIRESTORE_DOCUMENT_MEMBER);
Log.d(METHOD, "get all members of lobby: " + lobby_id);
for (final DocumentReference docmem : docmems) {
/*docmem.collection(FIRESTORE_DOCUMENT_MEMBER).get()
.addOnSuccessListener(queryDocumentSnapshots -> {
Log.d(METHOD, "Found Members for: "+lobby_id+": "+Arrays.toString(queryDocumentSnapshots.getDocuments().toArray()));
//Convert DocumentReference to User-Object
for (DocumentSnapshot document : queryDocumentSnapshots.getDocuments()) {
Log.d(METHOD, "Get User Object from "+UserManager.class.getCanonicalName());
UserManager.getUserByDocSnap(document, o -> members.add((User) o));
}
});*/
UserManager.getUserByRef(docmem, o -> members.add((User) o));
}
lobby.setMember(members);
Log.d(METHOD, "Start getting the Creator of this Lobby: " + lobby_id);
//create an User-Object for the Creator
UserManager.getUserByRef((DocumentReference) documentSnapshot.get(FIRESTORE_DOCUMENT_CREATOR), o -> {
User creator = (User) o;
lobby.setCreator(creator);
Log.d(METHOD, "Got the Creator, now get the artist for: " + lobby_id);
UserManager.getUserByRef((DocumentReference) documentSnapshot.get(FIRESTORE_DOCUMENT_ARTIST), a -> {
User artist = (User) a;
Log.d(METHOD, "Got the Artist. All Infos collected for: " + lobby_id);
//Create The Lobby-Object
lobby.setArtist(artist);
Log.d(METHOD, "Save the Lobby to the CacheMap: " + lobby.toString());
//add it to the given list and trigger the feedback
feedback.trigger(lobby);
});
});
documentSnapshot.getReference().addSnapshotListener((snapshot, e) -> {
if (e != null) {
Log.w(METHOD+"+new", "Listen failed.", e);
return;
}
if (snapshot != null && snapshot.exists()) {
Log.d(METHOD + "*new", "Current data: " + snapshot.getData());
String update_lobby_id = snapshot.getString(FIRESTORE_DOCUMENT_ID);
Lobby update_lobby = allLoadedLobbys.get(update_lobby_id);
update_lobby.setCreationDate(snapshot.getDate(FIRESTORE_DOCUMENT_CREATIONDATE));
update_lobby.setPrivateLobby(snapshot.getBoolean(FIRESTORE_DOCUMENT_PRIVATELOBBY));
UserManager.getUserByRef(snapshot.getDocumentReference(FIRESTORE_DOCUMENT_ARTIST), o -> update_lobby.setArtist((User) o));
UserManager.getUserByRef(snapshot.getDocumentReference(FIRESTORE_DOCUMENT_CREATOR), o -> update_lobby.setCreator((User) o));
List<User> update_member = update_lobby.getMember();
update_member.clear();
List<DocumentReference> update_docmems = (List<DocumentReference>) documentSnapshot.get(FIRESTORE_DOCUMENT_MEMBER);
//update_lobby.setMember(update_member);
Log.d(METHOD+"*new", "get all updated members of lobby: " + update_lobby_id);
Log.d(METHOD+"*new", "members DocRef List: " + update_docmems);
/*for (final DocumentReference update_docmem : update_docmems) {
Log.d(METHOD+"*new", update_docmem.getId());
UserManager.getUserByRef(update_docmem, o -> {
Log.d(METHOD+"*new",((User) o).toString());
update_lobby.addMember((User) o);
});
}*/
getMemberList(update_docmems, new ArrayList<>(), o -> {
List<User> mems = (List<User>) o;
update_lobby.getMember().clear();
update_lobby.getMember().addAll(mems);
});
} else {
Log.d(METHOD+"*new", "Current data: null");
}
});
}
private static void getMemberList(List<DocumentReference> update_docmems, List<User> member, IFeedback feedback){
final String METHOD = TAG + " #getMemberList";
/*if(null == member){
member = new ArrayList<>();
}*/
if(update_docmems.isEmpty()){
feedback.trigger(member);
return;
}
DocumentReference docref = update_docmems.get(0);
UserManager.getUserByRef(docref, o -> {
member.add((User) o);
Log.d(METHOD, o.toString());
update_docmems.remove(0);
getMemberList(update_docmems, member, feedback);
});
}
The Realtime only provides the "normal" Data but not the array of references. When I initialy load the Data from Firestore i get the actual Data of the Firestore (not empty). But I want to get the whole Document, inluding the "normal" Data (id, creationDate, ...) and the whole array of members.
I already burned 1.5 days to solve this and I cant figure out, whats wrong..
Never mind, i got my error.... really stupid one ^^
in the part where i updated my objects, when the firestore changes.. i used the wrong/old DocumentSnapshot. So I used the inital Members-Array not my new updated one :D
should be:
List<DocumentReference> update_docmems = (List<DocumentReference>) snapshot.get(FIRESTORE_DOCUMENT_MEMBER);
instead of:
List<DocumentReference> update_docmems = (List<DocumentReference>) documentSnapshot.get(FIRESTORE_DOCUMENT_MEMBER);
Now i get my updates correctly :D
I am reading the data from the firebase database.Following is snapshot of the data stored in database.
In the snap string starting with "8SS..." is the uid of the user. Following is the code for retrieving the data from firebase database.
//To check if uid of current user and database user matches.
Query q = FirebaseDatabase.getInstance().getReference().child("Location").child(user.getUid()).equalTo(FirebaseAuth.getInstance().getCurrentUser().getUid());
q.addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
Log.d(TAG, "Yay!!");
User us = singleSnapshot.getValue(User.class);
String string = "Name: "+ us.getName()+"\nAddress: "+ us.getlat()+ us.getlon()+ "\n\n";
n.setText(string);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// read query is cancelled.
Log.d(TAG, "loadPost:onCancelled", databaseError.toException());
}
});
User class contains getters and setters.
The error is that only empty Text View appears concluding reading from database fails.
How to evaluate if query is true or false?
What is the error while reading from ValueEventListener()?
I tried using this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Location").child("8SS0uk4FmiPUtXP208Tx8Cqxt2z2");
And then calling on ref.addListenerForSingleValueEvent() but still nothing gets displayed.
I tried using this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Location").child(user.getUid());
This gives dataSnapShot : "DataSnapshot={key='-Kn...', value="latitude:.., longitude:..., Name:..."}. But this is not how I expected it to be.
The database structure should have been Location --> Uid --> Name : "Jane", .. .
This is my code for inserting data in the database.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser() ;
refDatabase = FirebaseDatabase.getInstance().getReference().child("Location").child(user.getUid());
DatabaseReference newPost = refDatabase.push();
//the push() command is already creating unique key
Map<String, String> mapname = new HashMap<String, String>();
mapname.put("Name", n.getText().toString());
mapname.put("latitude", Double.toString(lat));
mapname.put("longitude", Double.toString(longt));
mapname.put("user id", user.getUid());
newPost.setValue(mapname);
I solved this question by introducing multiple for loops.
So, the snapshot of my first child was dataSnapShot : "DataSnapshot={key='-Kn...', value="latitude:.., longitude:..., Name:..."}.
Below is the code to extract all the values and keys :
mRef.addValueEventListener(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "Children" + dataSnapshot.getKey());
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
String st = singleSnapshot.getKey();
Log.d(TAG, "Yay!!" + singleSnapshot.child(st));
st = "";
int count=0;
for(DataSnapshot singleSnap : singleSnapshot.getChildren()) {
Log.d(TAG, "String" + singleSnap.getValue());
//n.setText(us.getName());
if(count==0) {
st = "Name: " + singleSnap.getValue() + '\n';
}
else if(count==1) {
st = st + "Latitude: " + singleSnap.getValue() + '\n';
}
else if(count==2) {
st = st + "Longitude: " + singleSnap.getValue() + '\n';
}
count++;
}
final TextView rowTextView = new TextView(Menu5.this.getActivity());
rowTextView.setText((CharSequence) st);
ll.addView(rowTextView);
}
}
This gives single key and value pair for every unique id of created by push.So, I had to hard code the concatenation and display as the structure will remain same throughout the app.
Why are you using equal to and then getting the current user. .child(user.getUid()) should already be your current user which gives you the value of the child you are trying to listen to.
I think the uuid's are the children of "8SSOuk.......".
So it should look something like this:
FirebaseDatabase.getInstance().getReference().child("Location").child("8SSOuk.......").child(user.getUid());
I am implementing a notification service on the server, to push out notifications to both Android and Iphones.
The problem I am having at the moment is that the Android device which I am testing on, is only receiving the default message.
My code is as follows :-
Main Program
string smsMessageString = "{\"default\": \"This is the default message which must be present when publishing a message to a topic. The default message will only be " +
" used if a message is not present for one of the notification platforms.\"," +
"\"APNS\": {\"aps\": {\"alert\": \"Check out these awesome deals!\",\"url\": \"www.amazon.com\"}}," +
"\"GCM\": {\"data\": {\"message\": \"Check out these awesome deals!\",\"url\": \"www.amazon.com\"}}," +
"\"ADM\": {\"data\": {\"message\": \"Check out these awesome deals!\",\"url\": \"www.amazon.com\"}}}";
var smsMessage = new SmsMessageObj
{
smsMessageSubject = "Test Message",
smsMessageBody = smsMessageString
};
snsClient.SendPush(endpointArn, smsMessage);
and the SendPush is as follows :-
public void SendPush(string endpointArn, SmsMessageObj msg)
{
if (string.IsNullOrEmpty(endpointArn))
throw new Exception("Endpoint ARN was null");
var pushMsg = new PublishRequest
{
Message = msg.smsMessageBody,
MessageStructure = "json",
Subject = msg.smsMessageSubject,
TargetArn = endpointArn
};
_client.Publish(pushMsg);
}
Do I need to include anything more so that I can get the "correct" Android notification?
Do I need anything in the app.config?
Thanks for your help and time
I have resolved this question. All I needed to do was to stringify the Json. Maybe it will help someone else in the future. So what I did was :-
var apns_Json = "{\"aps\": {\"alert\": \"Check out these awesome deals_Apple!\",\"url\": \"www.amazon.com\"}}";
var gcm_Json = "{\"data\": {\"message\": \"Check out these awesome deals_Google!\",\"url\": \"www.amazon.com\"}}";
var adm_Json = "{\"data\": {\"message\": \"Check out these awesome deals!\",\"url\": \"www.amazon.com\"}}";
string smsMessageString = "{\"default\": \"This is the default message which must be present when publishing a message to a topic. The default message will only be " +
" used if a message is not present for one of the notification platforms.\"," +
"\"APNS\": " + JsonConvert.ToString(apns_Json) + "," +
"\"GCM\": " + JsonConvert.ToString(gcm_Json) + "," +
"\"ADM\": " + JsonConvert.ToString(adm_Json) + "}";
I am trying to get last offline time of a particular jabberId by this piece of code.
LastActivityManager lActivityManager = LastActivityManager.getInstanceFor(MessageService.getConnection());
lActivityManager.isLastActivitySupported(to + "#localhost");
Log.v(TAG, "Last Activity: " + lActivityManager.getLastActivity(to + "#localhost"));
LastActivity activity = lActivityManager.getLastActivity(to + "#localhost");
But I am keep getting service-unavailable exception.
I have checked the server configuration but this feature is implemented correctly from server side.
Have you added other jabber id as your roster. If not try adding them then check.
If you are using ejabbered then you can manually add roster from their admin panel for testing.
I used this code snippet to add roster--
Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all);
String number = datacollection.get(i).getNo().replace("+", "");
String jid = number + "#localhost";
Collection<RosterEntry> entries = roster.getEntries();
for (RosterEntry entry : entries)
{
System.out.println(entry);
if (entry.getUser().equals(jid))
{
rosterAlreadyAdded = true;
if (entry.getType() != RosterPacket.ItemType.both)
{
// Create a presence subscription packet and send.
Presence presencePacket = new Presence(Presence.Type.subscribe);
presencePacket.setTo(jid);
connection.sendStanza(presencePacket);
}
}
}
if (!rosterAlreadyAdded)
roster.createEntry(jid, jid, null);
I am sending a message (POST) to Google GCM server https://android.googleapis.com/gcm/send for sending a push notification to a registered android device. The POST body looks something like this:
{
"registration_ids" : [android_registration_id],
"data" : {
"message" : "Hello World!",
"update" : "You've got a new update",
"info" : "You've got new information updates too!"
}
}
Suppose that I don't know what all key-value pairs are being sent to me (gcm registered android app) in the "data" field and I want to enumerate and print them, can I extract the fields in "data" as a JSON structure?
For e.g. In the above example, I need the following as a JSON object:
{
"message" : "Hello World!",
"update" : "You've got a new update",
"info" : "You've got new information updates too!"
}
Bundle data = intent.getExtras();
Iterator<String> it = data.keySet().iterator();
String key;
String value;
while(it.hasNext()) {
key = it.next();
value = data.getString(key);
}
Try this. Using key and value you can construct initial json.
JSONArray array = new JSONArray(jsonBodyOfTheResponse);
for (int i = 0; i < array.length(); i++) {
JSONObject row = array.getJSONObject(i);
.
.
. }