NullPointerException in Cordova App reported by Fabric SDK - android

I am using Ionic framework to build the hybrid Android app and the app works fine. I am using Fabric Crash analytics plugin and its reporting the crashes of the app.
I am getting the below crash details very often and not sure what's the reason for the same. I am not sure what would be the starting point to start analysizing this.
Fatal Exception: java.lang.NullPointerException
at android.webkit.WebViewClassic.setNetworkAvailable(WebViewClassic.java:4224)
at android.webkit.WebView.setNetworkAvailable(WebView.java:731)
at org.apache.cordova.engine.SystemWebViewEngine$1.setNetworkAvailable(SystemWebViewEngine.java:112)
at org.apache.cordova.NativeToJsMessageQueue$OnlineEventsBridgeMode$2.run(NativeToJsMessageQueue.java:340)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5319)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(NativeStart.java)
Is it related to any plugin or any issue in Ionic or Cordvoa? Any help or advise would be helpful.

I have the same problem. I also use Cordova and Fabric Crashlytics.
It's reproduced only on Android 4.1.2, 4.2.2, 4.3.
I have reproduced the bug:
open WebView with content that contain javascript functions;
open new WebView and close it;
disable network (wifi and mobile) as soon as possible;
return to app and show stacktrace.
I found a solution:
I'm not using CordovaActivity in my app. I'm using CordovaInterface.
PluginManager associated with deleted WebView continues to call its methods. So I manual call WebView.handleDestroy() to destroy PluginManager.
In my Fragment:
#Override
public void onDestroy()
{
if (webView != null)
{
webView.handleDestroy();
webView.destroy();
webView = null;
}
super.onDestroy();
}
Update:
It's reproduced when you destroy WebView, but PluginManager continues to live and sends javascripts events to subscribers (WebViews). Because I call WebView.handleDestroy().

You could swallow the exception? Edit this file:
/platforms/android/CordovaLib/src/org/apache/cordova/engineChange/SystemWebViewEngine.java
And change this
webView.setNetworkAvailable(value);
to this
import java.lang.NullPointerException;
...
try {
webView.setNetworkAvailable(value);
}
catch (NullPointerException e) {
Log.d(TAG, "webView.setNetworkAvailable called after destroy");
}
Not really a solution, but given the difficulty in reproducing locally, it may be an option to consider.

My solution was in SystemWebViewEngine.java.
change protected final SystemWebView webView; to protected SystemWebView webView;
in destroy() method after
if (receiver != null)
{
try
{
webView.getContext().unregisterReceiver(receiver);
}
catch (Exception e)
{
Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
}
}
add
webView = null;
Replace webView.setNetworkAvailable(value); with
if (webView != null)
webView.setNetworkAvailable(value);

Related

Xamarin.Forms app works on iOS, throws error on Android ("Object reference not set to an instance of an object")

