Update firebase database after specific time - android

I have a data field and time field ,user Enter data and time
After Writing data on firebase realtime Database I want to reset data field and Time Field to 0 after The specifed time in Time Field
I read about cloud function but I don't know to solve my problem
I'm new to firebase and it's cloud function Please help...
Data field will contain somedata
Time Field Will Contain data like 20 ,30 or 40 which represent time in mins
so after writing both to database
say if time field contain 20 ,so after 20 min to writing data in database, it should be reset to 0
Thanks in advance

The scenario you describe could be achieved in two ways. In my opinion, one can be cheaper and easier (no function involved but need to add some logic and a query to data on client side) if you could implement it which depends on your case.
Not the cheapest one: Schedule (cron type jobs) to scan your database regularly and check for the specified time and reset your data if condition is met. And this requires you to use Firebase functions and cron type services to configure it.
The cheaper way (although dependent on your case) in my mind would be to set your logic client side, so whenever a user is navigating to that data , check for the time and if condition is met reset the data client side without client noticing. This way, you don't need to set up functions, and you are not performing anything as long as no client has gone there (wherever that the data your mentioned is used in your app) Just keep in mind that this depends on whether you can have such scenario or your data has to be update regardless of users interaction with it. I have managed to redesign stuff whenever I have come across a case that needs periodic updates, etc.
More info on second option:
Imagine your users are checking for an order which can expire after some time. Your intention is to reset data when expiry time has arrived. Instead of resetting data via functions, etc, you can write logic so that whenever a client queries the orders, you check for expiry time and if expired, you perform what has to be done there and then, in addition to making sure your client won't see the expired order. Hope this makes it more clear. It's sort of a passive way of updating your data in db.

Related

Logic to update network requests using Work Manager

