Android: Get Time Spent Per Activity - android

Firstly, I'm not looking for time spent on a given application. There is already "an app for that", com.android.settings/.UsageStats, and a good deal of supporting code in the AOSP frameworks/base/services/java/com/android/server/am/UsageStatsService.java, etc.
The code that I've examined so far does not seem to record elapsed time spent on particular <activity>s. I have thought to get this information two ways, but feel there must be something cleaner and simpler, that leverages more existing code. The ideas have been:
Instrument the base Activity class onPause() and onResume(), to hack in a timestamp, and log the info some place (probably a SQLite database.)
Instrument the Context class, to make note whenever startActivity() and friends are called.
So what do you think -- anything better than those options? Thank you in advance!

So what do you think -- anything better than those options?
Anything is better than #2, which requires custom firmware.
#1 is your only option within the SDK for API Level 13 on down AFAIK.
API Level 14 (a.k.a., Android 4.0) added in Application.ActivityLifecycleCallbacks, which you can register via registerActivityLifecycleCallbacks() called on your Application (e.g., getApplicationContext()). I haven't used these yet, but it would appear that you can arrange for a single listener to be notified of activities coming and going, avoiding forcing you to extend some common base Activity class with your desired logging.

Related

Android - Determine App Launches and Total Time as Top Activity

I am working on a solution or code that can be embedded inside of an Android APK to track how many times the app has been launched and how long the app has ran for. I know one way to do this is using the ActivityLifecycleMethods in API 14 and in lower versions of Android having code placed in all Activity Lifecycle events or by providing a base Activity class.
1) Is there a way to hook the ActivityLifecycleMethods without the developer having to make any changes to their code outside of dropping additional code into their App?
I believe this answer is no because even with an Enum Singleton it is not loaded until it is referenced. Also the Enum Singleton will go away once the activity is changed since a different class loader is used when activities change.
If I wanted to keep the Enum Singleton around would it be possible to store a reference to the applicationContext and thus it wouldn't be removed when the Activity changes? Is that what google means by
"There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton." on http://developer.android.com/reference/android/app/Application.html
2) I am not a fan of this solution for older API versions. It seems very likely developers could forget to modify their Activity Lifecycle methods or forget to inherit from the created BaseActivity. Are there any other unique solutions for these older platforms? Is there any other approaches that can be done to determine when an activity isn't running? Could any of the following work:
a) User a class loader to ensure the base activity with the proper metrics are always used
b) Implement some type of heart beat. Will a timer stop working if the app is paused or killed? Is there some other way? Could the ActivityManager be used?
You have many Analytic Agents like Flurry to do that.
When ever you want to track an event, you will add it to flurry and inturn it syncs with server after specific time.
You may use the same logic.
Better create a library file with following features:
Start Application
End Application and report time to db.
Track a specific event count and update to db.
Sync the data to server you like to.
Call appropriate events from your app.

Is System.exit(0) really that dangerous?

An application background service updates sqlite database. Therefore my activities are becoming outdated. Activity intents also contain outdated params so onCreate, onResume will crash the application. An easiest solution is to restart whole application. I don't want to add IFs to all onCreate, onResume methods in all activities to handle one special case.
I noticed that ACRA has following code executed after an exception has been handled.
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
However many people discourage use of System.exit(0). Is System.exit(0) really that dangerous for an Android application data integrity? Of course my code will close the database before existing.
Update:
I known how to use finish(), content providers, send broadcasts, read many answers here on SO, etc. However each of these approaches requires additional thousands lines of code. I implemented solution with System.exit(0) in ten minutes. The restart is so fast that it is indistinguishable from ordinary startActivity action. The db update/restart is done after longer user inactivity so the app is already suspended by the system. My app doesn't require real time syncing. During tests the application behaves correctly. This is quick and dirty solution.
Therefore I asked the question about possible side effects of System.exit(0). Not how I can do the design differently. I know that current design is not perfect.
System.exit(0) is an artifact from Java runtime, it isn't meant for Android. So in any cases using it would be worst solution.
Why don't you use Activity.finish() gracefully?
If you terminate the process you are living in, you'll loose most of the caching and restart time (~resume in the eyes of the user) for it next time will be higher.
Read more in Activity Lifecycle documentation on Android Developers.
Killing the process will not clean up any registered resources from outside the process. BroadcastReceivers, for example. This is a leak and the device will tell you as much.
You really shouldn't be updating the database schema from a background service. Do it when your activities resume.
If you are just updating your data, resuming an activity should validate the data specified by the Intent and tell the user if, for example, Item X is no longer there.
No tool is that dangerous if used carefully and for a specific, well thought off purpose.
However, In your case I do not believe System.exit() is the right way to go. If your application depends on data from a database, create a background service (or a few, depending on what you need) that will inform your application of changes and update the data. It is, in my opinion the right way to handle changes.
As for scenarios when you want to use System.exit() I personally sometimes use it when I can't recover from a critical error and no graceful degradation is possible. In those cases it is better to force all resources associated with your application to cease rather than just leave loose ends tangling around. To clarify, you should always use error handling before doing anything radical. Proper error handling is often the way to go.
But this is a very delicate topic and you are likely to receive quite a few diverging answers.
Therefore my activities are becoming outdated.
Use a ContentProvider and ContentObserver (or the Loader framework), or use a message bus (LocalBroadcastManager, Otto, etc.) to update the activities in situ.
Activity intents also contain outdated params so onCreate, onResume will crash the application
Copy the relevant "params" to data members of the activities. Update those data members as needed (e.g., from the handlers from the message bus-raised events). Hold onto that data as part of your instance state for configuration change (e.g., onSaveInstanceState()). Use this data from onCreate(), onResume(), etc.
An easiest solution is to restart whole application
It is not easiest, if you value your users, as your users will not appreciate your app spontaneously evaporating while they are using it. Do you think that Gmail crashes their own app every time an email comes in?
Next, you will propose writing a Web app that uses some exploit to crash the browser, because you cannot figure out how to update a Web page.
I noticed that ACRA has following code executed after an exception has been handled.
A top-level exception handler is about the only sensible place to have this sort of code, and even there, the objective is for this code to never run (i.e., do not have an unhandled exception).
There's an existing answer HERE that might give you some help as to why people say it's bad to use System.Exit().

