Context in Marshmallow - android

Question is about context, it return null on first time running after installing app. Do I need permissions? Earlier versions work. Android developer preview v3 (nexus5)
public class App extends Application {
private static App application;
#Override
public void onCreate() {
super.onCreate();
Log.e("APP::", "CREATE");
application = this;
Log.e("APPLICATION ::", "" + application);
}
public static Context getContext() {
return application != null ? application.getBaseContext() : null;
}
}

You're calling getContext() before onCreate() is called. Don't do that. If possible, don't use a static reference to App at all.

Related

Toast resource not found Resources$NotFoundException: File res/layout/transient_notification.xml

this problem is not always there, I can't find the cause of the problem, ask for help, thank you.
My code is
private static Toast systemToast;
public static Toast getSystemToast(Object resId) {
if (null == systemToast) {
// Apps is the Application.java
systemToast = Toast.makeText(Apps.getAppContext(), R.string.me_empty,
Toast.LENGTH_SHORT);
}
String res = String.valueOf(resId);
if (resId.getClass() == Integer.class) {
systemToast.setText(Integer.valueOf(res));
} else if (resId.getClass() == String.class) {
systemToast.setText(res);
}
systemToast.setDuration(Toast.LENGTH_SHORT);
return systemToast;
}
/** Apps.java **/
public class Apps extends Application {
private static Apps sContext;
#Override
protected void attachBaseContext(Context base) {
sContext = this;
}
public static Apps getAppContext() {
return sContext;
}
In some Android equipment, Error occurred, The error Log is:
android.content.res.Resources$NotFoundException: File res/layout
/transient_notification.xml from xml type layout resource ID #0x10900ef at
android.content.res.Resources.loadXmlResourceParser(Resources.java:2720) at
android.content.res.Resources.loadXmlResourceParser(Resources.java:2675) at
android.content.res.Resources.getLayout(Resources.java:1096) at
android.view.LayoutInflater.inflate(LayoutInflater.java:422) at
android.view.LayoutInflater.inflate(LayoutInflater.java:368) at
android.widget.Toast.makeText(Toast.java:282)
This error might be occurred, when pass context object not proper initialize or might be its referencing to null.
1.if you are using Fragment than, you can find Context in onAttach Method. And pass your getSystemToast Method.
**#Override
public void onAttach(Context context) {
super.onAttach(context);
}**
2. If you are using Activity, than get Context using getBaseContext() Method or ActivityName.this both will return you context
You no need to defined function for get Context. Android provide Following Method for get Context.
1.getApplicationContext() Application context is associated with the Applicaition and will always be the same throughout the life cycle.
2.getBaseContext()
3.onAttach() in Fragment.

Singleton Destruction, Class Loading etc in android

I want to get clarity on loading of classes, destruction of objects etc in android because I noticed some weird things happening when using Singleton in My Activity. Best I will describe it using code :
My Singleton class
public class FilterCriteria {
private final String TAG=FilterCriteria.class.getSimpleName();
private static FilterCriteria filterCriteria=new FilterCriteria();
private FilterCriteria()
{
}
public static FilterCriteria getInstance()
{
return filterCriteria;
}
private int rentUpperBound,rentLowerBound;
private int bedrooms,baths;
private float distance;
private ObjectStateListener listener;
public void setFilters(float distance,int baths,int bedrooms,int rentLowerBound,int rentUpperBound) {
this.distance = distance;
this.baths=baths;
this.bedrooms=bedrooms;
this.rentLowerBound=rentLowerBound;
this.rentUpperBound=rentUpperBound;
if(listener!=null)
listener.onObjectStateChanged();
}
public void attachListener(ObjectStateListener listener) {
if (this.listener == null) {
this.listener = listener;
Log.v(TAG, "NO LISTENER PRESENT AS EXPECTED");
} else {
Log.v(TAG, "LISTENER PRESENT!!! BUT THE ACTIVITY WAS STARTED JUST NOW.");
}
}
public void destroy()
{
filterCriteria=null;
}
}
The attachListener(ObjectStateListener listener) function is called only once in the activity. So, when I open my activity the first time, I get this log from attachListener function
NO LISTENER PRESENT AS EXPECTED
Now, I close the activity and then reopen it. But now I get this log
"LISTENER PRESENT!!! BUT THE ACTIVITY WAS STARTED JUST NOW."
So, that means the object still lives on even after the activity (and the application) was closed. Is this normal???
So, I tried to destroy the singleton instance using the destroy() function in the onDestroy() function of Activity.
#Override
protected void onDestroy(){
filterCriteria.destroy();//Trying to destroy the singleton
super.onDestroy();
Log.v(TAG,"Destroying activity");
}
But I got NullPointerException on this line filterCriteria.destroy(). So, that means android has already made object null, whereas when I see in debug mode, other members of the Activity are still alive. Why is only this null?
What is happening!???
When you invoke the method attachListener() you are creating a reference to the linked object (even if it is static): this reference will be binded to the activity lifecycle.
On the other hand, filterCriteria will follow the static field Java-like lifecycle (but you can still remove this reference manually).

How to hold an Object as long as a service live?

I have an Object that i use in all my activities which holds a lot of complex data in it, it would be quite an hassle to use Android framework of saving the object state and passing it around from activity to activity, so i thought it would be possible to make a Singleton that manages this object and makes it live as long as the application lives.
Tried to use regular Java Singleton scheme, with normal class and normal static instance, but the instance becomes null after a while (which is very confusing, why would an Object that is still referenced be turned to null and garbage collected?). so i decided to flow with Android designers and created a Service to manage this Object, the Service looks something like that :
public class DataService extends Service {
private Data data;
private static DataService instance;
#Override
public void onCreate() {
instance = this;
data= new Data(...);
instance.data.addProgressListener(listener);
(new Thread() {
#Override
public void run() {
data.doInitProgress();
listener = null;
};
}).start();
}
public static void listenToInitDataProcess(final ProgressBar progressBar,final Runnable onDone) {
listener = new ProgressListener() {
private int progress;
private int max;
#Override
public void onUpdateProgress(final long i) {
progressBar.setProgress(progress+=i);
}
#Override
public void onProgressEndComputed(final long n) {
progressBar.setMax(max=(int) n);
}
#Override
public void onDone() {
progressBar.setProgress(max);
onDone.run();
}
};
if (instance!=null) instance.data.addProgressListener(listener);
}
public static Data getData() {
return instance.data;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
now the problem with that is that after a while that the app is on i get NPE caused by instance is null... notice that i was listenning to the data object creation and i was trying to get it only after it was once inited, so no way that instance was suppose to be null...
how to do this right then?
If you want an Object that lives as long as your application lives (i.e. as long as its process is not killed by OS) you can extend android.app.Application, put your 'global' data there and use that subclass as your app context (needs to be declared in manifest)
However many argue that singletons provide essentially the same result as custom context e.g.
Singletons vs. Application Context in Android?
but the instance becomes null after a while
First, understand Effective Java's singleton recommendations, and how something wouldn't become null:
// Singleton with public final field
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}
But a Service is different, since there is no public constructor there. So, first check if the Service is running (as referenced in this post: Check if Service is running from a Broadcast Receiver):
private boolean isMyServiceRunning(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (DataService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Then define some methods in your Service to return your needed state variables.

Store Objects in ApplicationContext

When my application goes to background , my (static and singleton) objects are cleared.
So I tried to store these objects in Applicaton Context . I am using the following code.
Accounts.create(getApplicationContext()) will be called once to store the accounts instance.
Is that possible(reliable) to store objects in Application Context ? I am not sure the following way is correct or not . please guide ..
public class Init extends Application {
private Hashtable<Object, Object> globalStore = new Hashtable<Object, Object>();
public void putToGlobalStore(Object key, Object value) {
globalStore.put(key, value);
}
public Object takeFromGlobalStore(Object key) {
return this.globalStore.get(key);
}
public void removeFromGlobalStore(Object key) {
this.globalStore.remove(key);
}
public boolean containsInGlobalStore(Object key) {
return this.globalStore.containsKey(key);
}
}
public class Accounts {
protected Accounts(String name, Context context) {
Init init = (Init) applicationContext;
init.putToGlobalStore(name, this);
}
private static Init applicationContext;
public static void create(Context context) {
if (context instanceof Application)
applicationContext = (Init) context;
else
applicationContext = (Init) context.getApplicationContext();
if (applicationContext.containsInGlobalStore(GLOBAL_NAME))
Logger.log("Warning " + GLOBAL_NAME
+ " is already created. This will remove all old datas");
new Accounts(GLOBAL_NAME, applicationContext);
}
private static final String GLOBAL_NAME = "accounts";
public static Accounts getInstance() {
try {
return (Accounts) applicationContext
.takeFromGlobalStore(GLOBAL_NAME);
} catch (Exception e) {
Logger.log("GLOBAL_NAME Lost");
return null;
}
}
Please help.
You should know that the application context itself gets destroyed if left unused for a long time in the background. So there is no guarantee that your static and singleton objects will not be cleared when the app is in background. Instead what you can do is persist your objects from time to time (either in a flat-file or shared preference or database) and restore them in the onCreate method of the Application class
I have been using this method in my application and i didn't see any problem unless my process gets killed by the OS or if there is a crash in my application and my app gets restarted.
If you think whatever data you are storing is valid for only life time of a program why don't you override OnCreate of Application object and create all your singletons there. This way you can always make sure your application has all singletons before your app starts functioning.
Application class is not permanent.
If App process killed, Application class private member variable data loss.
Using Shared Preferences.
I know this question was asked a long time ago, but here's a good article that suggests using the Application object to store data is generally not a sound design methodology.

Using Application context everywhere?

In an Android app, is there anything wrong with the following approach:
public class MyApp extends android.app.Application {
private static MyApp instance;
public MyApp() {
instance = this;
}
public static Context getContext() {
return instance;
}
}
and pass it everywhere (e.g. SQLiteOpenHelper) where context is required (and not leaking of course)?
There are a couple of potential problems with this approach, though in a lot of circumstances (such as your example) it will work well.
In particular you should be careful when dealing with anything that deals with the GUI that requires a Context. For example, if you pass the application Context into the LayoutInflater you will get an Exception. Generally speaking, your approach is excellent: it's good practice to use an Activity's Context within that Activity, and the Application Context when passing a context beyond the scope of an Activity to avoid memory leaks.
Also, as an alternative to your pattern you can use the shortcut of calling getApplicationContext() on a Context object (such as an Activity) to get the Application Context.
In my experience this approach shouldn't be necessary. If you need the context for anything you can usually get it via a call to View.getContext() and using the Context obtained there you can call Context.getApplicationContext() to get the Application context. If you are trying to get the Application context this from an Activity you can always call Activity.getApplication() which should be able to be passed as the Context needed for a call to SQLiteOpenHelper().
Overall there doesn't seem to be a problem with your approach for this situation, but when dealing with Context just make sure you are not leaking memory anywhere as described on the official Google Android Developers blog.
Some people have asked: how can the singleton return a null pointer?
I'm answering that question. (I cannot answer in a comment because I need to post code.)
It may return null in between two events: (1) the class is loaded, and (2) the object of this class is created. Here's an example:
class X {
static X xinstance;
static Y yinstance = Y.yinstance;
X() {xinstance=this;}
}
class Y {
static X xinstance = X.xinstance;
static Y yinstance;
Y() {yinstance=this;}
}
public class A {
public static void main(String[] p) {
X x = new X();
Y y = new Y();
System.out.println("x:"+X.xinstance+" y:"+Y.yinstance);
System.out.println("x:"+Y.xinstance+" y:"+X.yinstance);
}
}
Let's run the code:
$ javac A.java
$ java A
x:X#a63599 y:Y#9036e
x:null y:null
The second line shows that Y.xinstance and X.yinstance are null; they are null because the variables X.xinstance ans Y.yinstance were read when they were null.
Can this be fixed? Yes,
class X {
static Y y = Y.getInstance();
static X theinstance;
static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;}
}
class Y {
static X x = X.getInstance();
static Y theinstance;
static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;}
}
public class A {
public static void main(String[] p) {
System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance());
System.out.println("x:"+Y.x+" y:"+X.y);
}
}
and this code shows no anomaly:
$ javac A.java
$ java A
x:X#1c059f6 y:Y#152506e
x:X#1c059f6 y:Y#152506e
BUT this is not an option for the Android Application object: the programmer does not control the time when it is created.
Once again: the difference between the first example and the second one is that the second example creates an instance if the static pointer is null. But a programmer cannot create the Android application object before the system decides to do it.
UPDATE
One more puzzling example where initialized static fields happen to be null.
Main.java:
enum MyEnum {
FIRST,SECOND;
private static String prefix="<", suffix=">";
String myName;
MyEnum() {
myName = makeMyName();
}
String makeMyName() {
return prefix + name() + suffix;
}
String getMyName() {
return myName;
}
}
public class Main {
public static void main(String args[]) {
System.out.println("first: "+MyEnum.FIRST+" second: "+MyEnum.SECOND);
System.out.println("first: "+MyEnum.FIRST.makeMyName()+" second: "+MyEnum.SECOND.makeMyName());
System.out.println("first: "+MyEnum.FIRST.getMyName()+" second: "+MyEnum.SECOND.getMyName());
}
}
And you get:
$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull
Note that you cannot move the static variable declaration one line upper, the code will not compile.
Application Class:
import android.app.Application;
import android.content.Context;
public class MyApplication extends Application {
private static Context mContext;
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static Context getAppContext() {
return mContext;
}
}
Declare the Application in the AndroidManifest:
<application android:name=".MyApplication"
...
/>
Usage:
MyApplication.getAppContext()
You are trying to create a wrapper to get Application Context and there is a possibility that it might return "null" pointer.
As per my understanding, I guess its better approach to call- any of the 2
Context.getApplicationContext() or Activity.getApplication().
It is a good approach. I use it myself as well. I would only suggest to override onCreate to set the singleton instead of using a constructor.
And since you mentioned SQLiteOpenHelper: In onCreate () you can open the database as well.
Personally I think the documentation got it wrong in saying that There is normally no need to subclass Application. I think the opposite is true: You should always subclass Application.
I would use Application Context to get a System Service in the constructor. This eases testing & benefits from composition
public class MyActivity extends Activity {
private final NotificationManager notificationManager;
public MyActivity() {
this(MyApp.getContext().getSystemService(NOTIFICATION_SERVICE));
}
public MyActivity(NotificationManager notificationManager) {
this.notificationManager = notificationManager;
}
// onCreate etc
}
Test class would then use the overloaded constructor.
Android would use the default constructor.
I like it, but I would suggest a singleton instead:
package com.mobidrone;
import android.app.Application;
import android.content.Context;
public class ApplicationContext extends Application
{
private static ApplicationContext instance = null;
private ApplicationContext()
{
instance = this;
}
public static Context getInstance()
{
if (null == instance)
{
instance = new ApplicationContext();
}
return instance;
}
}
I'm using the same approach, I suggest to write the singleton a little better:
public static MyApp getInstance() {
if (instance == null) {
synchronized (MyApp.class) {
if (instance == null) {
instance = new MyApp ();
}
}
}
return instance;
}
but I'm not using everywhere, I use getContext() and getApplicationContext() where I can do it!
I know the original question was posted 13 years ago, and this is the Kotlin version of getting context everywhere.
class MyApplication : Application() {
companion object {
#JvmStatic
private var instance: MyApplication? = null
#JvmStatic
public final fun getContext(): Context? {
return instance
}
}
override fun onCreate() {
instance = this
super.onCreate()
}
}

Categories

Resources