Sporadic crashes when trying to get application object - java

My app is reporting an occasional NullPointerException on the following line:
MyApplication.myAppInstance.updateDay();
from which I understand that myAppInstance is null. The above line is being called in the onStart() method of one of the app's main activity right below super.onStart()
In the application class I have:
public static MyApplication myAppInstance;
public MyApplication() {
myAppInstance = this;
}
And that's the only place the variable gets written to in code.
The crash only happens on Android 9.
What would be causing this? The app kinda assumes that the application instance will always be available.
I should note that this crash only appears in the Play Console and not in Crashlytics.
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3194)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3302)
at android.app.ActivityThread.-wrap12 (Unknown Source)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1891)
at android.os.Handler.dispatchMessage (Handler.java:108)
at android.os.Looper.loop (Looper.java:166)
at android.app.ActivityThread.main (ActivityThread.java:7425)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:245)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:921)
Caused by: java.lang.NullPointerException:
at com.timSim.myScheduler.MainActivity.onStart (MainActivity.java:667)
at android.app.Instrumentation.callActivityOnStart (Instrumentation.java:1339)
at android.app.Activity.performStart (Activity.java:7392)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3157)
This is happening to a very small number of users, so I can't replicate it.

To use Application class. You need to declare it in the manifests.xml.
Try this:
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:name=".MyApplication"
.../>
And
class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
// TODO:
}
}

Related

InternalSyntheticLambda in Crash report

I got following crash report:
java.lang.NullPointerException:
at com.myapp.actions.SellAction.getAction (SellAction.java:16)
at com.myapp.handler.SellHandler.sell (SellHandler.java:169)
at com.myapp.main.MyActivity.sell (MyActivity.java:537)
at com.myapp.main.Fragment2.lambda$onCreateView$0 (Fragment2.java:31)
at com.myapp.main.Fragment1$$InternalSyntheticLambda$1$c14fd7a0fe0c17e220e277448d1b71579f8038a9784d642f5a2e5b6a00f377eb$2.onClick$bridge (Fragment1.java)
at android.view.View.performClick (View.java:7862)
at android.widget.TextView.performClick (TextView.java:15004)
at android.view.View.performClickInternal (View.java:7831)
at android.view.View.access$3600 (View.java:879)
at android.view.View$PerformClick.run (View.java:29359)
at android.os.Handler.handleCallback (Handler.java:883)
at android.os.Handler.dispatchMessage (Handler.java:100)
at android.os.Looper.loop (Looper.java:237)
at android.app.ActivityThread.main (ActivityThread.java:8167)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1100)
The code from Fragment2.lambda$onCreateView$0 (Fragment2.java:31) to SellAction.getAction is a valid stacktrace in my code. But usually (I don't see how this is possible) the Fragment1 (Fragment1$$InternalSyntheticLambda$1$c14fd7a0fe0c17e220e277448d1b71579f8038a9784d642f5a2e5b6a00f377eb$2.onClick$bridge (Fragment1.java)) has nothing to do with that code and I have no idea how it appears there. I don't know if that has something to do with the InternalSyntheticLambda. But I do not find anything about that on the internet (10 search results at google). Does anyone here has an idea what that is or how that can happen?
Looks like some handler or listener is leaking.
Try to look through all the call chain between
at com.myapp.actions.SellAction.getAction (SellAction.java:16)
and
at com.myapp.main.Fragment2.lambda$onCreateView$0 (Fragment2.java:31)
There might be view or some other object that is set up with listener which is not dropped correctly on view destroy. Special attention to Fragment2#onCreateView line 31.

utility class's static member (null) lifecycle

I have a utility class that has constants and static methods.
Furthermore, that has one static field.
public class MyUtil implements IMyUtil {
public static String IS_DEBUG = false;
...
private static MyEnumType mMyEnum;
...
// static getter setter methods for mMyEnum
}
I have two fragments (FragmentA and FragmentB for the sake of simplicity).
FragmentA set the mMyEnum value, and then later use it with the getter method. When the user presses a button, I show FragmentB.
In the onActiviyCreated() method of FragmentB I get the mMyEnum value.
On my test devices everything is ok. But in the Google Play Console I see a bunch of NullPointerException errors at this line:
String testString = MyUtil.getMyEnum().getSomeStringValue();
I can't figure it out why can be myEnum null on that line and why I can't reproduce it. MyUtil obviously can't be null, getSomeStringValue() can be null, but it doesn't throw a NullPointerException, so the only myEnum can be null. But why? And if it can be null how can I reproduce it?
Thank you.
UPDATE #1:
Play shows a wide range of devices (Samsung A3, S6, S7, S8, LG X, G3, Huawei P9 etc.) and API versions (5.0 -> 7.1). Full stack trace is:
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2984)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1642)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:154)
at android.app.ActivityThread.main (ActivityThread.java:6776)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1386)
Caused by: java.lang.NullPointerException:
at com.mycompany.fragment.FragmentB.onActivityCreated (FragmentB.java:35)
at android.support.v4.app.Fragment.performActivityCreated (Fragment.java:2089)
at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManagerImpl.java:1133)
at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManagerImpl.java:1290)
at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManagerImpl.java:1272)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated (FragmentManagerImpl.java:2149)
at android.support.v4.app.FragmentController.dispatchActivityCreated (FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart (FragmentActivity.java:600)
at android.support.v7.app.AppCompatActivity.onStart (AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart (Instrumentation.java:1256)
at android.app.Activity.performStart (Activity.java:6972)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2937)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1642)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:154)
at android.app.ActivityThread.main (ActivityThread.java:6776)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1386)
Long-lived Static members present a problem because Android may have freed memory and removed this value at some time (when no fragment is active with a reference to it). You also haven't explicitly said whether you can get to FragmentB without setting a value from FragmentA first, so this could also be your problem.
Additional note - a constant should be constant - so should have the final keyword.
My suggested solution would be to get rid of this bad architecture where two components are relying on an outside god-object to maintain their state. Pass your enum value as an Extra in the intent.
You can write to the bundle with
public static final String KEY_ENUM = "MyEnumKey";
bundle.putString(KEY_ENUM, myEnum.name()):
and then read it back with
Bundle bundle = intent.getExtras();
MyEnumTypemyEnum = MyEnumType.valueOf(bundle.getString(FragmentA.KEY_ENUM));
Another suggestion is to ensure that myEnum is never null (which by default it is). Declare it like:
private static MyEnumType mMyEnum = MyEnumType.MY_DEFAULT_VALUE;