Android share location service between multiple map activities

I'm writing an application with 3 mapactivities, and i've implemended a local service(like google tutorial) that recives update from location manager, to share location data from gps between these activities.
Now i want to put every activity in separated process to follow google's suggestion.
So my question is how I have to proced??
Implement and AIDL interface for remote services or register every mapactivity to location listener??
Thanks for answers and sorry for my bad english :P
If it's just a single application that needs location information, then using a remote service and AIDL is an unnecessary complication. The easiest way would be to have a local service with which the activities can bind, then have the service use sendBroadcast() to send location information. The activities can then register a BroadcastReceiver to pick up this data.
First the rationale:
That quote in the Javadoc is a bit... weird. If you understand "running" as being between onResume() and onPause(), then normally two Activities belonging to the same Application cannot "run simultaneously". You would probably have to mess with the Application class or the OS itself to have it behave otherwise.
To wit, I'm actually developing an app at the moment that uses several MapActivity subclasses and haven't encountered any problems so far (i.e. 40+h of development and testing, both on emulators and a device).
Therefore I would suggest:
Try to implement your app as a single-process activity with a local service and just run with it.
If you don't want to do that (can't blame you ;) ), or you encounter any problems, I would suggest starting out with a MapView, perhaps encapsulated within a Fragment. Here's a discussion to get you started.
In short, due to Android's practical fragmentation, keeping your Activities in one process and commiting more time by starting with a more bare-bones implementation will be a safer, ultimately less time-consuming and probably more efficient approach than artificially splitting your app and potentially gritting your teeth on the IPC. At least in my opinion.
After some research i think the best way is to implement IPC with a messenger like described in Android doc http://developer.android.com/guide/topics/fundamentals/bound-services.html#Messenger.. I'll test this solution an report here the result..
Best tutorial is http://developer.android.com/reference/android/app/Service.html#RemoteMessengerServiceSample where is implemented a 2 way communication from client and service..

Android StartActivtyForResult() from a Service

