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.
Related
Currently we're making an Android library that contains an Activity. We want to control the exact flow and the state of the activity, but give the user that implements the library control what the UI looks like. Meanwhile, we want to expose the least amount of internal classes.
The SDK user may decide where views are placed, sizes, colors; we decide on what happens on onClicks and provide the texts of TextViews.
The activity makes use of a Model-View-Intent pattern, so we want to expose the immutable state. Without adjustable UI, the Activity and all its' classes are internal. With adjustable UI, a lot more classes have to made public. This increases the risk of breaking changes on updates and exposes our logic.
To expose the UI, several solution were thought of:
Having a static callback on the activity that calls onCreate(), so setContentView() can be set, and calls render(state: State) on every state change. Our classes are shielded as we like, but using a static for this is questionable.
Make the Activity open, so sdk users can subclass it. This means that every class used by the activity, has to be changed from internal to public.The classes which actually should be internal, will be hidden by obfuscating them with ProGuard.
It would be the nicest to pass a function in the Intent, which to my knowlegde is not possible.
Pass a POJO were we define parameters such as background color, which is the most restricting to the sdk user and is not in consideration.
Which solution is the best? Is there another method than the ones we thought of?
The SDK user may decide where views are placed, sizes, colors; we decide on what happens on onClicks and provide the texts of TextViews.
I picture this like so:
Your consumer receives a State, a ViewGroup, and an Actions object, which I'll explain later.
Based on State the consumer is required to create several views and place them as they wish within supplied ViewGroup.
The consumer is also required to register above views using some Actions.register*Button methods.
The above logic is executed inside one callback method. Once said method finished your SDK will verify correctness (all required actions are assigned a clickable view) and proceed.
Now, how to pass this callback method to sour SDK?
1.
It would be the nicest to pass a function in the Intent
This is actually possible with relative ease (and, IMO, some severe drawbacks).
In your SDK create a static Map<Key, Callback> sCallbacks. When your consumer registers the callback using your API, you'll generate a lookup key for it and store it within the map. You can pass the key around as an Intent extra. Once your SDK activity is opened it can lookup the callback using the key from its intent.
The key can be a String or UUID or whatever fits your needs and can be put inside an intent.
Pros:
It's deceptively easy to implement and use.
The consumer can use your SDK from just one file. All the calling code is in one place.
Cons:
You're not in charge where the callback is created. The consumer may create it as an anonymous class inside an Activity, which results in a memory leak.
You lose the callback map when process dies. If the app is killed while in your SDK activity you need to gracefully handle it when the app is restarted.
Variables are not shared across multiple processes. If your SDK activity and the calling code are not in the same process, your SDK activity will not be able to find the callback. Remember that the consumer is free to change process for their activities and even override your own activity process.
The calling point would look something like startSdk(context) { state, parent, actions -> /* ... */ }.
This is by far the most comfortable method for the consumer, yet the weaknesses start to show once you leave the area of a typical consumer setup.
2.
Make the Activity open, so sdk users can subclass it.
As you explained this is not possible without making compromies on your end.
Pros: ?
Cons:
The consumer needs to register their subclass and unregister your original SDK activity in AndroidManifest.xml. I'm assuming the manifest merger is enabled. This is a pain, as I often forget to look here.
The consumer gets easy access to your activity and is free to break it as they please.
Unless your documentation is pristine, the consumer will have a hard time figuring out what to override in your activity.
The calling point would look something like startSdk<MySdkActivity>(context).
I really don't understand the benefits of this option, as a consumer. I lose the benefits of #1 and gain nothing in return. As a developer I can't sanction this 'let the consumer deal with it' attitude. They will break things, you'll get bug reports and you will have to handle it eventually.
3.
Here I'll try to expand on the idea mentioned first in comments.
The callback would an abstract class defined by your SDK. It would be used as follows:
The consumer extends this class and defines the callback body. The class needs to have an empty constructor and be static. Typically it would be defined in its own file.
The class name is passed in an intent to your SDK activity.
Your SDK activity reflectively creates an instance of the callback.
The callback class could have several methods, one could set up menu, one could setup only view hierarchy, one would get the whole activity as parameter. The consumer would pick the one they need. Again, this needs to be documented well if there are multiple options.
Pros:
You separate the callback from the call site (where your SDK is called from). This is good, because the callback is executed inside your activity, completely separated from calling code.
As a result you can't leak the calling activity.
The consumer doesn't need to touch AndroidManifest.xml. This is great because registering your callback has nothing to do with Android. The manifest is mainly for things that the system interacts with.
The callback is easily recreated after process death. It has no constructor parameters and it's stateless.
It works across multiple processes. If, by any chance, the consumer needs to communicate across processes they're in charge of how they achieve that. Your SDK is not making it impossible as in case #2.
You get to keep your classes internal.
Cons:
You have to bundle a proguard rule to keep the empty constructor of each class extending the abstract callback class. You also need to keep their class names.
I'm assuming you'll hide the intent passing as an implementation detail so the entry point could look something like startSdk<MyCallback>(context).
I like this one because it shifts all possible responsibilities from the consumer to you, the SDK developer. You make it hard for the consumer to use the API wrong. You shield the consumer from potential errors.
Now back to the first paragraph. As long as the consumer can get their hands on a context (ViewGroup.getContext()) they're able to access the activity and the application (in that process). If both the calling activity and your SDK activity live in the same process the consumer could even access their prepared Dagger component. But they don't get to override your activity methods in unexpected ways.
First time asking on stackoverflow here !
Okay so here's the context. I'm doing an android application, and I'm trying to implement something like a plug-in framework.
My main app's MainActivity's purpose is to manage and launch/show Fragments.
Each of my plug-in will contain (at least) a Fragment and it's layout.
Thus, the idea is to fetch the fragment and put it inside my main app's MainActivity, from it.
So I decided to put my Fragments/Plug-ins into different apps and give all my plug-ins and main app the same user_id. This way all of them are in the same process, and even if they appear in the phone's Application Manager, only the main app is launchable and visible in the Application Browser (which is great).
But here's my problem... How do I get access to my plug-ins Fragments ?
I thought I could fetch some class through the PackageManager and use relfexion to use my fragment, but apparently you can't (or I didn't find how).
I considered binding Services together on each end (Application - Plug-in) but I have no guarantee that the services will bind together. Especially since each app have the same copy of the service, aka not the same Service.
Maybe by using a common .jar to make sure the Services are the same, and thus pass an instance of my Fragment to the main app (yes an instance would suffice).
Or make a CustomClassLoader (but then I might need advice on how to load classes from my other app, because I don't know how to do that...)
I've been running in circles in my head and on the net to find a solution...
To make things clear:
How do i fetch the classe (CustomClassLoader) or an instance (via binding or maybe sharedPreference or wiriting my instance in a file and read it in the main ?) of another app, considering they share the same user_id and thus are in the same process ?
Just because apps share the same user_id this does not imply they are running in the same process. They may and propably have been started by the same process. Sharing resources amongst processes is commonly known as IPC.
AIDL , the android Interface Definition language is a way for implementing IPC. Still this will not allow you retrieve objects from a different application directly but the possibility to invoke methods on remote objects.
But your problem description to me seems more like accessing objects of an jar at runtime in an application. This could be done via classloading.
So your app could retrieve a jar from a Server and load your fragments from it. The definitions of the fragments than would be runtime updateable if you define your fragments completely by code.
My app needs to initially download data from two different web services (JSON) and import them into it's local database (Realm). I have two activities that need to display data from these web services. The first one (HomeActivity) is the initial activity that the app loads. The second one (LineupActivity) is created when navigating to it from the HomeActivity.
Currently, I've created an Application class (extending Application) in order to handle the web service downloading and importing. In it's onCreate(), it calls two methods, which are AsyncTasks that download and import each web service.
The reason I've added this download/import process into the Application class is for 2 reasons:
I want all the app data to be downloaded as soon as possible, so
when navigating to the second activity it doesn't need to initiate
another download.
Both these activities have swipe to refresh. They call each respective method in the Application class to re-download/import the
web service data.
Have I approached this incorrectly? Should I move the web service download/import logic out of the Application class? Also, does the onCreate() of the Application class get called more than once? Meaning, I know that it only gets called only once in the application's lifecycle, but does the Android OS eventually kill an app and have it call the onCreate() in the Application class when starting it again? I want the app to download fresh data upon startup, but not every time the user brings the app into focus.
Have I approached this incorrectly?
"Incorrectly" is a very relative term in this context.
Metaphorically, its like the context is never null but that doesn't determine boolean incorrect is true or false.
Should I move the web service download/import logic out of the Application class?
I would say Yes, as the download logic would not be related to the O.S. and the app being alive in its memory. Your requirement does not seem complex. Service would be necessary if the downloads are huge chunks of data, and if its not necessary, don't do it.
Also, does the onCreate() of the Application class get called more than once? Meaning, I know that it only gets called only once in the application's lifecycle...Application class when starting it again?
No, it won't be called more than once without app being killed and restarted. And what your are saying is correct, but for your requirement, there are probably more efficient and lighter ways to do it rather than combining it with an Application class.
For the rest of the logic, you could implement Asynctasks as a separate class and implement interfaces which are the callbacks of the result of your task. This would help in Swipe-to-refresh functionality.
In terms of documentation reference, Application class
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way.
Your case seems exactly that.
One thing you need to decide is When, how often do you need to refresh/download the data. For only start-up of the app or once daily, you can store date/day in SharedPreferences and check the value in onResume() of your Activity.
You can also implement inheritance with a Base Activity with the necessary download check logic in it and extend your classes. A Splash Screen would always help to initiate the downloads.
I suppose you could approach this anyway you want, though I like to implement one of the three options mentioned here: https://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf.
The presentation itself can be found here: https://www.youtube.com/watch?v=xHXn3Kg2IQE.
This does however not mention how you should sync on startup. But you could just set a SharedPreference in the application class and then use one of the patterns to sync in the background.
I'd recommend you instead of using Application to download your stuff to use a Service. If by any reason your app gets killed by the OS your dl's will never complete. Using a Service it will.
Also, you can use a Broadcast to your activity to signalize that the service has completed downloading and taking the necessary following steps.
first: I think it's bad to place the download at appliaction onCreate
as stated in documentation
Called when the application is starting, before any activity, service,
or receiver objects (excluding content providers) have been created.
Implementations should be as quick as possible (for example using lazy
initialization of state) since the time spent in this function
directly impacts the performance of starting the first activity,
service, or receiver in a process. If you override this method, be
sure to call super.onCreate().
pay attention to this part
Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity
so any delay in download or import may cause the first activity to be delayed.
and the behavior is not clear, a black screen maybe?
Second suggestions for download/import:
1- use an AsyncTask in the first activity, where you display a small progress bar indicating the download/import process or even block the whole UI until completed (based on your business)
2- add a splash screen while downloading the data
regarding fresh data, you can store a timestamp, last_updated
and before starting the download/import process, check that value, if less than your accepted value (say 1 hour) don't start the download/import.
finally, regarding onCreate() call, i think it's not called everytime, only when app is re-created, like 1st run after reboot, or after being killed or forced close.
I work on a project that has several developers.
We work on one rather large app.
Every developer has several activities that can be seen as sub-apps of the whole main-app.
I do realize, that this may not be the best design, but it exists and we have to handle it somehow.
Now the main issue is, that we need a master, that is always active and checks I/Os etc and that can give out status changes to every sub-app/activity. Something like "we just lost internet connection" etc.
Right now, that master is a singleton, that is first instantiated by the launcher activity and that every activity/sub-app can register to by passing the appropriate interfaces depending on what updates the activity would like to receive.
This is working, however it doesn’t feel right, because the singleton needs context to access system resources to determine system stati like internet or gps. Should the singleton be killed by OS, than a simple "getInstance" wouldn’t do much good, because the singleton would somehow need to acquire a context. I've read about extending the Application class and creating a static member context there, but this variable had to be volatile AND its possible that it returns null if the entire app is in some restart-after-crash/kill state. It doesn’t feel safe.
In addition, there should also be a possibility that the master somehow opens a user-dialog to display warnings etc to the user. Those warnings should look the same across the entire app and no dev should have to worry about when or why it suddenly pops up. Right now, those messages appear as custom toasts that overlay everything. Of course they require context and if the app is about to close there could be a problem.
All in all, that’s the mess we are in and I’m looking for a solution.
So how do I create a safe master object or activity (or even service ?!) that can pass info to different activities and post warnings etc (and Maybe even has the ability to close activities or at least order them to close themselves without the need to register a can_close interface).
It should be that safe, that if after a crash android only restarts the activity that was active it somehow manages to also be restarted or at least have/give the same info as before.
Every idea is welcome but total overhauls of the app are just not possible (lack of time and manpower)
Here are a few ideas:
Create a Service component for all the monitoring you need to do.
If I understand correctly, this service will be required only if
some of the activities are running. So you can make it a bound
service. Let all activities bind to this service when they start
and unbind when they close. The service will be started when the
first activity binds.
Create a base class for all your activities. You can write all the common code here. e.g. the code to bind to and exchange messages
with the master service. This class can also contain utility methods
for notifying user etc. So all activities will use the same method
for notification.
For user notifications, you could either use Status Bar Notification or create a Fragment which can capture, aggregate
and display the notifications. You can have a common menu item
implemented in the base Activity class to show/hide this Fragment.
If you use Status Bar Notification, make sure you use one aggregated
notification for your app. Otherwise, the different activities might
create a clutter in the status bar.
I guess that one solution would be to create a service that serve as the master.
You will have to make it run independently of the different activities (but don't forget to manage own to shut it down neatly if the app is no longer used, you don't want to kill your clients battery).
A service can't act on the interface though, so you will probably need to broadcast messages to the activities to order them to open a dialog.
A final thought : Toasts are ok but popup that block the interface are very bad, especially on a mobile device.
I have an application that is driven by a configuration XML: various
app properties are loaded at the app start-time by parsing the XML and
initializing static variables of some class. The data read from this
XML drives different Activities of the application. Presently, I have
called the "parsing and the properties-initialization" from the
onCreate() of my Main Activity.
I have a few questions as regards this case/approach:
Should I invoke the app initialization method from the Application
Object or is the current approach correct? What advantages/
disadvantages do/would we get/have if I choose to invoke it from the
Application object?
Do we really need a static class to store app properties? Or can we have all the properties as a static Collection variable in the application object?
Parsing a XML(~200 nodes) at app load time might take some time(not
sure how long tho); How can I avoid the dreaded ANRs? I am using a
Pull Parser.
Please help me find answers to these questions.
Thank you.
It depends on what you're initializing. Application's onCreate() should be used when you're doing things that need to be done before any part of your app works correctly and only needs to be done once, whereas Activity/Service/etc's onCreate() should be used for things that are needed for that component alone and needs to be done multiple times.
The main concern I have for putting all your initialization into a component is that it will make extending your application more difficult later on. Suppose you want to make some Activity in your application accessible by outside intents - now you've got to either move the initialization code to Application or you have to duplicate initialization code in the non-launcher Activity.
It sounds like you should check out SharedPreferences, especially PreferenceManager.getDefaultSharedPreferences(). The preferences will be stored between sessions and it gives you easy access to simple properties from any Context.
Threading. I find AsyncTask to be the easiest way to accomplish this task; there's a good write-up on it at Google. Alternatively, you could fire up a Service to do this in the background while having a foreground Activity inform the user that you're booting up the app.
The Application object is used for sharing non-persistent state across the application. I don't think you'll need to use an Application class at all. You can do your initialisation in the onCreate() method of the Activity that is called first. To quote the documentation:
The subclass is optional; most applications won't need one. In the absence of a subclass, Android uses an instance of the base Application class.
You don't need to create your own class to store application properties. This is done for you by SharedPreferences.
You should also have a look at the setDefaultValues() method in the PreferenceManager
class as this will set preferences from the data in an XML file. What's nice about this method is that use the readAgain parameter so that the XML is only parsed once - the first time you start up your application - rather than every time.