I have an application which fetches data from an API. SO basically, right now, the app works as such:
If connected to the internet, fetch data and use Android Room to store for offline use
If not connected to the internet, check if data exists in Room. If exists, display it. If it doesn't exist, display an error message.
I did some research online on how to implement an efficient offline storing policy and Google suggests to use Work Manager to queue requests and then send it when connected.
I actually want to know how to implement this ? (not the code but the logic, i.e should i schedule requests everyday to the API or every time it's connected to the internet ?)
If someone with experience with offline apps could help would be great.
My network requests are done through Retrofit and i already create a class that perform calls to the API.
Keep in mind WM (work manager) is designed to perform operations when certain conditions are met (e.g.: the user has enough battery, the display is off, etc.). So this may end up with your data not being updated when you need it. WM is good for operations you want to happen but are not critical to occur "right now". I'd say always use the Room DB as the single source of truth. If the data is in room, show it, if it's not, fetch it, if you can't, well, you tried. Send a message to the user. You can use a NetworkConnectivityListener to monitor connectivity and check if you have a pending query (you could store the parameters of this query in your Room database in another table for ease of use). So you'd query the DB, obtain the pending queries (if any) and execute them, update the data, and let the ViewModel/Repository decide if there's a context to show this data (UI).
I feel like you are very close to achieve what you need.
So in other words:
UI: Observes its viewModel for some sealed class xxx state to tell it what to do (show an empty list, show an error, pass data to a recyclerview adapter, etc.).
ViewModel: Using its viewModelScope.launch { ... } will call a repository.fetch(...) or similar. Your viewModel will fetch this data when the Fragment tells it to do so (e.g. the user pressed a button) or on some lifecycle event (onStart for example).
The Repository in this case normally exposes a flow (if you can use the experimental api) or a suspend function that can perform the following actions (that can vary depending on your business rules)
If the data is available in the Database, return it immediately.
If the data is old (or we still want to refresh it), then perform the network API (if there's connectivity to do so). If there's No connectivity, you could store this "pending" query in the database for later. You could also check if you have a pending query before doing any of this, perhaps it's outdated or perhaps you need to execute it.
In any case, once the query goes through, you insert the results in the database, and call the same method you used in step 1.
Don't forget to update your "pending" query if you had one (or if you use this).
With WorkManager, you could schedule the "fetch data from API" part to happen at some point (so your data will be kept more up to date), but I all really depends on the use-cases you have.

how much resources does firebase on()/addValueEventListener takes?

I see that Firebase website has a lot of documentation to help us optimize the usage of resources, however, I have not found a detailed example of the resources used.
This could be useful to me to understand how to build my applications and to better choose the strategy in terms of performance and cost.
TAKING ANDROID AS EXAMPLE
I understand that when i do a:
query.addListenerForSingleValueEvent(...);
all the reference is "queried" to the database so that is a single query but takes down all the object.
if i do:
query.addValueEventListener(...);
the connection is kept open, but will it keep making connections on time intervals?
Or maybe is considered like a single connection in terms of billing?
And after a change on the database, will it query all the object down again?
In general how much is heavier and expensive to make a single request vs using the realtime-db feature of listening to a reference?
Maybe there is a section in the docs that explain this but I didn't found it.
query.addListenerForSingleValueEvent(...);
all the reference queried" to the database so that is a single
query but takes down all the object.
It will listen once to the objects within inside the child you are querying, not all of the objects inside the database.
query.addValueEventListener(...);
the connection is kept open, but will it keep making connections on
time intervals?
It has no intervals, instead it listens whenever a change is made into your database, lets say you change certain value from your database and that will trigger your addValueEventListener. This will only consume resources when some value changes into your database, so the usage will be a variant with your database usage, instead , addListenerForSingleValue will fire just once to query your data and we can assure that it will consume less network resources than a listener that is always listen to some changes to bring into your app
Check this usefull link : https://www.firebase.com/docs/java-api/javadoc/com/firebase/client/ValueEventListener.html

What is the best approach to upload 1000+ records to a server that also contains images for each record from an iOS/Android app?

I have a app working offline. It is assumed that 1000+ records are created with images in each record during this period and whenever connectivity is established. What should be the approach to send all the 1000+ records to server that also handles any interruption between the network calls or API failure response.
I assume I have to send records in batches but how to handle the interruption and maintain consistency and prevent any kind of data loss.
I guess the best way here is to send each record separetely (if they are not related to each other).
If you have media attachments, sending of each record will take 2 seconds in average, if you uploading via mobile internet with speed ~2 MB/s. If you will send the large batch of records via each request, you must have stable connection for a long period.
You can send each record as multipart request, where parts are record's body and media attachments.
Also you have no need to check for internet connection, or use receiver for catching changes of connection state. You can simply use this libraries for triggering sync requests:
JobScheduler
Firebase JobDispatcher
Evernote android-job
I would suggest to use Firebase database API.
It has got nice offline/online/sync implementations.
https://firebase.google.com/docs/database/
And it is possible to read/write the data using Admin SDK for your NodeJS server:
https://firebase.google.com/docs/admin/setup
You can use divide and conquer approach means divide the task into small task and upload the data to the server.
1. take a boolean flag "isFinishData" starting with false.
2. starting upload the data on server from 0 to 100 records.
3. next record send from 100 to 200.
4. this process run until last record (1000) is not send .
5. in last record update set boolean variable true and exit from loop .
this logic would be work fine in IOS/android both.
Save your records in local Db and use ORMs for it. Use Retrofit which provide onSuccess and onFailure method for Webservice calling. To send data to server at regular interval you can use sync adapter.
1st I need to know how did you save image in local db ?
You need to create a service to catch connection status. Each time when connection is established, you submit your record as Multipart kind. You can you Retrofit/Asynctask.
Just submit 1 record per one Retrofit/Asynctask, it makes you ez to handle success/fail of each record.
You can run a single or multi retrofit/asynctask to submit one or more record, it's up to you.
If ur data has image, on server side, you have to handle process from ur server to 3rd server ( server to save image ).
This is a very broad question and it relates to Architecture, UI Experience, limitations, etc.
It seems to be a synchronization pattern where the user can interact with the data locally and offline but at some point, you'd need to synchronize the local data with server-side and vice-versa.
I believe the best place to start is with a background service (Android, not sure if there's a similar approach on iOS). Essentially, regardless of whether the Android app is running or not, the service must handle all the synchronization, interruption, and failure in the background.
If it's a local db, then you'd need to manage opening and closing the database appropriately and I'd suggest using a field to mark any sync'd records so if some records did fail, you can retry them at another point.
Also, you can convert the records to json array, then do a post request.
As for uploading images, definitely needs to be in batch if there's a lot of them but also making sure to keep track of which ones are uploaded and which ones aren't.
The one problem that you will run into if you're supporting synchronization from different devices and platforms, is you'll have conflicting data being synchronized against the backend. You'll need to handle this case otherwise, it could be very messy and most likely cause a lot of weird issues.
Hope this helps on a high level :)
To take on simple approach ,have 1 flag in your data objects [NSManagedObject] classes as sync.While creating new object / modifying an existing object change sync flag to false .
Filter data objects with sync value as false.
let unsyncedFilter = NSPredicate(format: "sync = %#", #(false))
Now you will have an array of objects which you want to sync with server.If you are sending objects one by one in requests.
On success change sync flag to true else whenever your function gets executed again on app launch/reachability status update, it will filter out unsynced data again & start synch.
As others have mentioned this is a rather broad question. A lot depends on both the architecture of the server that will receive the data as well as the architecture of the app.
If you have any control over the implementation of your backend I would recommend implementing a storage solution that allows for pausing and resuming of transfers. Both Google Cloud Storage and Amazon S3 offer a similar functionality.
The idea behind this approach is to be able to pick up the upload from where it stopped. In case of app crash or issues with internet connection you don't have to restart all from the beginning.
In your case I would still start separate uploads for each one of the records and store their upload progress.
Here you can find an example of how to use the pause / resume approach using the mobile SDK with Amazon https://aws.amazon.com/blogs/mobile/pause-and-resume-amazon-s3-transfers-using-the-aws-mobile-sdk-for-android/.
Editing adding reference to Amazon iOS SDK , http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transfermanager.html
Best way is to break the files into chunks of 100s and upload at intervals or when app is idle.

Mobile devices offline sync with webservice

Im am developing a webservice for an App that I am writing. I want to make the App offline accessible.
I made that webservice so that if you request JSON from the webservice you can give a date:
/color/colors/date/2014-03-01T12:00/
If you don't give the date you will get everything that is inside the database and that is active. If you give the date you will only get everything that is updated after that date.
Now my problem is that if I remove something from the webservice of from the App then it will not be synced and the other devices will never know that it is removed.
I could work with a field where I say that a record is removed but then I need to keep every record and I can't delete any record.
Is there a better way to do the syncing? Or what is the best way?
I think there is no possible way to detect the deleted entry's change, unless you send the information that the entry is deleted. The best practise you set a field in the table with integer type, then you can set this value on updates. You don't have to set it only 1 or 0, you can use bigger numbers (for example I used 30 on that entries, that I deleted on 20th march , on this day was a big code logic change. after that i knew when the status integer is 30, then i deleted this row after that date.) It may be a silly example, but you can implement your own logic.
It depends on how important it is to update the rest of the devices when a change is made.
If it is critical, then it would be worth implementing push notifications or something similar to each device to let them know about the updated situation. Otherwise, you would simply have the other devices poll the server to check for changes on their own accord, and the frequency or the trigger of this poll would depend again on how critical it was that they get an update. Maybes they only need updating when they visit a certain activity, so in that case you would only poll when you reach the onResume() event of that activity
Update
If you don't need to keep a history of the deleted record, then why can't you just delete it, and then when the rest of the devices update, you clear all and download a fresh set? If that is too intensive, you would NEED to have a reference to the id, which you could do in a table or use a special value in the field (like null, 0 or -1) to mark it. Otherwise there would be no way to reference it

How to cache and store objects and set an expire policy in android?

I have an app fetch data from internet, for better performance and bandwidth, I need to implement a cache layer.
There are two different data coming from the internet, one is changing every one hour and another one does not change basically. So for the first type of data, I need to implement an expire policy to make it self deleted after it was created for 1 hour, and when user request that data, I will check the storage first and then goto internet if nothing found.
I thought about using a SharedPrefrence or SQLDatabase to store the json data or serialized object string.
My question is:
1) What should I use, SharedPrefrence or SQLDatabase or anything else, a piece of data is not big but there are maybe many instances of that data.
2) How to implement that expire system.
I'd use SQLite for storage + have a last invalidated timestamp in Application subclass.
It would get compared against System.currentTimeMillis() on each data access call to decide whether a new set should be fetched. Have a thin proxy layer for that.
You can use the HTTP HEAD method to check the modification date on the server and see if you really need to fetch new data. Every time the application launches, and at intervals while it is running, query the server to see if the data has changed. This assumes the data is cached on the server and not dynamically generated at every request or dependent on which client makes the request.
Thus you need to store the data and date for each item. SharedPreferences should suffice if the data is a string of moderate length and there is less that a few kilobytes total. If there is a known upper bound on the length of the data then use a database, otherwise you could use plain files. SharedPreferences writes an xml file every time you commit.
You can create a Thread with a long sleep interval to do the periodic checks, or create a Handler and use postDelayed or similar to spawn a checking thread. Check items as often as your maximum for stale data. If you check every 10 minutes, you allow up to 10 minute old data, with an average of half that. Checking at launch will make things appear up to date in most cases anyway.
If all the items expire at once, then you only need to check the date of one item to know they should all be refreshed. If not, you could try to use conditional GET instead of checking the HEAD of each item.

Categories

Resources