Android help understand code - android

Hi I am new to programming and I am trying to create simple alarm clock app in android can some help me to understand this code
public static AlarmActivity instance() {
return inst;
}
#Override
public void onStart() {
super.onStart();
inst = this;
}
More detailed code is here

The code you posted is an example of the Singleton pattern. And here goes a quote from wikipedia
...the singleton pattern is a design pattern that restricts the
instantiation of a class to one object. This is useful when exactly
one object is needed to coordinate actions across the system. The
concept is sometimes generalized to systems that operate more
efficiently when only one object exists, or that restrict the
instantiation to a certain number of objects.
Normally this pattern requires you to make the object's constructor private but that's kinda impossible with Android activities.
By doing that
inst = this;
the activity "stores itself" in a variable that will be later returned by the getInstance() method. Using this patter will allow other classes (other activities, I guess) use this activity by simply calling AlarmActivity.getInstance()...which can be beneficial in some cases.

Saving a pointer to this in a variable is common in Android programming:
it will be used, later on, by other classes that have no access to this (because they have a "different" this) while they might still need access to the context (Activity).

Related

Why extend the Android Application class?

An extended Application class can declare global variables. Are there other reasons?
Introduction:
If we consider an apk file in our mobile, it is comprised of
multiple useful blocks such as, Activitys, Services and
others.
These components do not communicate with each other regularly and
not forget they have their own life cycle. which indicate that
they may be active at one time and inactive the other moment.
Requirements:
Sometimes we may require a scenario where we need to access a
variable and its states across the entire Application regardless of
the Activity the user is using,
An example is that a user might need to access a variable that holds his
personnel information (e.g. name) that has to be accessed across the
Application,
We can use SQLite but creating a Cursor and closing it again and
again is not good on performance,
We could use Intents to pass the data but it's clumsy and activity
itself may not exist at a certain scenario depending on the memory-availability.
Uses of Application Class:
Access to variables across the Application,
You can use the Application to start certain things like analytics
etc. since the application class is started before Activitys or
Servicess are being run,
There is an overridden method called onConfigurationChanged() that is
triggered when the application configuration is changed (horizontal
to vertical & vice-versa),
There is also an event called onLowMemory() that is triggered when
the Android device is low on memory.
Application class is the object that has the full lifecycle of your application. It is your highest layer as an application. example possible usages:
You can add what you need when the application is started by overriding onCreate in the Application class.
store global variables that jump from Activity to Activity. Like Asynctask.
etc
Sometimes you want to store data, like global variables which need to be accessed from multiple Activities - sometimes everywhere within the application. In this case, the Application object will help you.
For example, if you want to get the basic authentication data for each http request, you can implement the methods for authentication data in the application object.
After this,you can get the username and password in any of the activities like this:
MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();
And finally, do remember to use the Application object as a singleton object:
public class MyApplication extends Application {
private static MyApplication singleton;
public MyApplication getInstance(){
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton = this;
}
}
For more information, please Click Application Class
Offhand, I can't think of a real scenario in which extending Application is either preferable to another approach or necessary to accomplish something. If you have an expensive, frequently used object you can initialize it in an IntentService when you detect that the object isn't currently present. Application itself runs on the UI thread, while IntentService runs on its own thread.
I prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences. There are also ways to pass data from a Fragment to its parent Activity using interfaces.
The Application class is a singleton that you can access from any activity or anywhere else you have a Context object.
You also get a little bit of lifecycle.
You could use the Application's onCreate method to instantiate expensive, but frequently used objects like an analytics helper. Then you can access and use those objects everywhere.
Best use of application class.
Example: Suppose you need to restart your alarm manager on boot completed.
public class BaseJuiceApplication extends Application implements BootListener {
public static BaseJuiceApplication instance = null;
public static Context getInstance() {
if (null == instance) {
instance = new BaseJuiceApplication();
}
return instance;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onBootCompleted(Context context, Intent intent) {
new PushService().scheduleService(getInstance());
//startToNotify(context);
}
Not an answer but an observation: keep in mind that the data in the extended application object should not be tied to an instance of an activity, as it is possible that you have two instances of the same activity running at the same time (one in the foreground and one not being visible).
For example, you start your activity normally through the launcher, then "minimize" it. You then start another app (ie Tasker) which starts another instance of your activitiy, for example in order to create a shortcut, because your app supports android.intent.action.CREATE_SHORTCUT. If the shortcut is then created and this shortcut-creating invocation of the activity modified the data the application object, then the activity running in the background will start to use this modified application object once it is brought back to the foreground.
I see that this question is missing an answer. I extend Application because I use Bill Pugh Singleton implementation (see reference) and some of my singletons need context. The Application class looks like this:
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication sInstance;
#Contract(pure = true)
#Nullable
public static Context getAppContext() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
sInstance = this;
}
}
And the singletons look like this:
public class DataManager {
private static final String TAG = DataManager.class.getSimpleName();
#Contract(pure = true)
public static DataManager getInstance() {
return InstanceHolder.INSTANCE;
}
private DataManager() {
doStuffRequiringContext(MyApplication.getAppContext());
}
private static final class InstanceHolder {
#SuppressLint("StaticFieldLeak")
private static final DataManager INSTANCE = new DataManager();
}
}
This way I don't need to have a context every time I'm using a singleton and get lazy synchronized initialization with minimal amount of code.
Tip: updating Android Studio singleton template saves a lot of time.
I think you can use the Application class for many things, but they are all tied to your need to do some stuff BEFORE any of your Activities or Services are started.
For instance, in my application I use custom fonts. Instead of calling
Typeface.createFromAsset()
from every Activity to get references for my fonts from the Assets folder (this is bad because it will result in memory leak as you are keeping a reference to assets every time you call that method), I do this from the onCreate() method in my Application class:
private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
super.onCreate();
appInstance = this;
quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
"fonts/Quicksand-Regular.otf");
...
}
Now, I also have a method defined like this:
public static App getAppInstance() {
return appInstance;
}
and this:
public Typeface getQuickSandRegular() {
return quicksandRegular;
}
So, from anywhere in my application, all I have to do is:
App.getAppInstance().getQuickSandRegular()
Another use for the Application class for me is to check if the device is connected to the Internet BEFORE activities and services that require a connection actually start and take necessary action.
Source: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class
In many apps, there's no need to work with an application class directly. However, there are a few acceptable uses of a custom application class:
Specialized tasks that need to run before the creation of your first activity
Global initialization that needs to be shared across all components (crash reporting, persistence)
Static methods for easy access to static immutable data such as a shared network client object
You should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
To add onto the other answers that state that you might wish store variables in the application scope, for any long-running threads or other objects that need binding to your application where you are NOT using an activity (application is not an activity).. such as not being able to request a binded service.. then binding to the application instance is preferred. The only obvious warning with this approach is that the objects live for as long as the application is alive, so more implicit control over memory is required else you'll encounter memory-related problems like leaks.
Something else you may find useful is that in the order of operations, the application starts first before any activities. In this timeframe, you can prepare any necessary housekeeping that would occur before your first activity if you so desired.
2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
You can access variables to any class without creating objects, if its extended by Application. They can be called globally and their state is maintained till application is not killed.
The use of extending application just make your application sure for any kind of operation that you want throughout your application running period. Now it may be any kind of variables and suppose if you want to fetch some data from server then you can put your asynctask in application so it will fetch each time and continuously, so that you will get a updated data automatically.. Use this link for more knowledge....
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android

