My use case: chat application. The user wants to send an image message to the other user. But the upload process takes a while to the firebase, the user may not stay in that fragment or app till the upload is complete. User may even close the app assuming his/her message will be sent.
Question: How do we guarantee the message delivery after the send button is clicked irrespective of the app is active or inactive.
You might want to take a look at the new WorkManager API. In their own words - "a library for managing deferrable (meaning it doesn't need to be done instantly) and guaranteed (guaranteed to happen eventually even if app is killed or restarted)"
You should probably still send the instant message using other means though, but the actual uploading of the image can be deferred to the WorkManager. See this video
Related
I am trying to use WorkManager for my usecase. I have a chat application which is supposed to send messages in order so for that I can use unique work name with ExistingPeriodicWorkPolicy.APPEND:
workManager.enqueueUniqueWork("SEND_MESSAGE", ExistingPeriodicWorkPolicy.APPEND , sendMessage);
However there is another requirement; a message can contain several images that should be uploaded first before sending the message with uploaded image ids. I can easily utilize WorkContinuation mechanism so that when user hits send, app first uploads images and then sends that message but for perceived performance, I want to start uploading the image as soon as it has been picked wether or not the message has been sent yet. So if user hits "send message" button while image is being uploaded, I want to be able to create a chain from existing work.
Is such dynamic chaining provided by WorkManager? Any clever ways to handle this situation with WorkManager?
One approach that I can think of is when user hits send, start the send message worker and then inside doWork, block the execution and wait for image upload workers to finish getWorkInfosByTag("UPLOAD_WORK"). Is this approach good?
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 an app that has a Service that offloads photos that people are taking to the server.
Specifically, users are sent to the device's native camera to take a photo and then the photo is returned via intent to the app from which they "approve" it.
This act of approval saves it out to the file system and the Service comes along every x seconds, notices files awaiting offload and offloads them.
This all works fine.
However... in situations where there is bad connectivity but enough for the HTTP handshake, the app finds itself in a state where even though the offload is happening in a Service, at the point where the user is coming *back to my app from the photo taking (and Android is delivering the 4-8mb photo back to my approval Activity, my app hangs - sometimes long enough to provoke the "do you want to kill or wait" prompt. Eventually (if you wait) it does succeed in making its way back to the app.
I've verified that this is Network related because when the connectivity is strong (or when the app is in airplane mode - so the upload just fails instantly) everything works perfectly smoothly. The *only time this happens is when the offloader in the Service is hampered by a hinky connection.
So, my question is - what can I do about this? Is there some way I can isolate the Service to not have a larger effect on the app? Is my solution to write a partner app that sits on the device and just looks to offload the files (would that even solve the problem?).
HERE is the report I'm getting when the WAIT/KILL prompt is offered to the user. I'm not sure what to make of it.
The answer turned out to be that Services are actually running on the main Display thread (I was mislead by the fact that when you make an HTTP call in a Service you don't have to run it in a separate thread manually).
http://gmariotti.blogspot.com/2013/03/antipattern-freezing-ui-with-service.html
I have an application that uses AsyncTasks to make calls to a REST server.
Imagine that during a loading period (this is, the AsyncTask going to the REST server and gets data to the next screen) the user presses Home.
What is recommended:
Cancel the current AsyncTask(s) and restart when resuming the Activity
or
Continue the AsyncTasks but avoiding the startActivity by checking if the app is on background (to avoid the foreground of the new activity after sending the app to background). And onResume sending to the next activity
Worst case scenarios that you should foresee:
The app goes to background and is killed due to lack of memory
The asynctask fails due to timeout or other REST error
After both, the user goes back to the app...
Well I ll recommend Service which should use AsyncTask to do its work. Service will insulate your activity from orientation change or user exiting. AsycnTask will insulate from the UI thread being blocked. But do make sure to exit Service when you are done with REST api.
This will give you best of both. Also if you are not using DB as a local cache then you can try that too. So even if the user goes away, the service will store the fetched data in the DB and when the user comes back you can quickly display the screen.
EDIT: Just want to add IntentService are easy to implement.
Try Design Patterns for REST clients on Android by Google for more exhaustive explanation
Using AsyncTasks can get really messy during a configuration change. From personal experience I would recommend going down the IntentService/ResultReceiver route instead.
See this post for more info:
Restful API service
I guess what you want to know is which way is better from a users perspective. From my experience, a user expects the app to continue the download in the background, because if he presses home, he normaly either wants to check some other apps in between or he pressed it unintentionaly and wants to go back into your app as soon as possible. If a user wants to cancel the download, he normaly presses the back button or a specific button to cancel that is somewhere on the screen of your app. So as the user normaly wants to continue using the app, the more convenient behaviour of your app is to continue downloading data and hopefully already display the downloaded data to the user when he gets back into your app.
From a technical perspective, I would not use a service. I would just leave the AsyncTask running. And in the worst case when the app gets killed inbetween, the app automatically goes into the starting activity when the user gets back to the app, because the app is restarted anyway. In the case that the asynctask fails, you can check if the data has been succesfuly downloaded and if not showing the starting activity. You can easily implement this with storing the downloaded data in a variable which's initial value is null. If the variable is still null after downloading, the AsyncTask failed and you have to go into the starting activity. I think this is a pretty robust implementation.
downloading continues as does the android market app, but it shows a notification with the option to cancel. You can implement this, using a service to download.
I have been working on a chat application and I need some suggestions to go about it. I have a server. Whenever a user logs into my app, and selects some user by searching, and sends a message to him, it will be stored on the server. Then my app checks if any a new message has arrived for me. If any message comes, it will be notified to the user. For achieving this, I have followed this method to update the UI whenever a new message comes.
And when the chat continues for more than 3 minutes, the app starts becoming slow. How to go about the problem?
If the app is sluggish that means there is a memory leak somewhere, or you are over logging, or doing something that you shouldn't be doing on the UI thread. Maybe you're polling the server too much?
By the way using TextView for chat is primitive, use the transcript mode for ListViews.