First I'm sorry for my english that is not so good :).
I am facing a problem to develop my app.
That is a general architecture scheme of my solution.
http://i.stack.imgur.com/ooTmE.png
To be quick, the app has to decode code bare but with two possible ways:
using exernal device (The constructor provides a sdk containing an android Service to communicate with the device),
use the camera of the mobile using the library Zxing which is possible to manage it with intent.
The goal of my own service is to manage some business code and make transparent the choice of the tool for the user.
I believed that was a good solution but I wanted to implement it and I had different problems.
My main trouble is that I cannot execute StartActivityForResult inside the service.
Do somebody have any suggestions for my problem whether a change in the architecture or a solution for the main problem?
#Laurent' : You have totaly right my service acts as an API adapter.
I will try to make the expected behaviour more clear.
I have an app that needs to recognize (real) objects which have QR codes on their top. This recognition action will be done several times by the user during the life of the app.
The user chooses to launch the recognition by clicking on a button (or otherwise but he knows that the recogntion will start). So no notification is needed.
The thing is he doesn't choose the way to do the recogniton. It is why, as you said, I implement an adapter.
The adapter chooses between :
Camera mobile or external device. The first is an activity coming from the Zxing library. The second one is a service that manages the external device. This service provides an interface to get back result.
One more thing, I need that my whole implementation (adapter and co) can be re-used by other apps that will also need to do recognition.
So my thought was to implement a service as an adapter to answer my two conditions (make transparent the choice for the user - and make the recognition available for other apps).
I hope you understand my problematic.
Given your architecture, your MyOwnService must act as an API adapter : it should provide a unified scanning API and address each external service specificities transparently.
Your expected behaviour is not clear enough to provide a solution that suits your needs but here are a few remarks that can be of some help.
Passive scanning:
Even if there are some workarounds : no activity should be launched from a service (not directly). Never. Bad. Services are background stuff, the most they will be permitted is to hint users with Notifications (this is point 2 of Justin excellent answer).
As a consequence there's nothing as a 'popup Activities' (and that's good!). If you need to continuously scan for barcodes, even when your activity is not run, then the only way to warn users is by using status bar notification.
Active scanning:
Inside your own activity you can bind to your wrapper service and make it start scanning for codebars. When it finds one it has to message your activity. Your Activity message handler has complete access to the UI to inform the user of your findings.
You selected Active Scanning in your edit, your problem is therefore to find a way for your service to actively notify your main application (the one that started the active scanning) that a new item has been scanned successfully.
You do NOT do this by starting a new activity (remember: this is bad) but you can bind to a service and/or use Messages between the wrapper service and the application.
I advice you take the time to read (and more time to comprehend) this android developer article on BoundServices and especially the part about Messengers.
A full example of Two Way Messaging between a Service and an Activity can be found in the following android examples : Service & Activity
Warning: designing robust, full blown AIDL-based services is a tough job.
Two ways you could solve this problem.
1) Have MyOwnService do a callback into MainActivity telling it to launch your ScanActivity.
- This is a better approach if MyOwnService's task is only going to be running while MainActivity is running and if the user would expect the ScanActivity to come up automatically.
2) Have MyOwnService create a notification that will let the user access the ScanActivity.
- This is a better approach if MyOwnService's task might be running longer than the life span of MainActivity. That way, you can let the user know, unobstrusively, that they might want to access the ScanActivity.
So finally I changed my architecture.
I make the choice to delete myOwnService and to create an intermediate activity that will be my API Adaptater.
This activity will have a dialog.theme to look like a dialog box indicating that a recognition is under execution.
If the recognition uses the external device this activity will stay at the foreground otherwise the camera activity will start (Being managed by the intermediate activity).
Thank to that I can manage my result from the intermediate activity and do not have an android strange architecture, keeping my business code for the recognition outside my main app.
Service was not the good choice.
Thanks a lot for you help and your time.

What is the preferred way to communicate between applications on Android (service vs. intents)

What is the difference between these two ways of interaction between applications on Android:
Implementing service in app #1 and using it in app #2
Handling intents and posting answers to the intents.
Interactions are supposed to be asynchronous.
What are pros and contras for each?
It really depends upon what it is you're trying to achieve. In the case where - as you ask - interactions should be asynchronous, there's no reason why you couldn't use Intents. This way has two advantages:
If it's a "general" request (something like "pick a photo" or such...) then it gives the user (and the operating system) a chance to choose the most suitable application. It's quite feasible that App #2 as you named it doesn't actually exist on the target user's device (unless App #1 specifically depends upon it).
App #2 can really take its time over whatever it is you've asked. If it's a user-centred task, then maybe it wants to launch an Activity and get user input, or such.
If you're looking for more technical advantages to this method: you don't have to worry about App #1 depending on generated class code every time you change the interface. When you write an interface using AIDL (this is how you implement the service model you named "1") the ADT will go away and generate a bunch of classes for you which you use to expose your remote service. Problems arise when App #1 has a different version of these generated classes to App #2. (And believe you me, the error messages associated with these problems are less than informative).
On the other hand, that's not to say that you should avoid the Remote Service model altogether; it has many useful applications. This is where my explanation becomes a little "hand wavy" but hopefully you will understand the gist of what I'm saying. AIDL interfaces give you much more direct control over the services you're calling. Instead of launching an intent, bundling in a bunch of data, and dispatching it in the hope that it will reach the correct Service (or activity, or other handler), then be handled in the right way, and eventually a result will get back to you, you directly call methods within a Remote class. The methods you call in that remote class are the ones specified by the AIDL interface written within App #2 (which functions like a server) - but you will quickly start to have to think about things like threads. You're directly calling code that lives in another process - which means that a thread belonging to App #1 is being given access to objects and methods in App #2.
How you deal with the fact that App #1 is calling code in App #2 is pretty much up to you, but the way I use (and I believe the recommended way, although if someone knows different I hope they will correct me here) is to use a Handler within App #2. When App #1 calls the AIDL interface, the code it calls sends a message to a Handler living in App #2, which then gets called by a thread belonging to App #2 - meaning you know which part of your app is accessing which members etc.
There are obvious advantages to this control flow, and to me it feels more "API-ish" - but that's not to say it's going to fit everyone's purposes. My experience is also that programming via an AIDL interface is much more error-fraught and fragile. Although technically it's always just doing what you told it to do, it's quite easy to tell it to do something wrong - or worse, misunderstand what you've told it altogether. I would say: exhaust other routes before thinking about writing an AIDL service.
On the note of asynchronous calls:
If you simply call code in App #2 directly, it's entirely synchronous.
If you use a message-handling interface, things are a little different. You can then provide a second AIDL interface living inside App #1 that allows App #2 to give you callbacks (this is what happens in the example on the official AIDL documentation for Android).
So you've got there two very flexable interfaces to interact between two processes. Both are good for different purposes.

Categories

Resources