Application class lifecycle while service is running

I am developing an application with custom Application class which initializes a couple of singletons so they live during all application working time. I also have a couple of services in my application which work with these singletons. Is it possible situation that Application class will be destroyed by android with singletons' instances before services so services will not be able to use them? Or application lives always even for services of it's context? What is the best way to find a way out of this situation?
Thanks.
Regarding the application object:
The application object is the main absolute starting point on any Android app. It will always exist before any of the Manifest declared items such as Activity, Service and BroadcastReceiver. So relax that the singletons will be there for you.
Regarding the singleton paradigma:
That's a big discussion topic, you can google more about it so what follows is my personal opinion on it. Whatever is the reason for your singletons (a database, an bitmap caching, a FileUtils) I think it's ok and correct to initialise them on the very first point of entry of your app, which is the Application. But the application itself is not an object meant to carry or hold those objects, that way my suggested design approach is to:
=> on your singleton object/class you'll have to:
private static MySingletonClass instance; // reference to the single object
private MySingletonClass(Context c){ // private constructor to avoid construction from anywhere else
// let's say it needs the context for construction because it's a database singleton
}
public static MySingletonClass get(){ //
if(instance == null) throw new RuntimeException("This singleton must be initialised before anything else");
return instance;
}
public static void init(Context c){ // call the initialisation from the Application
instance = new MySingletonClass(c);
}
=> and then on your Application object you simply init the singleton
onCreate(){
MySingletonClass.init(getApplicationContext());
}
with that way you'll keep the necessary initialisation, enforce the singleton pattern but to access the object you call to that object class not to the application. I know it's just a organisational difference, but I believe that that's what separate good and bad code.
So for example on your service the call is: MySingletonClass.get() and should never be MyApplication.mySingle.
hope it helps.
From my understanding service can't live without application context, service is bound to the application with the Context reference so I think if the application is killed also the Context is killed and that lead that all components are been killed,
you can read here for more info
http://developer.android.com/guide/components/fundamentals.html#proclife