I'm new to Xamarin.Forms.
I got an app that works well on iOS. However, on Android, it crashes after some time, and throws the following error:
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance
of an object.
Debug says it happens on this code:
private void OnElementToggled(object sender, EventArgs e)
{
this.Element.IsToggled = this.Control.Checked;
}
This toggle turns an option on or off inside our app. The toggle works fine on iOS. It also works on Android, but if I navigate around the app and switch the toggle on/off a few times, I get the error. I only get this error on Android, and only after I navigate around. Also, I get it at different times on simulator vs device (Galaxy S5 Neo). The simulator can run longer before I get the error.
I'm dumbfounded. How do I fix this?
I've searched and found What is a NullReferenceException, and how do I fix it?. That solution doesn't seem to apply in my case, because my code works fine on iOS and initially on Android.
Thank you very much for your time and help.
Try/Catch is a basic C# concept, any intro book will cover it
private void OnElementToggled(object sender, EventArgs e)
{
try {
this.Element.IsToggled = this.Control.Checked;
catch (Exception ex) {
// use logging (ie, appcenter.ms) to log this exception
}
}

Getting a lot of crashes from android youtube player api

I am using version 1.2.1 (tried with latest version 1.2.2) of android's youtube player api. It works fine on most of the devices. However now and then, I keep on getting crashes on crashlytics. I am getting the following crashes
Fatal Exception: java.lang.IllegalStateException: android.os.TransactionTooLargeException
at com.google.android.youtube.api.jar.client.RemoteEmbeddedPlayer.x(SourceFile:558)
at bpd.w(SourceFile:576)
at tef.onTransact(SourceFile:390)
at android.os.Binder.transact(Binder.java:395)
at com.google.android.youtube.player.internal.d$a$a.r(Unknown Source)
at com.google.android.youtube.player.internal.s.h(Unknown Source)
at com.google.android.youtube.player.YouTubePlayerView.e(Unknown Source)
at com.google.android.youtube.player.YouTubePlayerSupportFragment.onSaveInstanceState(Unknown Source)
at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:1936)
at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1654)
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1722)
at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:1938)
at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1654)
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1722)
at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:527)
at com.newshunt.news.activities.NewsBaseActivity.onSaveInstanceState(NewsBaseActivity.java:56)
at com.newshunt.news.activities.NewsDetailsActivity.onSaveInstanceState(NewsDetailsActivity.java:613)
at android.app.Activity.performSaveInstanceState(Activity.java:1388)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1286)
at android.app.ActivityThread.callCallActivityOnSaveInstanceState(ActivityThread.java:4588)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3960)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4023)
at android.app.ActivityThread.access$1200(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1498)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Also getting crashes for the following exception.
Fatal Exception: java.lang.IllegalStateException: android.os.DeadObjectException
at com.google.android.apps.youtube.api.jar.a.eo.surfaceDestroyed(SourceFile:236)
at android.view.SurfaceView.updateWindow(SurfaceView.java:589)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:237)
at android.view.View.dispatchDetachedFromWindow(View.java:12854)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2757)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2757)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3844)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3819)
at android.view.ViewGroup.removeView(ViewGroup.java:3751)
at com.google.android.youtube.player.YouTubePlayerView$1.b(Unknown Source)
at com.google.android.youtube.player.internal.r.h(Unknown Source)
at com.google.android.youtube.player.internal.r$e.onServiceDisconnected(Unknown Source)
at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1111)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1125)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5317)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(NativeStart.java)
The crash happens to appear in specific versions of youtube application like 5.2.27. Although there are a lot of issues filed for these crashes, there has been no reply from the youtube developers on how to mitigate this issue.
Some of the fellow developers have suggested the following workarounds
1) Use loadVideo instead of cueVideo. But I cannot use this workaround because loadVideo always autoplays the video which is not a requirement of my application. Also someone mentioned that with loadVideo also, this problem is happening although in some different version.
2) Put check in the code to check the youtube application version and then put the specific code. Now the problem with this approach is that I have to check each and every version of youtube app ever released and check which versions are causing the issue which is not a good workaround.
Now is there any fix which I can apply to avoid this issue or are the youtube developers planning to release some jar which internally takes care of all these issues?
I reduced the bug occurrence by putting youtube calls (like youtubePlayer.loadVideo(), cueVideo(), getCurrentTimeMillis() etc.) in a try catch block and catch the IllegalStateException exception then reinitialize youtube player.
To create a new instance of the YoutubePlayer just call the initialize() method in the catch block.
Example:
if (youtubePlayer != null) {
try {
youtubePlayer.loadVideo(videoId);
} catch (IllegalStateException e) {
initialize(API_KEY, this);
}
}
but the bug still occurred , I worked around it by catching these exceptions and restart activity. This uncaught exceptions and to catch them you need to use UncaughtExceptionHandler
example :
private Thread.UncaughtExceptionHandler defaultUEH;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
// setup handler for uncaught exception
Thread.setDefaultUncaughtExceptionHandler(_unCaughtExceptionHandler);
}
private Thread.UncaughtExceptionHandler _unCaughtExceptionHandler =
new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e(TAG, "uncaughtException: ", ex);
PendingIntent myActivity = PendingIntent.getActivity(getApplicationContext(),
192837, new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager;
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
15000, myActivity );
System.exit(2);
// re-throw critical exception further to the os (important)
defaultUEH.uncaughtException(thread, ex);
}
};
The android YouTube Player API is not stable, there are known bugs in it. The team from YouTube said that they will release a new version of the library.
For now, the best solution I have found is to build my own library.

[Video Call]Cannot recall the Video Chat

