If you refer to any documentation about logging events (Facebook,GoogleAnalytics etc), or may be other different sdk things, you can see activation helper methods that take place in lifecycle of concrete activity.
Ex:
The best way, I guess, to put such methods in BaseActivity. But sometimes it's not possible coz of project issues, where I can't use BaseActivity.
Is there any another way to handle all these things together in one place, (like interfaces or something)?
Thanks!
The reason why you put it in each activity is because you want to know how much time a user is spending on each screen and track it. In your case if you want to simplify things add it in the application
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.
Inspired by the Android developer guide I am trying to write code in which all fragments are self-contained (in terms of network/logic) and any actions they perform (click/tap) which should result in launching a new activity/fragment would be delegated to the activity (through callback).
To begin with, it seemed right. But now , when I have fragments which have more than 1 such widgets (which need the fragment to navigate to a new screen), it seems like a mess. I either need to write multiple callbacks or do some switch-case logic in Activity for different actions done on a fragment.
If this design sounds bad, what are the scenarios where implementing callbacks (as suggested by the guide) would be a good idea ?
I don't know how you are implementing these callbacks.
One approach to this problem is to use the contract pattern:
The fragment defines a Contract interface, that any hosting activity must implement
When the fragment wants to pass control to the activity, it calls a method on that interface
Jake Wharton has the canonical implementation of this in a GitHub gist. The only piece that is not shown is that the activity that hosts his MyCoolFragment needs to implement the MyCoolFragment.Contract interface.
This assumes that each fragment has distinct events to raise to the activity and therefore needs its own interface. If you have several fragments with common characteristics, you could standardize on a single interface, rather than duplicating the Contract everywhere.
There are other approaches (e.g., the comment on the gist suggesting using a message bus), but for simple fragment->activity communication, the contract pattern should have the least overhead, both in terms of coding and runtime implementation.
Your general approach, though, of delegating work to the activity where that work may result in changes to another fragment, is definitely a good one. It makes it that much easier to handle the cases where the fragments are not on the screen at the same time, perhaps hosted by different activities, as you handle different screen setups (phone vs. tablet, single screen vs. displaying content on a connected TV, etc.).
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().
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.
I'm going through the tutorials for android and something about intent/activity interaction is confusing me. In Javascript whenever there is an ajax call we define how the results should be handled along with the ajax call and we can use different callbacks for different ajax calls throughout the application lifecycle. In android starting an activity with an intent and handling the passed back results are decoupled, at least that's how it's done in the tutorial and there is only a single point of entry for how the results are handled so it's hard to perform on the fly handling of results without messing with the main entry point. I can easily imagine some complex logic that could make the switching inside the main entry point into a horrible mess. Is this a fundamental android architectural thing or is there another way to do things with actual callbacks instead of switch statements in a single entry point?
It is true that you are limited to a single location for receiving responses that an activity has finished. It would be nice if you could define a callback function for each, but that is not how it works.
In my experience though, you seldom have so many different destinations from a single activity that it is hard to manage. Generally each page only leads to one or two other pages that you might care about getting results from.
You can do something like the following to cleanly separate your logic for each case:
void onActivityResult(int requestCode, ....) {
switch(requestCode) {
case Activity1:
onActivity1Result(...);
break;
case Activity2:
onActivity2Result(...);
break;
}
}
Intents and Activities are designed to allow developers to develop re-usable, loosely coupled components.
I understand that, when working internal between two activities that you are creating, the mechanisms can seem unnecessarily restrictive. The restrictiveness is part of the open nature of the platform. The same mechanism that you use to start an activity you own could start an Activity created by another developer or by the OS itself.
That being said, there are a plethora of options for passing information between activities. It really depends what you are trying to accomplish. I try to think of activities just that, activities from the users perspective. I'm going to list some mechanisms for passing data and, if you'd like to further describe your application or need, I'll try to help you narrow the options down:
Intent.putExtra
startActivityForResult (I'm assuming you know this one)
SharedPreferences
Service
ContentProvider
Also note that you do not have to start a new activity for a background process without its own screen such as an Ajax call - you can use AsyncTask instead which allows for a javascript style callback.