Lifecycle of enum based singleton on Android

A few days ago I've discovered that singleton can become anti-pattern in Android. My singleton (class with private constructor and instance stored in static field) was deleted (instance was deleted despite the fact other activities were still using this singleton (via getInstance() method) so another instance had to be created ) because Activity from which it was first invoked was deleted (after invoking finish for only this one activity).
I've read already how this problem can be resolved however I've also just read "Effective Java". There is said that "Single-element enum type is the bast way to implement a singleton".
So now I'm wondering what would be the lifecycle of singleton created this way in Android application? Would it be the same like in case of "standard singleton implementation" so after destroying activity from which it was invoked the first time it will be destroyed (even if it used also in other activities)?
I'm not asking about proper android singleton implemenation or the singleton pattern itself (is it pattern or anti-pattern etc) but I'd like to know what be the lifecycle of such enum singleton object and when it will be destroyed.
In all cases, the classes you use are tied to the ClassLoader that loaded them. This is true in Java in general, not just Android. Android will isolate activities by using new ClassLoaders each time -- at the least, it doesn't promise it won't, and it does as far as I can tell.
Any singleton, or other class-level state, is tied to the Class which is tied to the ClassLoader. This is why your state "disappears"; it's actually that your calling code is seeing a new Class in a new ClassLoader.
So, your enum-based trick, or anything else along these lines, would have exactly the same behavior. You just can't "persist" activity information this way. You can and should write to a SQLite DB. You could probably stash it in the SharedPreferences too.
The application object is a good location to store information which needs to be accessible to various activity or service instances. You can retrieve it like this (where this is an Activity or Service):
private MyApplication app;
in onCreate(...){
...
this.app = (MyApplication) this.getApplication();
...
}
Remember to set the name also in the manifest:
Set the attribute "name" of the "application" tag:
The value is the path to the class relative to the package of your app.
The application object is created when the app is started, you can initialize like in an activity or service in it's onCreate() method.
One thing to remember: The application object can survive closing your "last" activity. In this case you may get the same application object with the state from the previous interaction with your app. If this is a problem you must somehow detect the initial start of your app (e.g. using a special launcher activity without UI, which initializes the application object and then starts a new intent.
BTW, the same may happen with singletons if they have not yet been lost to garbage collection.
My secure singleton implementation is like that:
I create a singleton class which has an attribute of boolean 'didReceiveMemoryWarning';
public class SingleTon(){
public boolean didReceiveMemoryWarning = true;
...
...
}
In application first screen(It is exactly first launch screen)(I have a splash screen that is visible 3 sec)
SingleTon.getInstance().didReceiveMemoryWarning = false;
And in every Activity's onCreate() method, check this boolean data,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(SingleTon.getInstance().didReceiveMemoryWarning){
{ Load your data from local to your SingleTon class,
because your app was released by OS};
}
}
it is my implementation.

