I am writing a simple Android library. I have a couple of methods that I would like executed when certain activity events happen - like after activity got loaded or when the activity gets paused.
One way I could think of was to create a class that extends activity, and write my methods there, and then have "target" activities extend that class. This was all methods get called
But if the end user is extending some other activity already, this method won't work. Is there a better alternative?
If you need only provide support back to API 14 or higher, you might be able to make use of the application level activity lifecycle callbacks - see the Application.ActivityLifecycleCallbacks interface for details.
To make use of this you need to register an instance of this interface with an Application instance, using the registerActivityLifecycleCallbacks method. One way to get that would be to have the developer using your library initialise your library by passing their Application instance to it. This is what I do in an SDK that I maintain, and it seems to work nicely.
Related
First of all: I am rather new to Android App programming and I have a rather basic question:
Already with the sandbox app I am currently working on, the code in the Activity class get quite huge because all the callback methods / listeners (click listener, callbacks from GoogleApiClient) are in there (either by implementing the respective interface or by creating a private class). But I would rather put those into separate classes.
But the question that I ask myself is this: how would I then be able to access the class attributes of the activity class? Sure, I would then probably create setter/getter, but still I first need a reference to the Activity object. How would I get this?
Thanks and regards!
It's a really wide question, since the answer depends by your project and by your programming style. The first suggestion is: move what you can move in one or more fragment. All stuffs related to google play services can be nicely handled in a fragment for example. Listener and callback are UI related components, so they need a Context of an Activity to work, but you can split your UI (again) with Fragment and keep a piece of logic in a Fragment and another piece somewhere else. If you have some logic that runs in background, then you should consider using Service. I tend to have empty Activities, but this is not a rule.
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.
There are many examples of taking a screenshot using a reference to the current activity. However, in my case, I need to take a screenshot of an activity which comes from an external SDK (but still within my app). For obvious reasons I don't have a reference to that activity object within my code. I saw solutions using Instrumentation and UiDevice, but they seem to work only when implementing a testing application using the TestCase framework, while I need it to work in a normal application.
Is there another way?
Well, if anyone finds this question useful, here's the answer I found:
In your activity or service, call getApplication().registerActivityLifecycleCallbacks(), passing it an object that implements the Application.ActivityLifecycleCallbacks interface. That object will get a callback on every activity's onCreate/onStart etc. with a reference to the Activity object, from which you can get the view and take a screenshot. You can identify that it's an activity from an external SDK by its package name.
NOTE: Application.ActivityLifecycleCallbacks is only available since API level 14 (a.k.a. ICS).
The premise is I am writing a library that in itself uses and implements the IBeacon SDK.
My code has to implement that SDK, does things and if someone uses my library they dont have to interact with this SDK at all, so I'm making a higher level codebase you could say.
Now my code cannot use any activities by itself, its just a library, another user will then implements my code. So my code needs to consume the IBeacon events and do something with it without being an activity by itself.
So I would implement IBeaconConsumer myself and then the person using my library would just give me an activity / context and I would pass it to the IBeacon SDK.
Doing so results in the following problem (with proper mainfest code):
The activity binds its iBeaconManager object however onIBeaconServiceConnect never gets called.
See this stackoverflow question: Android IBeaconManager not connecting from activity
My vague assumption is this: the class implementing IBeaconConsumer is not an activity and its not the same class as the one I am binding the IBeacon service to and that might create the problem.
Its just very hard to debug since it all works, no errors, just no ibeacon activity - same behavior as if you forget to add the part in the manifest
If you want your IBeaconConsumer implementation to not be an instance of Activity or a Service, then you simply need to chain the bindService and unbindService methods to a valid ApplicationContext instance, and return that valid instance from the getApplicationContext method. This is not needed when you are implementing this interface with an Activity, because an Activity implements these three methods for you.
You can see an example of this in a related question here.
Is there a way to get the Intent, or any other information about how the app was launched (BroadcastReceiver,Service,Activity), within the Application, without adding code to all the class that can lunch the app (keep in mind that there are library class that I can't override.
I couldn't find anything within the Context interface, that could retrieve any data about that.
I thought about using a class loader, and query somehow what classes have been loaded to memory.
Is there a way to get the Intent, or any other information about how the app was lunched (BroadcastReceiver,Service,Activity), within the Application, without adding code to all the class that can lunch the app (keep in mind that there are library class that I cant override.
On API Level 14+, your Application can call registerActivityLifecycleCallbacks(), after which it will be called for all lifecycle methods on activities within your app. Using that, you can call getIntent() on the Activity that is supplied to your callback.
However:
That is only for API Level 14+
That is only for activities, not other components
Since onNewIntent() is not included in the callbacks, you can only readily get the original Intent that started the activity, not any Intent that caused an existing instance to come back to the foreground, if that matters