I create a CallActivity implement Video Call webrtc. I use quickblox sdk version 2.2.2. The Video Call work fine. But when i ended a Video Call and finish() CallActivity, then i restart CallActivity again, the Video Call not work any more, i can start a new Video Call, but my partner can not receive this Call. I must force stop my app by app manager, Video Call work fine again. Maybe the video call session has problem!
How to recall when restart CallActivity. My destroy() method on CallActivity.
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendVideoCall);
if (QBChatService.isInitialized()) {
try {
if (QBRTCClient.isInitiated()) {
endCall(getCurrentSession().getUserInfo());
//QBRTCClient.getInstance().getSessions().clear();
QBRTCClient.getInstance().removeCallback(this);
QBRTCClient.getInstance().close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
currentSession = null;
}
We recommend you to update your SDK version to the latest one (2.2.6) as it has most video call issues fixed.
You can download it and chtck the framework changelog here: http://quickblox.com/developers/Android#Download_Android_SDK

Java nullpointer exception from Webview in android.webkit.WebViewClassic.loadDataWithBaseURL

Following the suggestions provided in this question I modified my AdMob code to be compliant with the recommendations, that effectively worked reducing the number of exceptions that were appearing. However a new exception is rising.
The code is the following:
#Override
protected void onDestroy() {
if ( adView != null ) {
adView.destroy();
adView = null;
Log.i(ApplicationData.APP_TAG, TAG + ": OnDestroy, destroying the Adview");
}
super.onDestroy();
}
The method adView.destroy() appears to work well as the LogCat message is published. Just after this message I am getting the following exception on WebView:
java.lang.NullPointerException
at android.webkit.WebViewClassic.loadDataWithBaseURL(WebViewClassic.java:2741)
at android.webkit.WebView.loadDataWithBaseURL(WebView.java:919)
at com.google.android.gms.ads.internal.request.n.run(SourceFile:206)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5297)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Unfourtunately I am not able to find a way to reproduce the problem but is happening in production regularly. I have not been able to find any problem, has somebody any hint of what I can do?
One of Google Mobile Ads SDK Team said (March 14),
We looked into this issue when it was first reported, and a fix has been released within Google Play services. You should see fewer and fewer instances as your users' devices update to the new version.
Refer to https://groups.google.com/forum/#!topic/google-admob-ads-sdk/oYpQI_L14Tg
This occurs when the WebView is destroyed before loadDataWithBaseUrl is called( probably by other thread). In AdMob code, i saw that they handle this now as follows
public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) {
synchronized(this) {
if(!this.isDestroyed()) {
super.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
} else {
Log.d("The webview is destroyed. Ignoring action.");
}
}
}
So it should not occur now.

Does setting Thread.setDefaultUncaughtExceptionHandler prevent Google's error-reporting from work?

In my Android application I utilize setDefaultUncaughtExceptionHandler to store information about unhandled exceptions locally on a user device. After some feedback I suspect that this code prevents the built-in Google's error-reporting feature from work, because I do not see error reports in the developer console, while exceptions are reported by users. Their devices are well past 2.2, where the error-reporting was introduced. Could it be that specific device with, say, 4.0.3 does not support this feature? If yes, how can I detect this programmatically?
I can't find information regarding this in Android documentation. I'd like both standard error-reporting and my custom handling work together. In my custom exception handler I call Thread.getDefaultUncaughtExceptionHandler() to get default handler, and in my implementation of uncaughtException I propagate exception to this default handler as well.
I first tried calling System.exit(1); as mentioned in this SO answer, but that didn't work.
Finally solved it by calling the uncaughtException(Thread thread, Throwable ex) again on Androids default UncaughtExceptionHandler (found it by checking the ACRA source code.
Example Activity
public class MainActivity extends Activity implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler _androidUncaughtExceptionHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_androidUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
// Rest onCreate
setContentView(R.layout.main_activity);
}
//#Override
public void uncaughtException(Thread thread, Throwable ex) {
try {
// Do your stuff with the exception
} catch (Exception e) {
/* Ignore */
} finally {
// Let Android show the default error dialog
_androidUncaughtExceptionHandler.uncaughtException(thread, ex);
}
}
}
Yes, this will stop the inbuilt error report. The user is given a dialog when your app crashes, with an option to report the error via Google Play. However, if you use setDefaultUncaughtExceptionHandler() then the exception is handled within your app, and no option is given to report it.
I recommend that you integrate ACRA into your project, as it allows you to easily receive error reports upon crashes.

Categories

Resources