I want to be able to recover from crash/closing the app or just device being disconnected.
Currently when I detect that the network is out for my Android device I save the Call created with RetroFit2 in a stack (to process later). If the user were to close the app or restart the device I lose the possibility to save these calls anywhere...
My question is the following, how can I save a RetroFit Call or an OkHttp3 Request?
None of them is serializable or nor can I convert them to strings from what I could see looking at the code.
Use android priority jobqueue by Yigit Boyar (one of the google android guys). It'll serailize your jobs, detect network changes (and respond accordingly) and persist even through device reboots (let alone app crashes). Plus a ton of other features. Just take a look. It is not exactly what you requested but it's a better solution. It's Magic.
Starting with v2, Job Queue can be integrated with JobScheduler or GCMNetworkManager. This integration allows Job Queue to wake up the aplication based on the criterias of the Jobs it has. You can see the deatails on the related wiki page. The Scheduler API is flexible such that you can implement a custom version of it if your target market does not have Google Play Services.
Try it and you'll be glad you did, as I've been. It filled the huge gap in my code that I spent weeks hacking together with spit, ducktape and faith.
Related
I'm new to app development and I am soon going to be developing an app for a local charity.
The charity is a dog rescue charity and the app will display information about dogs available for adoption.
The content will obviously need to be updated frequently, even daily, which will obviously not work constantly updating the app via the relevant app stores. What is the most common way to deliver content to an app?
My thoughts on previous experience would be to create a REST API and deliver the content remotely. Would an app allow this? Is there a method more generally used?
Thanks in advance.
You can save all the information to show of each dog available to adoption in a database, then make the app retrieve all the data from it every n time.
I recommend you to use Firebase, it is cross-platform (includes Android and iOS), and I consider it really good when starting using databases.
Here you can find documentation for every supported platform, and easy examples on how to work with it.
Good luck with your project! :)
I see you don't have clear specification on how often to update the app content and technical capability.
Use JobScheduler
Syncing to the backend (via REST API)to fetch the data is a battery drainer & there is no use in syncing data on device which is about to die, I would prefer Jobscheduler which will intelligently act as per various environment criteria met like charging/idle.
There are several facilities available to help your app schedule work. These include:
AlarmManager
JobScheduler
SyncAdapter
Caution: Exponential backoff is enabled on job dispactchers/schedulers
For 24-hour logic check here
Basically, there is a Google way, which suggests using Service for long running operations (which I use at the time). On the other hand, there are a lot of examples in community by honored developers, which avoid using Service and at most incorporate Fragment's setRetainInstance(boolean retain).
While Google has declared that a lot of bad stuff might happen if we don't use a Service, I still feel anxious because there are, it seems, so many projects leaving Service aside.
Can you consolidate the Google's case or provide suggestions for abandoning Service?
P.S. I'm developing "classic" rest-client applications.
P.S.S. I forgot to mention that Service is used in pair with ContentProvider(for cachging purposes, guard against system app forceshutdowns).
Thanks.
If the network request is very likely to take under a second, or if you don't mind it if your process terminates before the request completes, using simple threading from the UI layer is fine, IMHO.
But once the user leaves your app (HOME, responds to an incoming call, etc.), the lifetime of your process is limited, and it could be very short if you do not have a service to tell the OS that you're still doing important work for the user.
So, if the network request is more in the 1-15 second range, and you'd like to feel fairly confident that the work will run to completion, use an IntentService or something along those lines.
If the network request is likely to be longer than that, such as a large download, now you have to worry about the device going to sleep and such. My WakefulIntentService was designed for this sort of scenario, where it will keep the device awake long enough to get the work done, then let the device go back asleep.
Some developers use services for all significant network I/O, skipping them only for truly ephemeral stuff like thumbnail images to populate a ListView or RecyclerView. So long as the service is only running when it is actively delivering value to the user, this is perfectly fine.
I have been developing for Android for little less then 2 years, and I am still puzzled by this seemingly simple question.
When should one implement a service?
From my experience there are some rare cases but I am questioning this because on every phone there are quite a lot of them running and I doubt it's just a poor application design.
This is essentially core of my question but following are some of my experiences and thoughts about the subject which can explain my question in more detail.
In all apps that I have developed only one really required a service. It was a background sound recorder and I was using it as Foreground service with notification since I wanted buttons to be able to control it (like music players do for example).
Except this I never really saw a requirement for the constantly running service because:
A) Intent listeners (Manifest registered BroadcastReceivers) are quite a useful feature and using them as you know is usually enough for many use-cases (for example showing notifications).
B) If scheduled execution is a must one can subscribe to alarm events.
C) I know that service in Android is quite different then for example in Windows since in Android services are just a "package" to organize your code in and have a the system manage the lifetime of the object. Services use the Main Thread but it's customary to spawn new threads in them.
D) In the development documentation services are suggested for network communication and background calculations but I don't get why you should not just use AsyncTasks for that. I am a big fan of these and use them extensively for lot of things from downloading data from the internet to doing FFT calculations under time critical conditions.
E) I get the usefulness of Foreground services but why are people using background services so much (excluding the system apps).
Those are my thoughts about the SERVICE and I hope someone with more experience will be able to explain these PROS and CONS (along with others that I probably missed).
When should one implement a service?
When you have work -- delivering value to the user -- that:
Needs some time to complete, perhaps longer than you have time for in the component wishing the work to be done, or
Is delivering that value under user control (e.g., music player, controlled by play/pause buttons in a UI), or
In rare cases, needs to be running continuously, as it delivers value continuously
there are quite a lot of them running and I doubt it's just a poor application design
Some are likely to be poor implementations, either due to technical misunderstandings, or other concerns (e.g., making marketing happy) trumping making users happy.
It was a background sound recorder and I was using it as Foreground service with notification since I wanted buttons to be able to control it (like music players do for example)
That is a reasonable use for a service, IMHO.
Intent listeners are quite a useful feature and using them as you know is usually enough for many use-cases (for example showing notifications)
I assume that by "Intent listeners" you mean manifest-registered BroadcastReceivers. In that case, if the work to be done by the BroadcastReceiver will take more than a millisecond, that work should be delegated to an IntentService for completion. onReceive() is called on the main application thread, and it is not safe for a manifest-registered BroadcastReceiver to fork a bare thread, as the process could go away shortly after onReceive() returns. However, in these cases, the service is usually short-lived (e.g., do some network I/O and disk I/O, then go away).
In the development documentation services are suggested for network communication and background calculations but I don't get why you should not just use AsyncTasks for that
An AsyncTask is a fine solution for background work that is:
Requested by the UI (activity or fragment), and
Will take less than a second or so, and
Is non-critical
For example, if you are downloading avatars to show in a ListView, AsyncTask is probably a fine choice, whether you use them directly or use some image-fetching library that uses them internally.
Conversely, if the user buys an MP3 through your app, and you need to download that MP3 file, an AsyncTask is not a good solution. That could easily take over a second. While the download is going on, the user could switch away from the app (e.g., press HOME). At that point, your process is eligible to be terminated... perhaps before your download is complete. Using an IntentService to manage the download is a signal to the OS that you are really doing work here, adding value to the user, and so the process will be left alone for a little while.
Note that if the background work might take 15+ seconds, WakefulBroadcastReceiver or my WakefulIntentService is probably a good idea, so the device does not fall asleep while you are trying to wrap up this bit of work.
I can name some of the Service uses from my experience:
to implement
location listener,
sound module, generating various voices
in app content updates,
API, provide services to other apps
in app billing
Communication with webservices (if requests frequency is high)
actually (excluding 5.) they all are working for the whole app duration, they are using some of the other android services, also they manage their state. I suppose one of the important thing here is state management during application life cycle changes.
I prefer to look at AsyncTasks in a same way as Executors (ExecutorService), they should be executed sequentially and for small tasks.
In the android website, you can find a table when to use Service, Thread, or WorkManager (the new API for scheduling jobs, currently in alpha as of this comment posted). https://developer.android.com/guide/background/#table-choose
The website also state that you need to use started service only as last resort. The Android platform may not support started services in the future. Refer to this link https://developer.android.com/topic/performance/scheduling#services
You should avoid using started services that run perpetually or perform periodic work, since they continue to use device resources even when they aren't performing useful tasks. Instead, you should use other solutions that this page describes, and that provide native lifecycle management. Use started services only as a last resort. The Android platform may not support started services in the future.
If you consider UI and bound services, u would think that both can exist and not be doing anything for certian periods. In such scenarios, your UI can be recreated a lot of times however service does not. And this is where service is important. Lets say you are processing images and then rotate device you want processing to continue while UI is being recreated. You recording a voice and then rotate device. These are one of the places where I find service very important. (Having lot of heavy data processing, interaction with web, that could be few seconds)
I have developed android apps, and have a web server application which serves REST style JSON, to the apps.
My apps are strongly dependent on that web services but as traffic gets higher, users' complaint started, as force close problems. I am not sure but maybe my server (AWS small instance) may not answer all requests correctly or in time.
I am planning to retry the web request when a problem on getting json response arise instead giving the error/net-connection alert.
I guess there are many developers who integrates apps with web services, so what is the good practice on handling network problems?
Or is the frequency of such network problems acceptable?
I take about 10-20 problem per day.
I have about 200.000+ web requests per day, for a AWS small instance (1.7 RAM), dedicated to server Tomcat. I analyze the logs there is no clue, no error log. Also the errors are spreaded.
You need to start with analyzing the problem, and determine the root cause or root causes of your issues. You always need to take into account that
a network connection might drop
a users switches from 3G / WiFi
the android devices "thinks" it's connected while in fact it's not
Also, be very sceptical when using the Android ConnectivityManager / NetworkInfo. Only trust it when it states that it is not connected. If it is connected, check it yourself (as sometimes, user is on a hotspot and the only connectivity he has is with a login page).
The application needs to handle all these scenarios properly. The way it's presented to the user depends on the use-case (do you want the user to be informed of the error, do you silently ignore it and just retry, ....)
In terms of retrying webservice connections, there are several ways to implement this :
exponential backoff
periodic rescheduling
event-driven triggering
retry-after moratorium intervals
You need to start by putting sufficient logging both on the client (Android) and on the server (AWS) so that you can analyze the issues and draw the proper conclusions.
I think the answer to your problem lies in the design of your android app.
You need to take into consideration the worst case scenario and redesign your application to take that into account and recover. Dealing with the chaos monkey - jeff atwood.
Personally I never allow an android app to be in a state where it needs to force close. For any or all network connection I assume that the connection is down, lossy, not all data can be retreived and (finally) up and working correctly.
That way my app will degenerate gracefully. If it needs web access it'll make an attempt in a background thread allowing the user to continue using the app, it will cache previous requests and will retry until it gets a connection or gives a nice toast to the end user.
So I have read the LVL docs backward and forward, and have it working with my app. I have seen the questions about the response being cached. But it still leaves me wondering, based on some of the wording in the LVL docs, does Google want us to call the license checker every time the app is initialized? Is that the safest way to implement this? Using the ServerManagedPolicy like Google suggests, do we just call the license check, and either run our app or do whatever we choose if they fail? One of my small concerns is the use of network data. They drill into us the need to be cautious of using resources without informing the user, and it seems to me this is a use of network data without letting the user know.
To add to this, is anyone experiencing any type of delay to their app due to this code? Due to the nature of my app, opening it and then waiting every time for an ok to come through the network would definitely distract from its use. Should I cache the response myself, or am I way over thinking this?
You answered your own question; if you feel that calling the service every time you start would be disruptive (which it would, e.g. the user is out of coverage), then don't do it.
Google make no recommendations about how often to use the licensing service; it's down to how paranoid you as the application developer are about piracy, balanced with how much you feel constantly checking would annoy the user.
Ok, fair, only check it once in a while.. But where can you "safely" store the information, that you should check it once a day only?
Eg, the first time you start the app, you will check it. Result of LVL is valid: so you store the date of the last successful check. But where to store it? Using SharedPreferences ? Is this safe? Because if you have root access on your device you could access the preference and change the valid date (to either way in the future, an yes, ofcourse you can check that in the code :-))
PS. Sorry, could not make a comment :(
Call it every time you start the app. The LVL library, as shipped by Google, will cache the response and use it the next time the user starts the app, thus not requiring a network connection if they restart the application within the cache valid time-frame.
What you likely want to do is change the amount of time the cache is valid. By default, google ships with a fairly low cache-valid time, which resulted in some upset users who were outside of a network when the cache had expired.
Concerning LVL: Although the SDK provides a sample implementation, Google themselves, clearly recommend against using it "as-is".
http://www.google.com/events/io/2011/sessions/evading-pirates-and-stopping-vampires-using-license-verification-library-in-app-billing-and-app-engine.html
After watching that, I believe, LVL is not an option for apps sold for 1-2$. Furthermore, a failed LVL check (if no network is available) will piss off legitimate users.
while it is true, that you can implement some kind of caching LVL responses, it will always boild down to the question, in how far you want to protect against piracy at the expense of legitimate users?
And: developer time is limited, so maybe it is more worthwhile to put efforts in improving an app, instead off wasting to much time trying to cut down illegal usage.