In Android, i have a socket keeping real-time communication with the server.
This app socket is being controlled by a service, that starts on boot and / or whenever a request is being emitted by the app.
Because I cannot depend on Google PlayStore, I fully control the sending + receving of push-messages manually.
Whenever a new push-message arrives from the server, the socket-service sends a local broadcast message and the listening activities can follow there own action.. If no activities are found, a default android notification is given to the user, saying '[ap] You have {n} new message(s)'...
This has its stability problems (the service can be shut down by the OS when low on memory for example) but its okay.
Now, consider the following:
I have multiple activities that listens-for and shows a count of unread messages.
HomePage
ConversationsOverviewPage
'The' conversation page (chatpage)
Each activity can be on the foreground, but can also be in memory for when the user back-presses and goes back 1 activity. So in Theory, there can be a situation where you want to update different/multiple activities at once.. This prevents having to 're-load' the unread messages from the server when the user gets back to a 'savedInstance'. So the broadcast pattern works best I think.
What is best practise for keeping global track of unread messages, while minimising the server trip on every activity instance:
Very simpel: Make a server request on each and every activity instance, and write update code again for every activity. But this results in the user seeing a delay, as it takes a second before the app receives data from the server and show the 'unread-messages' balloon.
Simpel: Have a global class.. Holding the unread messages for each conversation, But I feel this can give problems with data being incomplete.. Especially when the app is not 'active'
My old vote: Have another service thats keeping track of the unread messages, that starts on boot (just like the socket).. Only when the service starts / boots, it will requests all unread-messages data from the server. Each activity can than 'ask' for the unread-messages data and don't have to worry about it anymore.
But this could be overkill?
My new vote: Keep the socket-service, and add a separate class to this service.. That holds the unread-data.. But this also does not feel to be right.. As the activity would have to ask the service something out-of-scope.. Its not the sockets concern to manage unread messages (separation of concerns), right?
Any thanks from experienced developers is much appreciated!
Third options is ok. Not sure where is overkill exactly. Obviously you shouldn't download all unread messages on every boot or socket reconnection. The most important rule of thumb is to load data when the app really needs it. Few moments about how I've developed about the same app:
there is socket Service which handles connecting, disconnecting, sending data(messages) and receiving data.
there is Notification manager which receives events from SocketService. It saves new data which comes from server and decides which broadcast notification should be sent.
when socket is connected it receives state data from server:
dates(timestamp) of last update for every chat. For instance if local database contains that chat A was updated yesterday but freshly received data from server says that the chat A was updated few seconds ago you need to broadcast event like chat A has been updated since last connection and save update date. If there there is any activity which somehow show the chat A it loads(through http or whatever) new data.
last messages for every chat. The app just compares locally saved last messages and freshly received. If there is new one the app again broadcast event like there is unread message/messages from user x. If there is visible activity which shows updated chat it updates data otherwise the app shows notification.
So the basic flow of handling unread messages is next: connect to the server > check if there is data about unread messages > save new data to the local database > broadcast events about new data.
And I would recommend you to use GCM and socket connection simultaneously. GCM really helps to keep data updated. It wakes up a phone and sometimes delivers data when socket connection just could not be established due to network problems.
Related
so I'm working with realtime database and I'm trying to make a chat app for practice.
I want to add the message to my list then let the message item inside the list upload the message to the server, I'm also showing an indicator that tells the user if the message is being uploaded, there are other approaches to apply this but I want to go with this one, anyways.
there isn't any problem when there is an internet connection. the problem is when there isn't any internet connection, the message is added to the list and the indicator appears, when the internet connection returns everything works fine still.
but if I send a message (while offline) and then leave the chat room and return to the chat room, the messages will get loaded and the indicator won't appear altho it isn't uploaded to the server (the data is cached now).
I want to find a way to tell if the data has been uploaded or not? I don't want to check the server to see if the node exists, I can't do that to every message it will cost too much, thank you.
If you enable disk persistence, Firebase keeps all of its pending writes in its disk cache. When the app restarts, it reads those pending writes and starts trying them. This is usually the right behavior for your users.
Unfortunately there is no built-in way to persist completion handlers for the Realtime Database. So upon a restart it becomes impossible for you to detect when the pending writes have been committed on the server.
So this typically means that you need to do something custom to detect the situation, and will have to determine for yourself whether the use-case is worth the effort.
If your messages are in some way ordered/timestamped (for example, if you add them by calling push()) you can keep track of what the last message is for which you received a confirmation from the server. That way you will know when the client restarts, which messages may not have been sent to the server yet.
Your onDataChange or onChildAdded will be called for those unconfirmed message straight away though when your app restarts, so you'll need an additional mechanism to detect when those unconfirmed messages are written on the server.
The best approach I know if is to write a "dummy" message when the app starts. Since the pending writes are treated as a first-in-first-out queue, your new dummy message write will be sent to the server after all the pending writes from the previous run. So when your completion handler gets called for this dummy message, you can be sure that all messages before it have also been committed (or rejected in case they violate your security rules).
Firebase cloud functions fires an onFinalize event when a file has been uploaded to the storage. So you could probably write a cloud function like this.
exports.uploadedServer = functions.storage.object().onFinalize((object) => {
const filename = object.name
//mark this filename or filekey as upload complete
return
})
You should be able to find more explanation here.
I have been trying to develop an android app like whatsapp, hike, etc....
I'm using SQLITE DATABASE to store messages local including images byte-codes.
I'm using the Runnable Handler with postDelayed() method of 3 seconds, which means every 3 seconds, the application connects with server for new messages and status be drawn, updated in listView and saved in sqllite database.
Now I'm facing trouble if the number of incoming messages are more say 150-200 messages.... the handler re-launch the code before the previous all 150 messages stored in database.
handler = new Handler();
handler.post(runnableCode);
Runnable runnableCode = new Runnable() {
#Override
public void run() {
if (check.check(1)) { //Check for Network Connection
asyncExecute = false;
getNewMessages(); //Calling method of asynctask for New Messages
}
handler.postDelayed(this, 3000); //Run this every 3 seconds
}
};
So, what I want is, till all my messages get saved in database and images downloaded completed, the handler should not be called. After saved and downloaded fully, the next handler should be called.
Tell me the best way to achieve this.
The way you did it may work but it's not a good way of doing it.
The way you got your solution together have a huge performance problem of consuming a lot of battery from the celular radio by keeping keeping it awake everytime even when the server doesn't have anything new.
If you want a more detailed explanation about this you can check it here.
To solve this problem you can do it in two ways:
1- Implement Google Cloud Messaging(GCM) on your app and server. When the user first opens the app you register the device to GCM, get key generated for you representing your device and send it to your server so that you can save it along side the user information.
Whenever a message comes for this user, all you need to do on your server is to look for the user devices IDs(multiple if you let him sign in on different phones at same time or single) and send a message to GCM passing the device id and the payload.
On your app side you can implement a broadcast receiver that waits for incoming GCM messages and you process them as you like.
2- The second way, that I think it is simpler is to user the new GCMNetworkManager to help you with this and also some more features as scheduling tasks etc.
Have you thought on a bidirectional connection with the server? If you make one for example, with WebSockets the client could just need to wait for new updates coming from the server in real time.
Here you have an example of socket.io (a WebSockets library) working on android:
Native socket.io and android
Another library including support for HTTP, Websocket, raw sockets and socket.io
AndroidAsync
I develop client-server app. Android client get real-time text data from server.
While app still active(activity on foreground) data show on screen.
Background service connect to server and sending intents, BroadcastReceiver on activity receive it.
When user leave activity(activity comes into background) BroadcastReceiver detach and service only show notifications about new data.
I have 2 ways next:
1) Service will save all new data to container, user after returning to activity open this container and draw data. In this case my question is: What the container should i use? What's thread-safe container use to communication beetween activity and service?
2) Service don't worry about save data just notify, but user after returning to activity should send request to server and get all data. In this case user maybe wait a long time.
Second way more simple than first, but force user wait isn't good.(async don't solve it)
What are you using in your projects? I think this is common case, but google doesn't help me, probably my search was bad.
I'm developing a simple multi-player Android game that communicates with its Game Server using Java Sockets. And to create non-freezing UI, I decided to make Service class in Android app to communicate with server over the Socket connection. Data exchange is done in JSON format.
Now the thing is, during entire game play, a single Socket connection will persist, and data exchange will be done from-and-to the server, but based on events happening on game client running in Android.
Eg; When user taps a button, some data is sent to server and server responds back with some data, until then, client will wait, when data arrives, UI on the activity will be updated, and client will again perform some action, and again that data will sent to server, and so on.
While the client is waiting for data from the server, I'll disable the controls on Activity such that user doesn't perform any actions until data arrives from server, and I'll also show waiting dialog on Activity to let user know that app is not frozen and is waiting.
Now, as Android service primarily works with onCreate(), onStart() and onDestroy() methods, I believe it executes something in background without any user intervention. So in case of my app where I need some input from user (or wait until user provides it) to send it to server, how I'll be using Service class in this case? Also, is there any other option I have apart from using service in such a scenario.
Also, note that I have two activities in my app which will be communicating with the server using single Socket connection.
I'm writing an Android App that receives text messages from a server via HTTP. I have a button on my App labeled "Poll". When I press this button, the App Polls the a server via HTTP and fetches some text messages.
These texts messages are to be sent out via SMS. What I would like to happen, is for there to be a background queue where these messages are added to. As soon as a message is added to the queue, the queue must immediately be attempted to be "flushed" (i.e. send all pending SMSs over the network). If the sending fails, the App must retry by itself every 60 seconds indefinitely.
What is the best way to achieve this? I guess I'm looking for some form of implementation where an IntentService has a timer that expires every 60 seconds, but can be forced to be expired on demand once a new text message comes in.
I'm ok regarding SMS functionality, as I've been following this guide: http://mobiforge.com/developing/story/sms-messaging-android
It's just the queue handing I need some help with.
Any help is appreciated, thanks