I'm using google analytics for android with a dispatch interval (ie. tracker.startNewSession("xxxx", 10, this);). However, I noticed during development that the SDK kept printing something about the database being full and the last event not being stored in LogCat. So I decided to call the .dispatch() method manually after every API call figuring it would kill two birds with one stone:
Send events more often, which would in theory stop them from backing up and losing some events (as per the logcat entries I saw in development).
Save battery by sending any GA events while the mobile radio was active.
Once I released that, I noticed that my GA stats (pageviews, et al) were about 35% higher; which can only mean one of two things, either lots and lots of GA events were being lost before, or it's now doubling up on sending some events erroneously.
anyone have any thoughts on a good way to troubleshoot this? If it's now doing a better job of reporting mobile pageviews and visits, then this is great. But if it's not accurately tracking the data now because I'm manually calling .dispatch(), then that's bad and I should revert this change.
That's what I saw too when I increased the rate at which I manually called dispatch. Plus it does make sense : since they are storing data locally and batch-sending to the server, I wouldn't be surprised if some data got stuck for a few days. And since data is associated with the day it was sent and not generated you get skewed stats.
PS: Have you taken a look at the new example app then provide for the Android SDk ? They run everything in AsyncTask in order to improve dispatching and to not hit the Main thread with network access. I've further improved that by storing all events in a queue and running only one AsyncTask... need to put it on Github but haven't cleaned it up yet.
The EasyTracker sample app uses AsyntTask and network queues to improves performances.
As mentioned by bitbox this could improve battery life and have less lost tracks without have to manually dispatch.
You can download the jar and source of EasyTracker from https://code.google.com/p/analytics-api-samples/downloads/list
Related
I have an android app that needs to store critical information coming from a sensor. The sensor updates data every 5 ms. I need to persist each of these data points on internal memory in text files.
In the current scenario, I am collecting data points for 2 seconds in memory and then writing to the file at the end of 2 seconds to save battery life. However, under situations where the app crashes, I am loosing the critical data points.
Does anyone have any suggestions on how to handle this?
Is it a good idea to write the data point to the file every 5ms. Would this significantly reduce the battery life and increase the load on the CPU? If anyone has come across a similar situation, can you please share how you resolved the issue?
I would suggest you to study the reason of your app crash. If your app is crashing because of internal exceptions there is a better way of dealing with this thing.
Write a good exception management and use this blocks to write data to internal memory whenever there is an exception generated. Re-start the app after the data has been successfully written.
It you app is crashing because of external reasons and you are unable to catch exceptions, you have to think of some other way.
As your App is critical, I would look into setting up a DefaultUncaughtExceptionHandler by calling Thread.setDefaultUncaughtExceptionHandler in your Application class. This way in the handler, you can write all unsaved data, AND you can restart the app for continued handling of your critical data. I would put some seconds counter in there, to prevent an infinite loop of crashes. The Open Source ACRA library uses Thread.setDefaultUncaughtExceptionHandler, so you may get some idea from there on how to use it.
An additional idea is to write the data using a service in a separate process, search for "Remote Service". This way, even if the app crashes, the service will still be alive. You will have to setup some functionality on how to share the data between the app and the service. If the app is really critical, I would setup 2 remote services, one that gets the info from the sensor (and caches it as a backup until confirmed that it's written), and one that caches the data and writes it every few seconds. Each service should also have a DefaultUncaughtExceptionHandler as above. This is in addition to the actual app, that will have the user interface. Though it is a little waste of resources, but for critical data it is not wasted.
i donot think there's a good method. What more important is to avoid crash maybe
Instead of writing to a file every 5 ms, which will be a costly operation, you can save data to SharedPreferences every 5 ms and every 2 sec, save the data from SharedPreferences to a file. SharedPreferences content won't be deleted even if app crashes and hence you will not have any data loss.
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.
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.
The Scenario: My App has many activities. At the end the user uploads his all data in just one click.
The Problem: A problem might arise if the user is on the move and goes out of service(internet service / poor connectivity), then he/she couldn't upload the data.
In this context I want to know what might be a best efficient approach.
I have thought of one approach. If due to poor connectivity / no service I will save the data locally in SQLite. Keep a thread alive when user opens the App next time to check if service/connectivity available. If yes, it will be uploaded instantly.
I will be eagerly waiting for your comments.
Save all your data to SQLite with a sync flag. Use a service to constantly check for unsynced flags, and try to send to server in the background, update the flag when sync is completed.
Another approach if you are syncing to a direct SQL Server from SQLite, you can set transactions or batch updates, so if connectivity fails, it will revert back the transaction.
For learning how to upload data I recommend watching Google I/O 2012 - Making Good Apps Great: More Advanced Topics for Expert Android Developers : http://www.youtube.com/watch?v=PwC1OlJo5VM# from 16:43. It deals with efficiency and impact on battery life.
To summarize the video:
Do one large upload instead of several small uploads due to how the phone radio works, and try to minimize touching the network.
On a lower level do as user370305 said, try to upload the data, if there is no connectivity delay the upload for the next time the user opens the app or clicks the upload button.
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.