I'm working on an application with Xamarin (in Visual studio 2015) for android.
When I run my application in debug mode, sometime the application stop with message "MyApplication has stopped".
I've added this code in MainActivity :
// Catch Exception
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;
I added breakpoints add log in both functions, but I see no traces in log and the breakpoints are not reached.
How can I debug this kind of problem ?
You need to debug your application through a persistent logger i.e. adb logcat. Sadly registering an unhandled exception handler does not guarantee it will be a "catch-all" as it might never reach that point. So you will need a combination of both adb logcat and Console.WriteLine for these types of issues. Please take the following note into account when you want to see what's going on within this handler, but also make use of adb logcat to see the reason of the crash in the first place.
/// <summary>
/// When app-wide unhandled exceptions are hit, this will handle them. Be aware however, that typically
/// android will be destroying the process, so there's not a lot you can do on the android side of things,
/// but your xamarin code should still be able to work. so if you have a custom err logging manager or
/// something, you can call that here. You _won't_ be able to call Android.Util.Log, because Dalvik
/// will destroy the java side of the process.
/// </summary>
protected void HandleUnhandledException (object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception) args.ExceptionObject;
// log won't be available, because dalvik is destroying the process
//Log.Debug (logTag, "MyHandler caught : " + e.Message);
// instead, your err handling code shoudl be run:
Console.WriteLine ("========= MyHandler caught : " + e.Message);
}
https://github.com/xamarin/monodroid-samples/blob/fb9d4ed266bdf68bb1f9fa9933130b285712ec82/AdvancedAppLifecycleDemos/HandlingCrashes/App.cs
Try it: Disabled "Use Shared Runtime" in Android build options. If it not helped try - disable "Use fast deplayment".
Related
I'm trying to implement an uncaught exception handler in an Android only app built with Xamarin for logging purposes.
AppDomain.CurrentDomain.UnhandledException += (o, e) => exLogger.UncaughtException((Exception)e.ExceptionObject);
TaskScheduler.UnobservedTaskException += (o, e) => exLogger.UncaughtException(e.Exception);
and
public void UncaughtException(Exception ex)
{
try
{
Log.Error(TAG, "Exception caught: {0}", ex.Message ?? "Unknown Exception");
var di = Directory.CreateDirectory(Path.Combine(context.FilesDir.AbsolutePath, TAG));
//Rest of Handler - saves error to file system, attempts to upload to a server
...
}
catch (Exception)
{
Log.Error(TAG, "Exception handler failed");
}
}
The handler in question works with zero problems when I implement it in a very simple "Hello World" application, where I trigger an exception on button-press:
throw new Exception("this is a test exception");
(or similar).
However, When I do the same thing in the application I am actually developing, the app crashes inside the handler, printing no further information as to why this happens.
When I step through my code, the debugger hits a breakpoint at the entry to the handler - e.g. within the try block, but before the Log.Error line. However, attempting to step further than this point results in immediate app crash, without either the Log.Debug line in the try OR catch block being executed - nothing is printed to the ADB Logger. Additionally, the error printed to the ADB Log by W/system.err is only the error I intentionally caused (to trigger the handler) - no information on the crash WITHIN the handler is provided.
Does anyone have any idea what could be causing this crash, or even advice on how to get more information from the ADB logs on what the crash within the handler was caused by? My only train of thought is that, because my app is a WebView application, potentially the WebView itself is consuming the Exception in some manner? Any help is greatly appreciated!
I have Android native C++ code. However, sometimes when I send app to background and back, it crash with SIGSEGV. I want to debug it using my own signal handling and print stack trace, however, when this error occurs, my signal handling is not triggered at all.
To JNI_OnLoad method, I have added:
struct sigaction sighandler;
memset (&sighandler, '\0', sizeof(sighandler));
sighandler.sa_sigaction = &android_sigaction;
sighandler.sa_flags = SA_SIGINFO;
int watched_signals[] = { SIGABRT, SIGILL, SIGSEGV, SIGINT, SIGKILL };
for(int signal : watched_signals)
{
sigaction(signal, &sighandler, &old_sa[signal]);
}
And I have:
static struct sigaction old_sa[NSIG];
static void android_sigaction(int signal, siginfo_t *siginfo, void *context)
{
MY_LOG("Sending PID: %ld, UID: %ld\n", (long)siginfo->si_pid, (long)siginfo->si_uid);
old_sa[signal].sa_handler(signal);
}
However, android_sigaction is never trigerred for the error, when app goes from background. I have tried to create bug in code (writing outside array bounds), trigger it with button push and the callback is correctly called.
What is going on?
Assuming that you're using Android 5.0+ device, your problem may be caused by ART. It exposes own signal() and sigaction() so it has a chance to steal signal and pass it somewhere else.
For debugging purposes you could try direct syscall:
for(int signal : watched_signals)
{
syscall(_NR_sigaction, signal, &sighandler, &old_sa[signal]);
}
So now your handler goes directly to kernel and ART shouldn't change it.
Of course it is OK only for debugging. If you want to go with this for a prod - you need to develop some logic that will respect previous handler.
P.S. also checking returned value and errno is a good idea as well.
I want to check exceptions and errors in my game in built up, but there is no debug console in game so I want to make one. Is there any way to get those errors from original console and write it on screen?
You can add a callback function to Application.logMessageReceived to receive the Debug.* messages. For example:
void Awake(){
Application.logMessageReceived += HandleLog;
}
private void HandleLog(string logString, string stackTrace, LogType type) {
// add them to some UI component for visualizing
}
Is there a way to view the log on a tablet running 4.4? I've downloaded several apps like aLogCat and none of them show what my app writes out with S.o.p or Log.d. I have an intermittent bug that gives the Unfortunately appname has stopped message.Is there any way to view the log after this event without having to connect to a PC and use the adb program?
What other ways are there to get debug output? Would trapping the System.out and System.err classes get the stack trace?
Thanks,
Norm
You're focussing on tring to read out logcat, but there are better solutions for reading crash logs. My personal preference is Crashlytics, which automatically logs fatal exceptions and provides mechanisms for logging other messages.
The way all these crash reporters work, is by defining a UncaughtExceptionHandler:
Thread.setDefaultUncaughtExceptionHandler(
new MyUncaughtExceptionHandler(this));
If you prefer to use your own solution, you may want to look into using this. See this related question for more details.
Is there a way to view the log on a tablet running 4.4?
No, sorry. An app can only see its own log messages, not those from other apps. Hence, a third-party log viewer cannot see your app's messages.
Is there any way to view the log after this event without having to connect to a PC and use the adb program?
Use any standard crash management library, like ACRA, or services like Crashlytics, BugSense, etc.
The AIDE Application (Android Integrated Development Environment) allows one to develop android Apps directly on android device.
One particular feature is to read the logcat.
You can get it here https://play.google.com/store/apps/details?id=com.aide.ui
Here's the code I've put in the program. It seems to work:
// Define inner class to handle exceptions
class MyExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e){
java.util.Date dt = new java.util.Date();
String fn = LogFilePathPfx + "exception_" + sdf.format(dt) + ".txt";
try{
PrintStream ps = new PrintStream( fn );
e.printStackTrace(ps);
ps.close();
System.out.println("wrote trace to " + fn);
e.printStackTrace(); // capture here also???
SaveStdOutput.stop(); // close here vs calling flush() in class
}catch(Exception x){
x.printStackTrace();
}
lastUEH.uncaughtException(t, e); // call last one Gives: "Unfortunately ... stopped" message
return; //???? what to do here
}
}
lastUEH = Thread.getDefaultUncaughtExceptionHandler(); // save previous one
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
In Eclipse, I notice that Logcat only retains a few dozen entries and deletes the older ones as soon as a new one come in. Is there a way to prevent this? I need my app to run for a long time and not lose any entries because my app eventually hangs or crashes after a few days, and I want to see if something in Logcat has been recorded.
I am not sure if this is the most elegant solution to the problem, but you can always increase the LogCat message size in Eclipse.
Window -> Preferences -> Android -> LogCat -> Maximum number of LogCat messages to buffer
The default is 5000, I believe. You can set it to be very high if you are planning to run your application for a long time.
i think you need to increase this show image
Here's a better solution:
Set the Default Uncaught Exception Handler. Whenever the app crashes, this will be called with the exception. Simply write a log entry saying it crashed then dump the logcat to a file. Finally, make sure you re-throw the exception to make sure the app crashes and funky things don't happen. Note: This is per thread, keep that in mind.
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e("TAG", "---My app crashed just now---", ex);
//TODO: Dump logcat to file
throw new RuntimeException(ex);
}
});
if you want to keep your app running for days.. its better you capture your logs from adb shell.
the common shell command would be :
logcat -c \\ to clear previous logs
logcat -v time>yourLogs.txt & \\ to capture fresh logs