Different Instance of Applicationcontext in Broadcastreceiver

I want to access a "global" variable in my MyApp(extends Application) from a broadcastreceiver (registered in the manifest) and e.g. multiple activities. Now I seem to have different instances of my MyApp: one for the BCR and one for the activities. Could sb help me with my problem?
thanks alot
Joerg
What I get from this is that you are trying to create a method to having a single Context object. First off, to do this you would need a Singleton Pattern of MyApp to create your "global" variable. However I would advice against this for these reasons:
Different application components by default have different contexts (base, application).
A BroadcastReceiver defined in the manifest is invoked by the OS, not by your application.
Using a Singleton Pattern for a context object will lead to some very nasty dependencies.
You are going against the design and beauty of the Android Framework.
I would suspect the reason you are doing this is so your MyApp class can start different activities. This makes sense, but... you can get a Context Object from almost anywhere. Many things in Android extend the ContextWrapper class (think Java Objects with the Object class). So there is really no reason to ever have a "global" instance of this. In fact your BroadcastReceiver's onReceive() method accepts a context parameter. You can use this to start activities and what not.
If this is not why you are wanting the MyApp singleton class - and there are justifiable reasons for needing it, I would look at the implementation designed by Bill Pugh as it is the safest in Java taking into account thread synchronization and locking.
Hope this helps. Remember, don't fight the SDK, let it work for you!
I had a similar problem, I was able to access an object in the activity using this pattern:
public class MyReceiver extends android.content.BroadcastReceiver {
private Object _object;
public MyReceiver(Someobject) {
_object = the object;
}
#Override
public void onReceive(Context context, Intent intent) {
Do something to the object.
}
}
Then call MyReceiver(theobject) instead of new BroadcastReceiver().

How to declare global variables in Android?