Android JAVA RX exception only from the play store

Hello everyone i have this exception from RX on my google play console, i've have never see it on my project but it occurred about 200 times as google play says... any one has an idea about that ?
java.lang.IllegalStateException:
at rx.android.schedulers.LooperScheduler$ScheduledAction.run (LooperScheduler.java:114)
at android.os.Handler.handleCallback (Handler.java:739)
at android.os.Handler.dispatchMessage (Handler.java:95)
at android.os.Looper.loop (Looper.java:158)
at android.app.ActivityThread.main (ActivityThread.java:7230)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)
**Caused by: rx.exceptions.OnErrorFailedException:**
at rx.observers.SafeSubscriber._onError (SafeSubscriber.java:187)
at rx.observers.SafeSubscriber.onError (SafeSubscriber.java:115)
at rx.exceptions.Exceptions.throwOrReport (Exceptions.java:216)
at rx.observers.SafeSubscriber.onNext (SafeSubscriber.java:139)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onNext (OnSubscribeDoOnEach.java:101)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call (OperatorObserveOn.java:224)
at rx.android.schedulers.LooperScheduler$ScheduledAction.run (LooperScheduler.java:107)
Your code is throwing an exception that is not caught.
Have you specified an function for onError?
[Your Observable].subscribe(value -> {
// Your onNext code
}, throwable -> {
// Handle error
});

Screen Locked causing Unable to find explicit activity class have you declared this activity in your AndroidManifest.xml?

I have been getting this error in my application for quite a sometime now at few client devices. I have posted a related question Here but found not useful answer.
After weeks of research and testing, i reproduce this error at development machine.
On login activity, after user insert required credentials and click Login button, I am running a AsyncTask to validate the credentials over the server. In between i am showing ProgressDialog to the user. In case if am locked the device during doInBackground execution using device hardware lock key or it dims by own and lock, PostExecute method throws exception. Following is code snippet of PostExecute. Normally without Locking the device it works well
if(EveryThing Goes Well)
{
progressDialogUtil.Dismiss();
Intent selectBikeActivity = new Intent(getApplicationContext(), SelectBike.class);
startActivity(selectBikeActivity); // Here Raised Exception
finish();
}
......
StackTrace is
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.yego.motodriver/com.yego.motodriver.SelectBike}; have you declared this activity in your AndroidManifest.xml?
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1523)
at android.app.Activity.startActivityForResult(Activity.java:3968)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
at android.app.Activity.startActivityForResult(Activity.java:3920)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
at android.app.Activity.startActivity(Activity.java:4259)
at android.app.Activity.startActivity(Activity.java:4227)
at com.yego.motodriver.Login.HandleLoginResponse(Login.java:502)
at com.yego.motodriver.Login.access$300(Login.java:61)
at com.yego.motodriver.Login$4.onGRPCTaskCompleted(Login.java:233)
at com.yego.util.GrpcTask.onPostExecute(GrpcTask.java:297)
at com.yego.util.GrpcTask.onPostExecute(GrpcTask.java:38)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5742)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
How to avoid this Exception ?
You have not declare your activity in AndroidManifest.xml like :
<activity
android:name=".SelectBike"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan"/>

