I need to call getPackageName early in the application lifecycle. I tried to call it in the Application constructor only to see that it throws NullPointerException. I had a look at the Android source code and found that Android calls the internal attach method which in turn calls the documented protected attachBaseContext method. Once I moved my code from the constructor into attachBaseContext everything works as expected.
Question: is it good idea to assume attachBaseContext method as a kind of extension to the Application constructor?
If you need just pacakageName I would suggest to use BuildConfig#APPLICATION_ID, because it is static variable and doesn't require waiting for application initialization. Difference between package name and application id you can find here.
If you anyway need some entry point to application, IMHO it seems to be a good idea to use attachBaseContext(Context c) method, because:
It might be called only once (as constructor).
It is the first place in Application where you can get application context
Related
I have been receiving some crash reports in the Play Store which initially seemed crazy to me.
Some activities (in 1 case, it's a broadcast receiver) are crashing in onCreate()/onResume() due to NullPointerException.
These activities are using static methods which in turn use the Application singleton [for context], but the object returned is null like if the application object didn't exist at all. From my understanding, the application should always have an instance.
My code is ordinary, the application sets a static field in its onCreate(), and the classes that the activities call use MyApplication.getInstance() which returns the application object.
How can MyApplication.getInstance() return null when called from activities? I have no idea how that could happen.
Of course, I have been unable to replicate this crash.
This mainly happens in Android 6, but I have some reports from Android 8 and 9.
I guess you are doing what the most voted answer says in this question.
However, you should see what many people warn in the comments:
The downside is that there is no guarantee that the non-static
onCreate() will have been called before some static initialization
code tries to fetch your Context object. That means your calling code
will need to be ready to deal with null values which sort of defeats
the whole point of this question. – Melinda Green
.
It's upsetting to see how many upvotes this answer has. You should never hold a static instance to context - for proofs sake, try using Leak Canary (github.com/square/leakcanary) and find the memory leak caused because of this. #people-with-enouhg-rep-and-Android-knowledge, please re-review this answer and act accordingly. This is guaranteed to be used by beginners and it's plain simple wrong. – Crearo Rotar
You should either:
User your Activity context whenever possible and pass it to any other class that needs it.
Or, what I really recommend, set up dependency injection using Dagger2. It is a little difficult to learn at the beginning, but there is a lot of information and tutorials to help you get started. Once you setup Dagger properly, all you need to access you Application context in a null-safe way is Inject it in the corresponding class like this:
public class MyClass {
#Inject
Context context;
...
}
As an alternative to the other answer about dagger dependency injection I just wanted to give an example of getting context from an activity the old fashioned way. If you declare context as a member variable it will be available all over your activity and can be passed to other classes as needed:
public class ExampleActivity extends AppCompatActivity {
private Context mContext;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
mContext = this;
}
I think I found the cause. In Android 6 auto restore not initializing app, the problem is the same and they identified the cause as being the auto backup feature that was introduced in Android 6. Basically, after a restore from the backup, the app is restarted in a weird way where the Application object is not created before the Activity. We now can reproduce the problem and disabling backup fixes the problem.
in my app, there are 5 classes and 1 activity. This activity has, as you all know, an OnDestroy() method. In this method I need to remove a test provider which is set up in another class called "mockingclass".
In "mockingclass" I have a method similar to this:
public void mocker()
{
xxx
location.RemoveTestProvider(location.GpsProvider);
xxx
}
While xxx stands for many other functions in this method, when the app is being destroyed I need to call ONLY for that ONE function in within this whole method.
Is there any way to do that at all? If not, what would be your suggestions?
THANKS!
Obviously you can't choose a single line from method to be executed. You need to extract it separate method which will be called separately. Maybe you should look at some injection? Let this call be injected as an delegate for example. In that way you could manipulate what should be called depending on situation.
I am trying to use this solution inside my Fragment, however I couldn't be sure where to call System.LoadLibrary(), finally I decided to call from onCreate method of the Fragment, I want to be sure if this would not raise some another weird error on different devices.
General it won't cause weird behaviours, as onCreate is mandatory callback when your fragment created by system. This make sure your native library is prepared before you do further operation in your fragment.
Take a look at fragment life cycle, it might be better if you put your library initialize routine on the first callback onAttach, you can use the attached Activity context to initialize your native library.
It is just a static initialization. You don't even have to have it inside your onCreate() at all. You can simply initialize it as the first part of your class next to your global variables as such:
class YourClass
{
static
{
System.loadLibrary( yourLib );
}
...
}
It is only important that it is done early or you may see UnsatisfiedLinkError followed by application's crash. That way whenever a call referenced later is made, the library itself has already been loaded. A static declaration at the top will do that as soon as an instance of the class has been requested; even before onCreate().
I have a class in my Android application that sub-classes the AndroidApplication object. The documents say:
public void onCreate ()
Since: API Level 1 Called when the
application is starting, before any
other application objects 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().
I placed a breakpoint on my sub-class's constructor and when I run my application, it is never reached. Naturally, when I call the sub-class's getInstance() method from other code it returns NULL since the instance variable is (supposed to be) initialized when the constructor is called.
Can anyone tell me what is wrong? I would assume from the docs that I don't have to create an instance of the AndroidApplication sub-class myself, or do I? Am I supposed to modify my manifest file somehow to add the AndroidApplication sub-class and if so, how?
-- roschler
I'm posting the answer here for others. Yes you need to add the name of your Application object sub-class's name to the Android manifest. For Eclipse users, the easiest way to do this is to open the AndroidManifest.xml file, select the Application tab in the manifest editor, and use the Browse button next to the Name field to find your Android Application object sub-class name and select it. The manifest file will be updated properly to register it. I just did that and it worked.
I had a problem of not having a . before my application class name.
Should be:
android:name=".MyApp"
since the MyApp class is in the package defined in the manifest.
I'm new to this and I'm sorry if this is a really dumb question. I'm just trying to clarify things. My book says I can retrieve application context for process by using the getApplicationContext() method. I just really don't know where to type this or what to do with any of it. I can go to the hierarchy but what do I do with all the script there. Also where would I write Activity Callbacks, in the main.xml? An exercise wants me to add a logging tag to my project but I'm not sure how to do this. The exact text says:
"Within the onCreate() callback method, add an informational logging message, using the Log.i() method."
and another exercise says to:
"Implement some of the Activity callback methods in addition to onCreate(), such as onStart(). Add a log message to each callback method and then run the application normally".
As these seem like basic questions, can someone please help me.
I am using the Android SDK, and Eclipse. I have made the Hello World application, but I have no idea what to do with Context or Retrieving resources. Please help!
The first rule I would give you: if you don't know why you need it, you probably don't need it. Use your activity object as the Context when you need a context.
The callbacks you talk about are on the Activity class. The Application Fundamentals describes what an Activity is: http://developer.android.com/guide/topics/fundamentals.html#Components
The only time you want to use getApplicationContext() is when you need a Context that exists outside of the lifecycle of an Activity class (or other component). You'll want to find documentation on specific cases where this is desired, there is a lot floating around. For example this one is part of the Android documentation: http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html
For the tasks you're working with here, you'll be using the Java code that defines the behavior of the application, not the XML files that define resources and layouts or the AndroidManifest.xml file that declares basic application properties.
If you're working with Hour 3 of the Sam's Teach Yourself... book, then you need to open the src\com.androidbook.droid1\DroidActivity.java file. In general, you would need src\<package-name>\<class-name>.java. When you open that file, you'll see a class (in this case, DroidActivity) that extends Activity and already has the onCreate() callback method. Anything that you want to happen during onCreate() goes inside that method. Other callback methods can be added inside the activity class. To see an example that has all the lifecycle callbacks (but doesn't do anything in them), look here.
A logging tag is just a string. You can declare it, for example, as a private static final String inside the activity class.
If there's confusion about where methods belong, where and how to define variables or constants, how to call methods, how to use classes, and so forth, then it might be best to go through an introductory Java text before starting with Android. There are plenty of free resources available for that.