I have Android application and own Application derived class holding some internal data.
Among other there are some string fields. The problem is that if I put the application in foreground, work on other application, switch back to my app again, the app may be restarted because it got killed by system. Unfortunatelly the Application object seems not to be created again because the onCreate method of application object doesn't get called and all fields are set to null. My Activity gets recreated but all Application's object fields are null. When is the Application.onCreate method called? How to handle it?
there is no onCreate that you can register to.in later API's there's a way to register to the Activity lifecycle functions. and then you can do what ever you want.
basically, what you should do is use SharedPrefrences for storing information.
what I would do is:
class MyApp extends Application {
private static String someResource = null;
public static String getSomeResource(Context context) {
if(someResource == null) {
SharedPrefrences prefs = (SharedPrefrences)
context.getSystemService(Context.SHARED_PREFRENCES);
someResource = prefs.getString(SOME_RESOURCE, null);
}
return someResource;
}
Application onCreate() will called only for one time during its life-cycle, i.e.. only when application is started.
As suggested by thepoosh below answer is valid ,if your application is killed,still the data is saved in shared preference.
Related
I have an android application
#HiltAndroidApp
class MyApp extends Application {
static MyApp app;
static MyApp getApp() {
return app;
}
#Override
public void onCreate() {
super.onCreate();
app = this;
}
}
and I am trying to use it inside a class
class AppStateUsingClass {
public void mymethod() {
MyApp app = MyApp.getApp();
//use app
}
}
Now I can access the app where I don't have the context but I am not sure if its correct way of doing.
My understanding is that the application life cycle is through out app start and stop, therefore its lives as a Singleton so it shall be fine but not sure.
Isn't there any simpler cleaner API to access app, I have app state in MyApp class which I would like to access where context is absent?
Any suggestions are highly appreciated?
What you are doing is a fairly common pattern, and shouldn't really cause problems.
The application class can be treated as a singleton that is alive as long as any part of your application is alive.
The docs specifically state that this class is used to hold application state.
However, depending your actual design, the kind of state information you want to hold and where you want to access it, you may want to create your own singleton, independent of the application class and use that.
Or, you may want to initialize your AppStateUsingClass with a state object passed in the constructor.
This is a design decision, and if you want more opinions on it, create a working code example and post it on https://codereview.stackexchange.com
We've recently started running into crashes in our Android app due to the app being open in multiple processes. Several different errors point towards that. For instance this error:
com.google.firebase.database.DatabaseException: Failed to gain
exclusive lock to Firebase Database's offline persistence. This
generally means you are using Firebase Database from multiple
processes in your app. Keep in mind that multi-process Android apps
execute the code in your Application class in all processes, so you
may need to avoid initializing FirebaseDatabase in your Application
class. If you are intentionally using Firebase Database from multiple
processes, you can only enable offline persistence (i.e. call
setPersistenceEnabled(true)) in one of them.
We are also seeing similar errors from SQLite and H2. This is a new issue and we have not explicitly allowed multiple processes to run. Nothing in our AndroidManifest.xml specifies a custom android:process attribute.
I suspect that some third party library is causing this. How do I identify the root cause of the multiple processes and how do I prevent it?
Another of our apps is connecting to this app via a ContentProvider. At first I thought that it having android:multiprocess="true" was the culprit but changing it to "false" did not help. I still suspect that the other app is somehow triggering the creation of a new process. This is how to the ContentProvider is defined:
<provider
android:name=".DegooContentProvider"
android:authorities="${applicationId}.DegooContentProvider"
android:exported="true"
android:protectionLevel="signature"
android:multiprocess="false">
</provider>
You can check in your applicaition class if there is foreign process. Here is an example:
public class MyApp extends Application {
#Override
public void onCreate() {
super.onCreate();
if (!isMainProcess()) {
// Do not call thread unsafe logic. Just return
return;
}
// Thread unsafe logic.
...
}
private boolean isMainProcess() {
int pid = android.os.Process.myPid();
ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
String currentProcName = processInfo.processName;
if (processInfo.pid == pid) {
if (TextUtils.equals(currentProcName, BuildConfig.APPLICATION_ID)) {
return true;
}
}
}
return false;
}
}
Looks like you are calling the method setPersistenceEnabled() multiple times.
Ensure it is not. You can do this in a several ways.
The preferred method will be to place it only in the onCreate() method of the default Application class if you are extending one.
Another solution will be to place it in the static block of any class.
static {
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
Or you can even set a static boolean variable say, inFirebaseInstanceInitialized and call setPersistenceEnabled() only if it is not true already.
In my android application, I have extended Application class. I am having some meta data which I do not want to re-initialize again and again. I initialize them in Application class and then use them.
private SampleSettings getSettings(){
return sampleSettings;
}
public class SampleApplication extends Application {
public void onCreate(){
super.onCreate();
sampleSettings = getSettingsFromDB();
}
}
Here getSettings returns null in some cases when accessed in application using applicationContext.
Sometime I am getting null pointer exception for such properties. I have seen when the app goes to background it occurs but not frequently.
My understanding is that those values should not become as long as application is started.
What am I missing which is causing them to become null?
Thanks
Your process does not live forever. When you are not in the foreground, your process may be terminated at any time by Android, to free up system RAM for other apps.
A custom Application object, or any static fields, are only for caching and other in-flight data. Your app needs to be able to start up, from any activity, lazy-initializing all of that as needed.
I am combining a static code analysis with a dynamic one. I basically create a new activity and set it up as the starting activity. During the run various methods in existing activities should be called.
I can call e.g. onCreate from outside, however, the super call to Activity will fail (or calls to SharedPreferences or other interesting classes) since Android does some initialization stuff when using the intents in order to call an activity (e.g. setting the context). But I need to somehow call methods like onCreate or onPause from outside while giving the target activity a valid context.
In my newly created activity I have got a valid context. I tried to pass it via calling ContextWrapper.attachBaseContext, but there is still a NullPointerException somewhere in Android due a the missing context. Is there some way to hack this somehow into a working state? Using reflection or other hacks would be no problem, since it is for analysis purposes only.
Thank you very much for any tips. I'd be able to modify the analyzed apps in any way to get this working.
However: Using an Intent is no option, since I cannot control which Activity-methods are being called, when and how often. I know that android has not been made for calling these methods directly, but it is not a common use case either :);
I have created a hack, which seems to help (I can get a valid context in the hacked activity). Let's see how far I get using this.
public static void hack(Activity hack, Activity main) {
try {
Field mActivityInfo = getField(Activity.class, "mActivityInfo");
mActivityInfo.set(hack, getClass("android.content.pm.ActivityInfo").newInstance());
Field mFragments = getField(Activity.class, "mFragments");
Field mContainer = getField(Activity.class, "mContainer");
Field mApplication = getField(Activity.class, "mApplication");
Field mWindow = getField(Activity.class, "mWindow");
Class FragmentManagerImpl = getClass("android.app.FragmentManagerImpl");
FragmentManager manager = (FragmentManager) mFragments.get(hack);
mApplication.set(hack, main.getApplication());
mWindow.set(hack, main.getWindow());
Class<?> FragmentContainer = getClass("android.app.FragmentContainer");
Method attachActivity = getMethod(FragmentManagerImpl, "attachActivity", Activity.class, FragmentContainer, Fragment.class);
attachActivity.invoke(manager, hack, mContainer.get(hack), null);
Method attachBaseContext = getMethod(ContextWrapper.class, "attachBaseContext", Context.class);
attachBaseContext.invoke(hack, new HackContext(main));
System.out.println("Hack performed");
} catch (Exception e) {
e.printStackTrace();
System.err.println("Hack failed :(");
}
}
I am trying to generate a notification from a class, Utilities.java, outside of the subclass of Context. I've thought about providing a SingletonContext class and have looked at posts ike this. I'd like to be able to return != null Context object since the notification can be generated at any given time because it is generated from a messageReceived() callback.
What are there downsides to doing something like this:
public static Context c;
public class MainActivity extends Activity{
#Override
public void onStart()
super.onStart()
c = this.getApplicationContext();
}
//other method somewhere outside this class
public Context getContext(){
return MainActivity.c
}
I don't think it would be any different than putting this on the onCreate(), however, it guarantees that the context is up to date when the activity starts.
The Context keeps a reference to this activity in memory, which you might not want. Perhaps use
this.getApplicationContext();
instead. This will still let you do file IO and most other things a context requires. Without a specific reference to this activity.
Maybe you should overwrite the onResume Method.
If you open a new activity, and switch back, the onStart method will not getting invoked.
Android Lifecycle: doc
BTW: I read about problems with ApplicationContext using a dialog or toast, so if you use the context to create on of these you should use your Activity as context.