I've just added the required code to my Android app and released the update to market.
Thinking about it though, I wondered what the data usage was like. Analytics doesn't send the tracking data immediately, instead it sends cached data at a set time interval or manually with a call in your app.
In my app I do this every minute. I don't think this is excessive as my app probably won't be open for long periods of time between uses.
I have three activities in my app that each track as a pageview. If the main activity is loaded it is tracked once. If nothing happens (i.e. no reloads or loads of other activities) after this one tracked pageview, will it continue to send data or will it know nothing has changed and therefore only send further data when more pageviews are tracked?
Cheers
Google's library works on a queue system. That being when you activity is loaded you have a call to track that page view. That single call will place a page view on the queue. Your timing code will take everything out of the queue and send it to the server. Once it's sent there is nothing left on the queue and it won't send anything when executes again in a minute. As long as there is nothing in that queue the polling cycle will look at the queue see there's nothing and go back to sleep waiting for another minute before checking to see if something new is there and repeating.
If the user shuts down the app and reloads it. Then the code will execute that page track statement again putting something back on the queue, and then it will send another page view.
It's important where you put that page track statement so that it sends it once per start and not during resume() or some other life cycle method that could be executed lots of times as the user jumps between views.
It won't keep sending the page view over and over on every polling cycle of your pumping thread.
Related
Since lengthly operations can't be done inside onBindSlice(), I am fetching data from server from onSlicePinned() method and then showing it in slices. But I can't understand when is this function called.
I thought it would be called every time we fresh start Assistant (i.e. starting Assistant after killing it). It is working while testing on Slice-Viewer app, every time i kill slice viewer and start again then onSlicePinned() is called along with onSliceBind(), but not in case of Google Assistant. So is this a bug or should be the way it is?
And if this is how onSlicePinned() should work, then is there any way i can fetch data every time onBindSlice() is called after starting app.
To load content from a server into a Slice you should follow the delayed content best practices here:
https://developer.android.com/guide/slices/templates#delayed_content
The tl;dr is, you should return something immediately, then go off and load/process your content, once the content is ready, call notifyChange() which will result in onBindSlice() being called again where you can return the Slice with the new content.
I hope I can explain this well ...
I am trying to understand better how to handle HTTP callbacks in Android, so I have created a simple app that uses Volley for HTTP requests. It only has a button that triggers an HTTP request to a service that, basically, just updates a number in a database and sends it in the JSON response after 5 seconds. The Activity gets the response and displays the response in a TextView. I am testing it in a real device that has enabled the "Don't keep activities" option in Settings - Developer Options.
This is the scenario I am testing:
Start App.
Tap the button that triggers the HTTP request.
Inmediately after tapping the button, tap the device's home button to send the app to background. onDestroy method is called because of the "Don't keep activities" option.
Wait a few seconds for the HTTP response. I can see the device gets it because it is printed in the logcat monitor and the database is updated.
Before running the callback, I check that the activity is still alive. Since the activity has been destroyed, the callback is ignored. If the app is restored from background, there is no crash but the Network Response is missed. Also, if I tap the button again, it sends a new HTTP request and increases the number again ...
So, the questions are:
Which are the best practices to deliver network responses to the UI? I mean, if instead of a simple operation let's say it was a register form and I get a phone call or something that forces me to send the app to background, where anything can happens, how can I make sure to not miss the network callback? Is there something that could delay the callback execution until the app is again in foreground?
Is there a way to save a Bundle like the one in onSaveInstanceState after onDestroy has been called and restore it when app is again in foreground?
Let's say the information that the HTTP response contains is sensitive. Is there a recommended way to handle this case? I was thinking to save the response in the internal storage and check for it when the app is again in foreground, but I don't know if it is possible to do that after onDestroy has been called, or if it not a good idea with sensitive data.
Thanks in advance!
1)YOu can never miss the network callback. You'll be called even if you're in the background, unless your entire app (not just the activity is killed). You'll just get the callback while backgrounded.
2)No. If you need the result of a network call the next time the activity starts like that, I suggest you use a Loader to load the data. That way you can query for the Loader results next time, and start the request only if needed.
3)Do what I suggested in 2 and there's no need for this question, its all in app memory.
I'm using Robospice. I want to write some reusable code to stop ProgressBars and ProgressDialogs as soon as pending network requests have cleared for the current activity. However, I'm running into a couple of problems.
I'm watching when requests have completed by instrumenting a custom SpiceServiceListener to call my custom callbacks implemented within each activity. During onRequestAdded(), I show any Progress UI element. During onRequestSucceeded(), onRequestFailed(), and onRequestCancelled(), I check getSpiceManager().getPendingRequestCount() to see if it reaches zero and then hide any Progress UI elements.
The pending request count never reaches zero in my app (at least inside these three methods), but it seems to stop at one. This is true even though I can see from the Retrofit logging that my requests all appear to be completed.
Is the pending request count global or is it specific to the current Activity and its spice manager instance? Is there a better method to watch for all requests finishing within the current activity?
I have an answer. I missed instrumenting onRequestProcessed(), so the number of pending network requests never appeared to reach zero. The pending request count now does reach zero.
I still don't know if the count is global or local to the current activity and its SpiceManager instance, but I'm getting useful results from my new code.
My Widget has two buttons for right and left navigation with in the widget. If I have a set of data then I switch between data using left and right arrow button. To update data I make a Http Call every minute. If http call takes time to return, my button clicks start getting accumulated and get suddenly fired in series after a pause of 7-8 seconds. I am using pendingIntents for buttons and receiving it in broadcast receiver of widget.
Button clicks work fine if HTTP call is fast.
But if HTTP call is slow to return, and I click on let say 10 times on right arrow, while clicking nothing will happen and after 7-8 secs 10 clicks will be fired in a flash.
Please suggest how can I stop my button clicks getting blocked and then getting fired in a row.
Is the slowness of HTTP call the actual reason of buttons getting stuck ?
You should not make HTTP call from your UI thread, so make sure you use an AsyncTask to perform any i/O or networking operation.
AsyncTask
Its probably because your doing the HTTP request on the UI thread which is not a good idea as HTTP request can take time as can other network tasks or I/O tasks, and android will detect this and may present the user with ANR message (App not responding) and ask the user if they want to force close the app.
You would need to run the HTTP request within an ASyncTask that the onclick event would fire. This way, a new thread would be created for the HTTP stuff while the user interface can carry on working and accepting user input instead of locking.
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.