Occasionally receiving WarningContextClassLoader instead of PathClassLoader causing flyway to crash

Context
In my android app, I use flyway to update my Db schema. Up to now I have one and only one migration, that creates 3 tables. Simple and usual business for flyway. It does work very well... most of the time! Sometimes it crashes with this error (full stack hereunder):
java.lang.ClassCastException: android.app.LoadedApk$WarningContextClassLoader
cannot be cast to dalvik.system.PathClassLoader
I have several questions related to that error :
What is LoadedApk.WarningContextClassLoader ?
Why is it sometimes used instead of dalvik.system.PathClassLoader ?
Is it a bug in my app, in Android system or in Flyway ?
I also noticed that I can inject explicitely the classloader inside flyway (Flyway.setClassLoader() )
How can I get for sure the right classloader ?
Note that I inject the Application Context in Flyway, not a particular activity's context.
Versions
I use org.flywaydb:flyway-core:4.0.2
I noticed this problem in Android 4.2.2 (JellyBean, api level 17) and 4.4 (KitKat, api level 19). AFAIK, it never occured on higher versions.
Stack trace
Exception java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mycompany.myapp.free.debug/com.mycompany.MainActivity}: java.lang.ClassCastException: android.app.LoadedApk$WarningContextClassLoader cannot be cast to dalvik.system.PathClassLoader
android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2306)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2358)
android.app.ActivityThread.access$600 (ActivityThread.java:156)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1340)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loop (Looper.java:153)
android.app.ActivityThread.main (ActivityThread.java:5299)
java.lang.reflect.Method.invokeNative (Method.java)
java.lang.reflect.Method.invoke (Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:833)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:600)
dalvik.system.NativeStart.main (NativeStart.java)
Caused by java.lang.ClassCastException: android.app.LoadedApk$WarningContextClassLoader cannot be cast to dalvik.system.PathClassLoader
org.flywaydb.core.internal.util.scanner.classpath.android.AndroidScanner.<init> (AndroidScanner.java:46)
org.flywaydb.core.internal.util.scanner.Scanner.<init> (Scanner.java:38)
org.flywaydb.core.Flyway.execute (Flyway.java:1353)
org.flywaydb.core.Flyway.info (Flyway.java:1040)
com.mycompany.db.FlywayHelper.info (FlywayHelper.java:54)
com.mycompany.db.FlywayHelper.migrate (FlywayHelper.java:45)
com.mycompany.db.GW2DatabaseHelper.migrate (GW2DatabaseHelper.java:56)
com.mycompany.db.DbInit.initKeyGuild (DbInit.java:62)
com.mycompany.db.DbInit.init (DbInit.java:42)
com.mycompany.business.BootApp.boot (BootApp.java:79)
com.mycompany.MainActivity.onCreate (MainActivity.java:51)
android.app.Activity.performCreate (Activity.java:5122)
android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1081)
android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2270)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2358)
android.app.ActivityThread.access$600 (ActivityThread.java:156)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1340)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loop (Looper.java:153)
android.app.ActivityThread.main (ActivityThread.java:5299)
java.lang.reflect.Method.invokeNative (Method.java)
java.lang.reflect.Method.invoke (Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:833)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:600)
dalvik.system.NativeStart.main (NativeStart.java)
Research update
Although its purpose is not clear to me, LoadedApk.WarningContextClassLoader appears to be a valid class loader, and should then be supported by Flyway. A pull request has been submitted.
In between, a workaround needs to be implemented, to inject the expected class loader:
private void injectClassLoader(Flyway flyway) {
ClassLoader classLoader = flyway.getClassLoader();
if (classLoader != null && !(classLoader instanceof PathClassLoader)){
flyway.setClassLoader(classLoader.getParent());
}
}
There's decent info the the commit message adding WarningContextClassLoader. I would guess passing the activity's context may help.
What is LoadedApk.WarningContextClassLoader ?
Why is it sometimes used instead of dalvik.system.PathClassLoader ?
Not really sure, but the purpose of this specific class loader seems to warn the user that its package could be sharing its virtual machine with other packages. More info here, thanks to #orip.
Is it a bug in my app, in Android system or in Flyway ?
Anyway the WarningContextClassLoader is still a valid class loader, and must be accepted by flyway. The cast made in AndroidScanner was just useless.
Solution
The bug is now fixed in flyway 4.1.

Categories