I am creating an application which requires login. I created the main and the login activity.
In the main activity onCreate method I added the following condition:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
loadSettings();
if(strSessionString == null)
{
login();
}
...
}
The onActivityResult method which is executed when the login form terminates looks like this:
#Override
public void onActivityResult(int requestCode,
int resultCode,
Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case(SHOW_SUBACTICITY_LOGIN):
{
if(resultCode == Activity.RESULT_OK)
{
strSessionString = data.getStringExtra(Login.SESSIONSTRING);
connectionAvailable = true;
strUsername = data.getStringExtra(Login.USERNAME);
}
}
}
The problem is the login form sometimes appears twice (the login() method is called twice) and also when the phone keyboard slides the login form appears again and I guess the problem is the variable strSessionString.
Does anyone know how to set the variable global in order to avoid login form appearing after the user already successfully authenticates?
I wrote this answer back in '09 when Android was relatively new, and there were many not well established areas in Android development. I have added a long addendum at the bottom of this post, addressing some criticism, and detailing a philosophical disagreement I have with the use of Singletons rather than subclassing Application. Read it at your own risk.
ORIGINAL ANSWER:
The more general problem you are encountering is how to save state across several Activities and all parts of your application. A static variable (for instance, a singleton) is a common Java way of achieving this. I have found however, that a more elegant way in Android is to associate your state with the Application context.
As you know, each Activity is also a Context, which is information about its execution environment in the broadest sense. Your application also has a context, and Android guarantees that it will exist as a single instance across your application.
The way to do this is to create your own subclass of android.app.Application, and then specify that class in the application tag in your manifest. Now Android will automatically create an instance of that class and make it available for your entire application. You can access it from any context using the Context.getApplicationContext() method (Activity also provides a method getApplication() which has the exact same effect). Following is an extremely simplified example, with caveats to follow:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
#Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
This has essentially the same effect as using a static variable or singleton, but integrates quite well into the existing Android framework. Note that this will not work across processes (should your app be one of the rare ones that has multiple processes).
Something to note from the example above; suppose we had instead done something like:
class MyApp extends Application {
private String myState = /* complicated and slow initialization */;
public String getState(){
return myState;
}
}
Now this slow initialization (such as hitting disk, hitting network, anything blocking, etc) will be performed every time Application is instantiated! You may think, well, this is only once for the process and I'll have to pay the cost anyways, right? For instance, as Dianne Hackborn mentions below, it is entirely possible for your process to be instantiated -just- to handle a background broadcast event. If your broadcast processing has no need for this state you have potentially just done a whole series of complicated and slow operations for nothing. Lazy instantiation is the name of the game here. The following is a slightly more complicated way of using Application which makes more sense for anything but the simplest of uses:
class MyApp extends Application {
private MyStateManager myStateManager = new MyStateManager();
public MyStateManager getStateManager(){
return myStateManager ;
}
}
class MyStateManager {
MyStateManager() {
/* this should be fast */
}
String getState() {
/* if necessary, perform blocking calls here */
/* make sure to deal with any multithreading/synchronicity issues */
...
return state;
}
}
class Blah extends Activity {
#Override
public void onCreate(Bundle b){
...
MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
String state = stateManager.getState();
...
}
}
While I prefer Application subclassing to using singletons here as the more elegant solution, I would rather developers use singletons if really necessary over not thinking at all through the performance and multithreading implications of associating state with the Application subclass.
NOTE 1: Also as anticafe commented, in order to correctly tie your Application override to your application a tag is necessary in the manifest file. Again, see the Android docs for more info. An example:
<application
android:name="my.application.MyApp"
android:icon="..."
android:label="...">
</application>
NOTE 2: user608578 asks below how this works with managing native object lifecycles. I am not up to speed on using native code with Android in the slightest, and I am not qualified to answer how that would interact with my solution. If someone does have an answer to this, I am willing to credit them and put the information in this post for maximum visibility.
ADDENDUM:
As some people have noted, this is not a solution for persistent state, something I perhaps should have emphasized more in the original answer. I.e. this is not meant to be a solution for saving user or other information that is meant to be persisted across application lifetimes. Thus, I consider most criticism below related to Applications being killed at any time, etc..., moot, as anything that ever needed to be persisted to disk should not be stored through an Application subclass. It is meant to be a solution for storing temporary, easily re-creatable application state (whether a user is logged in for example) and components which are single instance (application network manager for example) (NOT singleton!) in nature.
Dayerman has been kind enough to point out an interesting conversation with Reto Meier and Dianne Hackborn in which use of Application subclasses is discouraged in favor of Singleton patterns. Somatik also pointed out something of this nature earlier, although I didn't see it at the time. Because of Reto and Dianne's roles in maintaining the Android platform, I cannot in good faith recommend ignoring their advice. What they say, goes. I do wish to disagree with the opinions, expressed with regards to preferring Singleton over Application subclasses. In my disagreement I will be making use of concepts best explained in this StackExchange explanation of the Singleton design pattern, so that I do not have to define terms in this answer. I highly encourage skimming the link before continuing. Point by point:
Dianne states, "There is no reason to subclass from Application. It is no different than making a singleton..." This first claim is incorrect. There are two main reasons for this. 1) The Application class provides a better lifetime guarantee for an application developer; it is guaranteed to have the lifetime of the application. A singleton is not EXPLICITLY tied to the lifetime of the application (although it is effectively). This may be a non-issue for your average application developer, but I would argue this is exactly the type of contract the Android API should be offering, and it provides much more flexibility to the Android system as well, by minimizing the lifetime of associated data. 2) The Application class provides the application developer with a single instance holder for state, which is very different from a Singleton holder of state. For a list of the differences, see the Singleton explanation link above.
Dianne continues, "...just likely to be something you regret in the future as you find your Application object becoming this big tangled mess of what should be independent application logic." This is certainly not incorrect, but this is not a reason for choosing Singleton over Application subclass. None of Diane's arguments provide a reason that using a Singleton is better than an Application subclass, all she attempts to establish is that using a Singleton is no worse than an Application subclass, which I believe is false.
She continues, "And this leads more naturally to how you should be managing these things -- initializing them on demand." This ignores the fact that there is no reason you cannot initialize on demand using an Application subclass as well. Again there is no difference.
Dianne ends with "The framework itself has tons and tons of singletons for all the little shared data it maintains for the app, such as caches of loaded resources, pools of objects, etc. It works great." I am not arguing that using Singletons cannot work fine or are not a legitimate alternative. I am arguing that Singletons do not provide as strong a contract with the Android system as using an Application subclass, and further that using Singletons generally points to inflexible design, which is not easily modified, and leads to many problems down the road. IMHO, the strong contract the Android API offers to developer applications is one of the most appealing and pleasing aspects of programming with Android, and helped lead to early developer adoption which drove the Android platform to the success it has today. Suggesting using Singletons is implicitly moving away from a strong API contract, and in my opinion, weakens the Android framework.
Dianne has commented below as well, mentioning an additional downside to using Application subclasses, they may encourage or make it easier to write less performance code. This is very true, and I have edited this answer to emphasize the importance of considering perf here, and taking the correct approach if you're using Application subclassing. As Dianne states, it is important to remember that your Application class will be instantiated every time your process is loaded (could be multiple times at once if your application runs in multiple processes!) even if the process is only being loaded for a background broadcast event. It is therefore important to use the Application class more as a repository for pointers to shared components of your application rather than as a place to do any processing!
I leave you with the following list of downsides to Singletons, as stolen from the earlier StackExchange link:
Inability to use abstract or interface classes;
Inability to subclass;
High coupling across the application (difficult to modify);
Difficult to test (can't fake/mock in unit tests);
Difficult to parallelize in the case of mutable state (requires extensive locking);
and add my own:
Unclear and unmanageable lifetime contract unsuited for Android (or most other) development;
Create this subclass
public class MyApp extends Application {
String foo;
}
In the AndroidManifest.xml add android:name
Example
<application android:name=".MyApp"
android:icon="#drawable/icon"
android:label="#string/app_name">
The suggested by Soonil way of keeping a state for the application is good, however it has one weak point - there are cases when OS kills the entire application process. Here is the documentation on this - Processes and lifecycles.
Consider a case - your app goes into the background because somebody is calling you (Phone app is in the foreground now). In this case && under some other conditions (check the above link for what they could be) the OS may kill your application process, including the Application subclass instance. As a result the state is lost. When you later return to the application, then the OS will restore its activity stack and Application subclass instance, however the myState field will be null.
AFAIK, the only way to guarantee state safety is to use any sort of persisting the state, e.g. using a private for the application file or SharedPrefernces (it eventually uses a private for the application file in the internal filesystem).
Just a note ..
add:
android:name=".Globals"
or whatever you named your subclass to the existing <application> tag. I kept trying to add another <application> tag to the manifest and would get an exception.
What about ensuring the collection of native memory with such global structures?
Activities have an onPause/onDestroy() method that's called upon destruction, but the Application class has no equivalents. What mechanism are recommended to ensure that global structures (especially those containing references to native memory) are garbage collected appropriately when the application is either killed or the task stack is put in the background?
I couldn't find how to specify the application tag either, but after a lot of Googling, it became obvious from the manifest file docs: use android:name, in addition to the default icon and label in the application stanza.
android:name
The fully qualified name of an Application subclass implemented for the application. When the application process is started, this class is instantiated before any of the application's components.
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.
Just you need to define an application name like below which will work:
<application
android:name="ApplicationName" android:icon="#drawable/icon">
</application>
Like there was discussed above OS could kill the APPLICATION without any notification (there is no onDestroy event) so there is no way to save these global variables.
SharedPreferences could be a solution EXCEPT you have COMPLEX STRUCTURED variables (in my case I had integer array to store the IDs that the user has already handled). The problem with the SharedPreferences is that it is hard to store and retrieve these structures each time the values needed.
In my case I had a background SERVICE so I could move this variables to there and because the service has onDestroy event, I could save those values easily.
If some variables are stored in sqlite and you must use them in most activities in your app.
then Application maybe the best way to achieve it.
Query the variables from database when application started and store them in a field.
Then you can use these variables in your activities.
So find the right way, and there is no best way.
You can have a static field to store this kind of state. Or put it to the resource Bundle and restore from there on onCreate(Bundle savedInstanceState). Just make sure you entirely understand Android app managed lifecycle (e.g. why login() gets called on keyboard orientation change).
DO N'T Use another <application> tag in manifest file.Just do one change in existing <application> tag , add this line android:name=".ApplicationName" where, ApplicationName will be name of your subclass(use to store global) that, you is about to create.
so, finally your ONE AND ONLY <application> tag in manifest file should look like this :-
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.NoActionBar"
android:name=".ApplicationName"
>
you can use Intents , Sqlite , or Shared Preferences . When it comes to the media storage, like documents , photos , and videos, you may create the new files instead.
You can do this using two approaches:
Using Application class
Using Shared Preferences
Using Application class
Example:
class SessionManager extends Application{
String sessionKey;
setSessionKey(String key){
this.sessionKey=key;
}
String getSessisonKey(){
return this.sessionKey;
}
}
You can use above class to implement login in your MainActivity as below. Code will look something like this:
#override
public void onCreate (Bundle savedInstanceState){
// you will this key when first time login is successful.
SessionManager session= (SessionManager)getApplicationContext();
String key=getSessisonKey.getKey();
//Use this key to identify whether session is alive or not.
}
This method will work for temporary storage. You really do not any idea when operating system is gonna kill the application, because of low memory.
When your application is in background and user is navigating through other application which demands more memory to run, then your application will be killed since operating system given more priority to foreground processes than background.
Hence your application object will be null before user logs out. Hence for this I recommend to use second method Specified above.
Using shared preferences.
String MYPREF="com.your.application.session"
SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
//Insert key as below:
Editot editor= pref.edit();
editor.putString("key","value");
editor.commit();
//Get key as below.
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
String key= getResources().getString("key");
On activity result is called before on resume. So move you login check to on resume and your second login can be blocked once the secomd activity has returned a positive result. On resume is called every time so there is not worries of it not being called the first time.
The approach of subclassing has also been used by the BARACUS framework. From my point of view subclassing Application was intended to work with the lifecycles of Android; this is what any Application Container does. Instead of having globals then, I register beans to this context an let them beeing injected into any class manageable by the context. Every injected bean instance actually is a singleton.
See this example for details
Why do manual work if you can have so much more?
class GlobaleVariableDemo extends Application {
private String myGlobalState;
public String getGlobalState(){
return myGlobalState;
}
public void setGlobalState(String s){
myGlobalState = s;
}
}
class Demo extends Activity {
#Override
public void onCreate(Bundle b){
...
GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
String state = appState.getGlobalState();
...
}
}
You could create a class that extends Application class and then declare your variable as a field of that class and providing getter method for it.
public class MyApplication extends Application {
private String str = "My String";
synchronized public String getMyString {
return str;
}
}
And then to access that variable in your Activity, use this:
MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();

Categories

Resources