I just started to learn Firebase for android a couple of weeks ago, and now I am creating a very basic chat application.
My problem occurs when I press the home button and then go back to the app. I think it calls the OnChildAdded() event again, and so it produces doubles. I don't know how to fix this. I'll be grateful if anyone could help me out.
This is the part where I am having trouble:
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//messageText.append(username + ": " + messageReceived + " \n");
Iterator iterator = dataSnapshot.getChildren().iterator();
String newmsg = null, theusername = null;
while (iterator.hasNext()){
newmsg = (String) ((DataSnapshot) iterator.next()).getValue();
theusername = (String) ((DataSnapshot) iterator.next()).getValue();
}
messageText.append(theusername + ": " + newmsg + " \n");
scrollView.postDelayed(new Runnable() {
#Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
},200);
}
Here is a picture of the emulator and the structure of my firebase console:
If onChildAdded() is being called multiple times for the same child, it is very likely that you have multiple listeners attached. You'll need to detach the listener when your activity becomes inactive.
// if you attach like this
var listener = ref.addChildEventListener(childEventListener);
// later detach the listener with
ref.removeEventListener(listener);
The best place to detach the listener depends on where you attached it. It is usually best to think of the pairs: onCreate()->onDestroy(), onStart()->onStop(), onResume()->onPause().
Related
I'm writing code in java (using Azure SDK for Java), I have a Service bus queue that contains sessionful messages. I want to receive those messages and process them to another place.
I make a connection to the Queue by using QueueClient, and then I use registerSessionHandler to process through the messages (code below).
The problem is that whenever a message is received, I can print all details about it including the content, but it is printed 10 times and after each time it prints an Exception.
(printing 10 times: I understand that this is because there is a 10 times retry policy before it throws the message to the Dead letter queue and goes to the next message.)
The Exception says
> USERCALLBACK-Receiver not created. Registering a MessageHandler creates a receiver.
The output with the Exception
But I'm sure that the SessionHandler does the same thing as MessageHandler but includes support for sessions, so it should create a receiver since it receives messages. I have tried to use MessageHandler but it won't even work and stops the whole program because it doesn't support sessionful messages, and the ones I receive have sessions.
My problem is understanding what the Exception wants me to do, and how can I fix the code so it won't give me any exceptions? Does anyone have suggestions on how to improve the code? or other methods that do the same thing?
QueueClient qc = new QueueClient(
new ConnectionStringBuilder(connectionString),
ReceiveMode.PEEKLOCK);
qc.registerSessionHandler(
new ISessionHandler() {
#Override
public CompletableFuture<Void> onMessageAsync(IMessageSession messageSession, IMessage message) {
System.out.printf(
"\nMessage received: " +
"\n --> MessageId = %s " +
"\n --> SessionId = %s" +
"\n --> Content Type = %s" +
"\n --> Content = \n\t\t %s",
message.getMessageId(),
messageSession.getSessionId(),
message.getContentType(),
getMessageContent(message)
);
return qc.completeAsync(message.getLockToken());
}
#Override
public CompletableFuture<Void> OnCloseSessionAsync(IMessageSession iMessageSession) {
return CompletableFuture.completedFuture(null);
}
#Override
public void notifyException(Throwable throwable, ExceptionPhase exceptionPhase) {
System.out.println("\n Exception " + exceptionPhase + "-" + throwable.getMessage());
}
},
new SessionHandlerOptions(1, true, Duration.ofMinutes(1)),
Executors.newSingleThreadExecutor()
);
(The getMessageContent(message) method is a separate method, for those interested:)
public String getMessageContent(IMessage message){
List<byte[]> content = message.getMessageBody().getBinaryData();
StringBuilder sb = new StringBuilder();
for (byte[] b : content) {
sb.append(new String(b)
);
}
return sb.toString();
}
For those who wonder, I managed to solve the problem!
It was simply done by using Azure Functions ServiceBusQueueTrigger, it will then listen to the Service bus Queue and process the messages. By setting isSessionsEnabled to true, it will accept sessionful messages as I wanted :)
So instead of writing more than 100 lines of code, the code looks like this now:
public class Function {
#FunctionName("QueueFunction")
public void run(
#ServiceBusQueueTrigger(
name = "TriggerName", //Any name you choose
queueName = "queueName", //QueueName from the portal
connection = "ConnectionString", //ConnectionString from the portal
isSessionsEnabled = true
) String message,
ExecutionContext context
) {
// Write the code you want to do with the message here
// Using the variable messsage which contains the messageContent, messageId, sessionId etc.
}
}
I've been stuck on this for months and I don't know what to do or where to look to solve it If you guys could point me in the right direction...
Basically, I have a simple chat room that will only ever involve two people and whenever a user sends a message I get two values: their username and their message.
At the moment this is my code for showing each message:
private void append_chat_conversation(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Log.e("Chat details: ", String.valueOf(ds));
chat_username = dataSnapshot.child("username").getValue(String.class);
chat_msg = dataSnapshot.child("message").getValue(String.class);
Log.e("Chat username: ", "" + chat_username);
Log.e("Chat message: ", "" + chat_msg);
}
messageView.append(chat_username + " - " + chat_msg + "\n");
}
As you can see when I get both values I append them into a simple textView in a scrollView in the chat window. However, I don't want that. I want to make it a bit nicer than just simple text. I just don't know how to show that layout below in the link with the relevant data in it (username + message).
Link to a picture that shows what layout I'd like.
Hope I explained it well enough, thanks for the help in advance.
I have a list of "Persons" profiles that contains some usual identifying information.
I'm able to add new entries programmatically without any issues.
I'm able to retrieve and display in a list the entries in firebase
The issue I am having is with retrieving the profile of the Person whose entry is clicked in the list mentioned above. The code for this is listed below. I have verified that thisPersonRef contains the correct path. As far as I can tell, the event listener is just skipped over/not triggered. I believe I am following the instructions and samples show at https://www.firebase.com/docs/android/guide/retrieving-data.html and https://firebase.google.com/docs/database/android/retrieve-data#attach_an_event_listener
The error I get is:
java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.bcll_tech.ptapp.Persons.Person.barCodeText' on a null object reference
I've also tried using addListenerForSinglevalueEvent as well as ChildEventListener and I get the same results. This makes me think that I must be missing some other step in the process.
Any help is appreciated as I've scoured the list and haven't seen anything quite the same.
Thanks.
public void onPersonSelected(String listRecordId) {
Log.d(logtag, "Activity: List item recordId = " + listRecordId);
final Firebase thisPersonRef = mPersonRef.child("barCodeId").child(listRecordId);
thisPersonRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Log.d(logtag, "PersonsListViewDetailsFragment: in listener. snapshot of " + thisPersonRef);
Person thisPerson = snapshot.getValue(Person.class);
Log.d(logtag, "From Get Data: Bar Code ID = " + thisPerson.barCodeText + "; Last name = " + thisPerson.lastName);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});
Log.d(logtag, "Activity: Get Person: BarCodeId = " + thisPerson.barCodeText);
}
Try like this
final Firebase thisPersonRef = mPersonRef.child("barCodeId").setValue(listRecordId);
and
Person thisPerson = snapshot.getChildren().getValue(Person.class);
reposting this question since I didn't get any responses the first time around. Parse doesn't appear to have any simple means of contacting them about this (which is frustrating), so I really hope someone here can help.
I am currently using Parse to create a messaging app. I have two fundamental ParseObjects in addition to the standard ParseUser, a Chatroom and a Message. A Chatroom contains pointers to the two users in the Chatroom. A Message contains the content of the Message, a pointer to the user who posted it, and a pointer to the Chatroom.
First, I create a list of all the Chatrooms that the current user is in. Then, I'm trying to create a second list of the most recent message in all of these Chatrooms (I have made it impossible to make a Chatroom without sending at least one Message first).
My code looks like this:
TextView mostRecent = (TextView) row.findViewById(R.id.mostRecent);
Date dt1 = null;
ParseQuery lastMessage = ParseQuery.getQuery("Message");
ParseObject chatroom = (ParseObject) roomList.get(position);
Log.w("Chatroom ObjectID...", room.getObjectId());
try {
lastMessage.whereEqualTo("chatroom", chatroom.fetchIfNeeded());
List<ParseObject> allMessages = lastMessage.find();
Log.w("# of Messages...", "Size of the list: " + allMessages.size() + ", Count of query: " + allMessages.count());
if (allMessages.size() > 0) {
mostRecent.setText((String) theList.get(theList.size() - 1).get("content"));
dt1 = allMessages.get(allMessages.size() - 1).getCreatedAt();
}
} catch (ParseException err) {
err.printStackTrace();
Log.w("PARSE ERROR", err.getMessage());
}
This code works for every Chatroom where the current user is the one who created the Chatroom and the Message in that Chatroom. However, whenever I have a different user attempt to start a Chatroom and send a Message to the original user, the code fails.
To be clear, the second user successfully creates both a Chatroom and a Message. I've verified that the Chatroom gets successfully added to the original user's list of Chatrooms, and that the Message contains a pointer to the correct Chatroom. However, for whatever reason, the Logs reveal a list size of 0 and a count of 0. I've even tried querying for the second user's exact message on the original user's account, and it claims the thing doesn't exist.
Any ideas? Could this have something to do with ACL? Thanks in advance!
NOTE: I've confirmed that both users are correctly included in the Message's ACL. What gives? Why isn't this working?
You need to wait for the query to fetch the data.
lastMessage.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> allMessages, ParseException e) {
if (e == null) {
Log.w("# of Messages...", "Size of the list: " + allMessages.size() + ", Count of query: " + allMessages.count());
} else {
Log.w("Exception thrown", e.getMessage());
}
}
}
I'm making an android app which uses bluetooth using phonegap and I'm having issues handling code because it get's called every 100ms.
I want to try if the issue occurs because my phonegap javascript code is to long causing delays.
To try this I want to dispaly the received message using a native textbox.
Is this possible? and How would I do this?
Thanks
Martijn
PS: I've tried using Toast but since I want to change the displayed value every 100ms this doesn't work.
Code
upon receiving a message this is the order the code is processed
bytes = mmInStream.read(buffer);
s_message = new String(buffer, 0, bytes);
String[] strArray = s_message.split(",");
mHandleReceivedThread = new HandleReceivedThread(strArray);
mHandleReceivedThread.start();
In the HandleReceivedThread:
if(strArrayReceived[0].startsWith("Pressure"))
{
if(strArrayReceived[1].contains("Pressure"))
{
double Pressure = Double.parseDouble(strArrayReceived[1].replace("Pressure", ""));
double PressureResult = Pressure/10;
String PressureValue = String.valueOf(PressureResult);
webView.sendJavascript("PressureValue = " + Pressure + ";");
webView.sendJavascript("document.getElementById('Pressure').innerHTML = " + PressureValue + ";");
Log.e(TAG, "Message fail: " + strArrayReceived[1] );
}
else
{
double Pressure = Double.parseDouble(strArrayReceived[1]
double PressureResult = Pressure/10;
String PressureValue = String.valueOf(PressureResult);
webView.sendJavascript("PressureValue = " + Pressure + ";");
webView.sendJavascript("document.getElementById('Pressure').innerHTML = " + PressureValue + ";");
}
}
this is basically what happens.
And this happens every 100ms , and for some reason the displaying of the Value has lag and sometimes the received message (which should be "Pressure,1500" , or a different value) is Pressure,1500Pressure , causing errors (which I've managed to fix). but this still isn't optimal.
The message is send correctly and if I use a simple chat app they are received correctly.
if there is anything else I should supply , just ask ;-)