Find why Xamarin app Crashes randomly - android

I am making a app with Xamarin.Forms, the app in the iOS doesn't crash but in Android, Application is crashing randomly, even if I only switch the tabs.
What is the best way to find what is making the app to stop working?
Thanks

What is the best way to find what is making the app to stop working?
well to add exception handling
try {
// ...
} catch(Exception e) {
// ...
}
or like the below example
public static void main(String[] args) throws FileNotFoundException, IOException {
try{
ExceptionHandler(1);
ExceptionHandler(2);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
System.out.println(" error to be checked");
}
testException(0);
}
public static void ExceptionHandler(int i) throws FileNotFoundException, IOException{
if(i =1 ){
FileNotFoundException myException = new FileNotFoundException("error for code 1 "+i);
throw myException;
}else if(i =2){
throw new IOException("error on 2 ");
}
}

You can also look into a crash reporting service like Hockey App (https://hockeyapp.net/ -- the free level is enough for getting crash reports). You'll get crashes reported there, including crashes in code that you can't catch.
Crash reports aren't quite as handy has being able to break in the debugger, but it's often enough to point you in the right direction.
Instructions on integrating Hockey App to a Xamarin.Forms app: https://support.hockeyapp.net/kb/client-integration-cross-platform/how-to-integrate-hockeyapp-with-xamarin

Related

Catching all possible exceptions while using android videoview

I am using android videoview to display a loop of videos, as per our requirement the video loop should continue even if one of the videos gives an error.
To catch any exception, I have included the relevant code in a try-catch block as shown in the below code. However, while testing all scenarios, I gave the wrong path to the videoview.setVideopath() but the exception is not caught. I can see in the android studio console that it reports the data source not found error, but catch block does not catch the exception. I also tried implementing onerrorlistener, it is also not called when this happens.
Could you please help me, I am attaching the relevant code and exception log, many thanks for your help.
private void DisplayVideo_VideoView(){
try {
adplayer = (ResizableVideoView) findViewById(R.id.adplayer);
String MediaStorePath = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/Videos";
// String videoPath = MediaStorePath + "/" + Root2Util.Videopathlist.get(CurrentMediaIndex).getFileName();
String videoPath = MediaStorePath + "/1" + Root2Util.Videopathlist.get(CurrentMediaIndex).getFileName();
//adplayer.setVideoPath(videopath[CurrentMediaIndex]);
adplayer.setVideoPath(videoPath);
adplayer.changeVideoSize(Root2Util.SCREEN_WIDTH, Root2Util.SCREEN_HEIGHT);
adplayer.setVisibility(View.VISIBLE);
adplayer.start();
adplayer.setKeepScreenOn(true);
adplayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
CurrentMediaIndex++;
//mp.reset();
if (CurrentMediaIndex == Root2Util.Videopathlist.size()) {
CurrentMediaIndex = 0;
}
playMedia();
// ErrorHandlerAsyncTask ErrorTask=new ErrorHandlerAsyncTask();
// ErrorTask.execute((Object)getApplicationContext(),(Object)String.valueOf(what));
return false;
}
});
} catch(Exception e) {
ErrorHandlerAsyncTask ErrorTask=new ErrorHandlerAsyncTask();
ErrorTask.execute((Object)getApplicationContext(),(Object)e.getMessage());
}
Exception log from the console :
W/VideoView: Unable to open content: /storage/emulated/0/Download/Videos/1f0a9106d-d7d5-470c-
b287-3e3cad7d13fb.mp4
java.io.IOException: setDataSource failed.
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1091)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1065)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1019)
at android.widget.VideoView.openVideo(VideoView.java:352)
at android.widget.VideoView.access$2100(VideoView.java:72)
at android.widget.VideoView$7.surfaceCreated(VideoView.java:628)
at android.view.SurfaceView.updateWindow(SurfaceView.java:580)
at android.view.SurfaceView.setVisibility(SurfaceView.java:256)
at root2tech.cloudplayer.HomepageActivity.DisplayVideo_VideoView(HomepageActivity.java:728)
at root2tech.cloudplayer.HomepageActivity.playMedia(HomepageActivity.java:958)
at root2tech.cloudplayer.HomepageActivity.access$200(HomepageActivity.java:78)
at root2tech.cloudplayer.HomepageActivity$5.run(HomepageActivity.java:571)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:935)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:730)
So, I just faced a similar issue, I needed to use a VideoView to play the video from a URL without any knowledge of if the URL was a valid video or not. I understand why you're asking about catching every exception as well. My VideoView would print out an IOException and another which I can't quite remember at the moment of this answer. To fix this, I used a very similar code to yours but in a different order. The setOnErrorListener is what solved my issue for me but I placed my OnErrorListener directly after my VideoPlayer initialization and before the setVideoPath.
This works because the setVideoPath is where the errors are handled, unfortunately, VideoView will print these errors to the log but it will not throw anything to crash the app (which I don't agree with or like one bit). Because of this, your setOnErrorListener should at least go before you set the path or there will be nothing for it to catch as the error would have been thrown already (The errors aren't thrown on start oddly enough.
To apply my solution to your code, I would change it to this:
private void DisplayVideo_VideoView(){
//initialize adplayer
adplayer = (ResizableVideoView) findViewById(R.id.adplayer);
//begin listening for errors
adplayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
CurrentMediaIndex++;
if (CurrentMediaIndex == Root2Util.Videopathlist.size()) {
CurrentMediaIndex = 0;
}
playMedia();
return false;
}
});
//build variables for readability
String MediaStorePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/Videos";
String videoPath = MediaStorePath + "/1" + Root2Util.Videopathlist.get(CurrentMediaIndex).getFileName();
//set path - If there is an issue with videoPath, the error should be thrown here
adplayer.setVideoPath(videoPath);
//final adplayer customizations
adplayer.changeVideoSize(Root2Util.SCREEN_WIDTH, Root2Util.SCREEN_HEIGHT);
adplayer.setVisibility(View.VISIBLE);
//begin the adplayer
adplayer.start();
adplayer.setKeepScreenOn(true);
}
It is not a good style of code to catch a raw Exception, it is too broad to handle different error cases. However, for most of the IO operations IOException is the base exception, it is recommended to catch this.
As per java docs, we also need to consider IO operations can throw IOError. Error is not under the hierarchy of Exception, but both IOException and Error share Throwable as the base class. With this consideration, you can write your try-catch block as:
try {
// Your code
} catch (Throwable throwable) {
if (throwable instanceof IOException) {
// handle IOException here
} else if (throwable instanceof Error) {
if (t instanceof IOError) {
// handle IOError here
}
} else {
//This else will be reached only if you have any custom exceptions
}
}
For more readability of the code, you can use multiple catch blocks:
try {
// Your code
} catch (IOException ioException) {
// handle IOException here
} catch (IOError ioError) {
// handle IOError here
}
Also, you can add throws clause to your method if you want to handle these exceptions later:
public void displayVideo() throws Throwable {
// Your code here
}
Note: This is not the perfect solution to capture all exceptions for your scenario. But, since your code also includes IO operations on the file, hence have used the above examples to explain how you can possibly implement your exception handling.

How to catch Amazon AWS errors Android

I am constantly getting error reports (from users) such as:
Caused by: Status Code: 400, AWS Service: AmazonSimpleDB, AWS Request ID: c5cb109d-bbff-fcea-bc0d-0cb60ff8f6af, AWS Error Code: RequestExpired, AWS Error Message: Request has expired. Timestamp date is 2012-06-06T13:19:59.415Z. Current date is 2012-06-06T14:20:03Z
Apparently this is because the user has the wrong timezone or something set? Regardless, I would like to catch this particular error and post a message to the user asking them to check their timezone settings however I can't find a way to do it. If I catch AmazonServiceException, the error shows up as null.
How can I catch errors based on Status Code or even Error Code? The current code that I tried looks like this:
try {
dostuff()
} catch (IOException e) {
updateAWS("DownloadErrors");
return "filenotfound";
} catch (AmazonServiceException e) {
return "downloadfail";
}
However AmazonServiceException e is always null so I can't pull any information from it.
other code:
private void doStuff() throws IOException, AmazonServiceException{
//code here
}
Apparently this is what I needed. SDb tracks "RequestExpired" and S3 uses "RequestTimeTooSkewed"
Also, this appears to be occurring because the system time is >15 minutes different than the AWS server. I put a note to the user to check their time and use "Automatic" date/time if possible. Tested it myself and reproduced the error as well as the solution.
try {
result = doOperations();
} catch (AmazonServiceException e) {
if (e.getErrorCode().equals("RequestExpired") || e.getErrorCode().equals("RequestTimeTooSkewed")) {
result = "timestamp";
}
}
return result;
}

Need some explaining

So this is the weirdest thing ever to happen to me during programing. Yes I'm no pro at programing, but I'm learning as I go. I've got an app talking to a server, a socket in the main thread, reading is done in a separate class and thread and writing in a separate class with asynctask.
The problem is LocationManager. I could talk to server and write/read commands just fine, I implemented the LocationManager and its listener.
I then proceeded to implement a method to update my textview with the new coordinates on locatinChanged. So far so good. Thing is when I use the Emulator control in eclipse and send coordinates the app crashed with a stringOutOfBoundsException (I've programed for 3 years now never seen this). I looked at the code stepped through it and so on. Read the stacktrace, logcat, console and everywhere I could think of but it got me nowhere. Until I finally went to the readerthread which looks like this:
public class ReaderThread extends Thread {
public void run() {
new Thread(new Runnable(){
public void run(){
try {
//Establish a bufferedreader to read from the socket/server.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()), 8 * 1024);
}
catch(Exception e) { e.printStackTrace(); }
//As long as connect is true.
while (connected) {
String line;
try {
//Try to read a line from the reader.
line = in.readLine();
System.out.println(in.readLine());
if (in == null) {
//No one has sent a message yet.
System.out.println("No data recieved");
}
else {
int i = 0;
//As long as someone is sending messages.
while((line = in.readLine()) != null ){
//Make a new Message.
Message msg;
msg = new Message();
//Set the object to the input line.
msg.obj = line;
//Set an id so it can be identified in the main class and used in a switch.
msg.what = i;
System.out.println("i is: "+i);
//Send the message to the handler.
Main.this.h.sendMessage(msg);
}
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}).start();
}
The variable i is in an if statement depending on what the server sent but I cut that out as it has nothing to do with this problem.
The problem is the freaking catch. When the catch is IOException, the app crashes. Out of dumb luck I changed this to Exception and printed e.message to catch the error and see what caused it. Thing is this change fixed it. How can switching IOException to just plain Exception fix a problem like this?
Its like with IOException the program says: "hey your not gonna catch the error but there is no error" but with Exception it says "Well now you could catch it so I'll proceed".
My app is working but I just can't grasp this, why and how does this happen?
You're essentially telling the application to catch the base Exception class. This means that any type of error will be caught, since all exception classes descend from that base type. Since StringOutOfBoundsException does not descend from IOException it was not being caught before and the error was not being caught. Instead of catching all exceptions, you might try the following:
try {
// Your code here...
} catch (IOException e) {
Log.e(TAG, "Caught an IOException!", e);
} catch (StringOutOfBoundsException e) {
Log.e(TAG, "Caught a string out of bounds Exception!", e);
}
I'm unable to determine what is actually throwing the StringOutOfBoundsException to begin with. It may be in the if statement that you cut out of your example.
while (connected) {
String line;
try {
//Try to read a line from the reader.
line = in.readLine();
System.out.println(in.readLine());
if (in == null) {
//No one has sent a message yet.
System.out.println("No data recieved");
}
The test for in == null is in a funny location. You should receive a NullPointerException if that test were to ever return true by nature of calling methods on it a few lines earlier. Obviously something is a little funny with this code.
You fail to save the return value from in.readLine() the second time you call it. I hope it did not contain anything useful. (Though, since you print the line, you obviously wanted to know what data it contained.)
Whatever that line was (from the first call to in.readLine()), it gets thrown away; there's nothing else in the loop that uses it before it is over-written on this line:
while((line = in.readLine()) != null ){
At this point, the two lines that you read are gone forever.
I'm not entirely sure what should be done to fix this; if it were me, I'd be sorely tempted to start over with a sheet of paper and sketch out what the method should be doing without looking at the existing code, then compare the sketch against the code to see which cases each one has overlooked.

Android Error handling - Sorry - The application has stopped unexpectedly

I've got it wrapped in a try catch, but the exception still trips that ugly screen.
URL u = null;
try {
u = new URL(txturl.getText().toString());
}
catch (MalformedURLException e) {
ReportError(e,"Unable to connect to "+u);
}
calls this:
private void ReportError(Exception e, String message){
Display(message+" - "+ e.getMessage().toString());
System.out.println(">>>>>>>>>>>>>>>>>>>>> "+message+" - "+e.getMessage().toString());printStackTrace();
}
Any way around this. It happens on the Android 2.2 emulator with Eclipse and on my Sprint Hero.
Do I have to validate the form?
Thanks.
I just needed to return after these exceptions. duh. sorry.

How do I obtain crash-data from my Android application?

How can I get crash data (stack traces at least) from my Android application? At least when working on my own device being retrieved by cable, but ideally from any instance of my application running on the wild so that I can improve it and make it more solid.
You might try the ACRA (Application Crash Report for Android) library:
ACRA is a library enabling Android Application to automatically post their crash reports to a GoogleDoc form. It is targetted to android applications developers to help them get data from their applications when they crash or behave erroneously.
It's easy to install in your app, highly configurable and don't require you to host a server script anywhere... reports are sent to a Google Doc spreadsheet !
For sample applications and debugging purposes, I use a simple solution that allows me to write the stacktrace to the sd card of the device and/or upload it to a server. This solution has been inspired by Project android-remote-stacktrace (specifically, the save-to-device and upload-to-server parts) and I think it solves the problem mentioned by Soonil. It's not optimal, but it works and you can improve it if you want to use it in a production application. If you decide to upload the stacktraces to the server, you can use a php script (index.php) to view them. If you're interested, you can find all the sources below - one java class for your application and two optional php scrips for the server hosting the uploaded stacktraces.
In a Context (e.g. the main Activity), call
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(
"/sdcard/<desired_local_path>", "http://<desired_url>/upload.php"));
}
CustomExceptionHandler
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
private String localPath;
private String url;
/*
* if any of the parameters is null, the respective functionality
* will not be used
*/
public CustomExceptionHandler(String localPath, String url) {
this.localPath = localPath;
this.url = url;
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e) {
String timestamp = TimestampFormatter.getInstance().getTimestamp();
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
String filename = timestamp + ".stacktrace";
if (localPath != null) {
writeToFile(stacktrace, filename);
}
if (url != null) {
sendToServer(stacktrace, filename);
}
defaultUEH.uncaughtException(t, e);
}
private void writeToFile(String stacktrace, String filename) {
try {
BufferedWriter bos = new BufferedWriter(new FileWriter(
localPath + "/" + filename));
bos.write(stacktrace);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendToServer(String stacktrace, String filename) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("filename", filename));
nvps.add(new BasicNameValuePair("stacktrace", stacktrace));
try {
httpPost.setEntity(
new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
}
}
upload.php
<?php
$filename = isset($_POST['filename']) ? $_POST['filename'] : "";
$message = isset($_POST['stacktrace']) ? $_POST['stacktrace'] : "";
if (!ereg('^[-a-zA-Z0-9_. ]+$', $filename) || $message == ""){
die("This script is used to log debug data. Please send the "
. "logging message and a filename as POST variables.");
}
file_put_contents($filename, $message . "\n", FILE_APPEND);
?>
index.php
<?php
$myDirectory = opendir(".");
while($entryName = readdir($myDirectory)) {
$dirArray[] = $entryName;
}
closedir($myDirectory);
$indexCount = count($dirArray);
sort($dirArray);
print("<TABLE border=1 cellpadding=5 cellspacing=0 \n");
print("<TR><TH>Filename</TH><TH>Filetype</th><th>Filesize</TH></TR>\n");
for($index=0; $index < $indexCount; $index++) {
if ((substr("$dirArray[$index]", 0, 1) != ".")
&& (strrpos("$dirArray[$index]", ".stacktrace") != false)){
print("<TR><TD>");
print("$dirArray[$index]");
print("</TD><TD>");
print(filetype($dirArray[$index]));
print("</TD><TD>");
print(filesize($dirArray[$index]));
print("</TD></TR>\n");
}
}
print("</TABLE>\n");
?>
You can also try [BugSense] Reason: Spam Redirect to another url. BugSense collects and analyzed all crash reports and gives you meaningful and visual reports. It's free and it's only 1 line of code in order to integrate.
Disclaimer: I am a co-founder
In Android 2.2 it's now possible to automatically get Crash Reports from Android Market Applications:
New bug reporting feature for Android
Market apps enables developers to
receive crash and freeze reports from
their users. The reports will be
available when they log into their
publisher account.
http://developer.android.com/sdk/android-2.2-highlights.html
It is possible to handle these exceptions with Thread.setDefaultUncaughtExceptionHandler(), however this appears to mess with Android's method of handling exceptions. I attempted to use a handler of this nature:
private class ExceptionHandler implements Thread.UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread thread, Throwable ex){
Log.e(Constants.TAG, "uncaught_exception_handler: uncaught exception in thread " + thread.getName(), ex);
//hack to rethrow unchecked exceptions
if(ex instanceof RuntimeException)
throw (RuntimeException)ex;
if(ex instanceof Error)
throw (Error)ex;
//this should really never happen
Log.e(Constants.TAG, "uncaught_exception handler: unable to rethrow checked exception");
}
}
However, even with rethrowing the exceptions, I was unable to get the desired behavior, ie logging the exception while still allowing Android to shutdown the component it had happened it, so I gave up on it after a while.
I see that the question is too old, and hope my answer is helpful for others having the same issue...
Give Crashlytics a try. It will give indepth insight into all the crashes on all the devices having your application and send a notification to you through email..And the best part is its completely free to use..
Ok, well I looked at the provided samples from rrainn and Soonil, and I found a solution
that does not mess up error handling.
I modified the CustomExceptionHandler so it stores the original UncaughtExceptionHandler from the Thread we associate the new one. At the end of the new "uncaughtException"-
Method I just call the old function using the stored UncaughtExceptionHandler.
In the DefaultExceptionHandler class you need sth. like this:
public class DefaultExceptionHandler implements UncaughtExceptionHandler{
private UncaughtExceptionHandler mDefaultExceptionHandler;
//constructor
public DefaultExceptionHandler(UncaughtExceptionHandler pDefaultExceptionHandler)
{
mDefaultExceptionHandler= pDefaultExceptionHandler;
}
public void uncaughtException(Thread t, Throwable e) {
//do some action like writing to file or upload somewhere
//call original handler
mStandardEH.uncaughtException(t, e);
// cleanup, don't know if really required
t.getThreadGroup().destroy();
}
}
With that modification on the code at http://code.google.com/p/android-remote-stacktrace
you have a good working base for logging in the field to your webserver or to
sd-card.
Google Play Developers Console actually gives you the Stack traces from those apps that have crashed and had sent the reports, it has also a very good charts to help you see the information, see example below:
I've been using Crittercism for my Android and iOS apps -- heard about them on techcrunch. Pretty happy with them so far!
I made my own version here :
http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html
It's basically the same thing, but I'm using a mail rather than a http connexion to send the report, and, more important, I added some informations like application version, OS version, Phone model, or avalaible memory to my report...
use this to catch the exception details:
String stackTrace = Log.getStackTraceString(exception);
store this in database and maintain the log.
You can also use a whole (simple) service for it rather than only library. Our company just released a service just for that: http://apphance.com.
It has a simple .jar library (for Android) that you add and integrate in 5 minutes and then the library gathers not only crash information but also logs from running application, as well as it lets your testers report problems straight from device - including the whole context (device rotation, whether it is connected to a wifi or not and more). You can look at the logs using a very nice and useful web panel, where you can track sessions with your application, crashes, logs, statistics and more.
The service is in closed beta test phase now, but you can request access and we give it to you very quickly.
Disclaimer: I am CTO of Polidea, and co-creator of the service.
Now a days Firebase Crash reports are very popular and easier to use.
Please refer following link for more information:
Firebase Crash Reporting
Hope it will help you.
Thanks resources present in Stackoverflow in helping me to find this answer.
You can find your remotely Android crash reports directly into your email. remmember you have to put your email inside CustomExceptionHandler class.
public static String sendErrorLogsTo = "tushar.pandey#virtualxcellence.com" ;
Steps required :
1st) in onCreate of your activity use this section of your code.
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this));
}
2nd) use this overridden version of CustomExceptionHandler class of ( rrainn ), according to my phpscript.
package com.vxmobilecomm.activity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.util.Log;
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
public static String sendErrorLogsTo = "tushar.pandey#virtualxcellence.com" ;
Activity activity;
public CustomExceptionHandler(Activity activity) {
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
this.activity = activity;
}
public void uncaughtException(Thread t, Throwable e) {
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
String filename = "error" + System.nanoTime() + ".stacktrace";
Log.e("Hi", "url != null");
sendToServer(stacktrace, filename);
StackTraceElement[] arr = e.getStackTrace();
String report = e.toString() + "\n\n";
report += "--------- Stack trace ---------\n\n";
for (int i = 0; i < arr.length; i++) {
report += " " + arr[i].toString() + "\n";
}
report += "-------------------------------\n\n";
report += "--------- Cause ---------\n\n";
Throwable cause = e.getCause();
if (cause != null) {
report += cause.toString() + "\n\n";
arr = cause.getStackTrace();
for (int i = 0; i < arr.length; i++) {
report += " " + arr[i].toString() + "\n";
}
}
report += "-------------------------------\n\n";
defaultUEH.uncaughtException(t, e);
}
private void sendToServer(String stacktrace, String filename) {
AsyncTaskClass async = new AsyncTaskClass(stacktrace, filename,
getAppLable(activity));
async.execute("");
}
public String getAppLable(Context pContext) {
PackageManager lPackageManager = pContext.getPackageManager();
ApplicationInfo lApplicationInfo = null;
try {
lApplicationInfo = lPackageManager.getApplicationInfo(
pContext.getApplicationInfo().packageName, 0);
} catch (final NameNotFoundException e) {
}
return (String) (lApplicationInfo != null ? lPackageManager
.getApplicationLabel(lApplicationInfo) : "Unknown");
}
public class AsyncTaskClass extends AsyncTask<String, String, InputStream> {
InputStream is = null;
String stacktrace;
final String filename;
String applicationName;
AsyncTaskClass(final String stacktrace, final String filename,
String applicationName) {
this.applicationName = applicationName;
this.stacktrace = stacktrace;
this.filename = filename;
}
#Override
protected InputStream doInBackground(String... params)
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(
"http://suo-yang.com/books/sendErrorLog/sendErrorLogs.php?");
Log.i("Error", stacktrace);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
6);
nameValuePairs.add(new BasicNameValuePair("data", stacktrace));
nameValuePairs.add(new BasicNameValuePair("to",sendErrorLogsTo));
nameValuePairs.add(new BasicNameValuePair("subject",applicationName));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity1 = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(
entity1);
is = bufHttpEntity.getContent();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
#Override
protected void onPostExecute(InputStream result) {
super.onPostExecute(result);
Log.e("Stream Data", getStringFromInputStream(is));
}
}
// convert InputStream to String
private static String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
Google Firebase is Google's latest(2016) way to provide you with crash/error data on your phone.
Include it in your build.gradle file :
compile 'com.google.firebase:firebase-crash:9.0.0'
Fatal crashes are logged automatically without requiring user input and you can also log non-fatal crashes or other events like so :
try
{
}
catch(Exception ex)
{
FirebaseCrash.report(new Exception(ex.toString()));
}
There is this android library called Sherlock. It gives you the full report of crash along with device and application information.
Whenever a crash occurs, it displays a notification in the notification bar and on clicking of the notification, it opens the crash details. You can also share crash details with others via email or other sharing options.
Installation
android {
dataBinding {
enabled = true
}
}
compile('com.github.ajitsing:sherlock:1.0.0#aar') {
transitive = true
}
Demo
While many of the answers on this page are useful, it is easy for them to become out of date. The AppBrain website aggregates statistics which allow you to find the most popular crash reporting solution that is current:
Android crash reporting libraries
You can see that at the time of posting this picture, Crashlytics is used in 5.24% of apps and 12.38% of installs.
This is very brute, but it is possible to run logcat anywhere, so a quick and dirty hack is to add to any catch block getRuntime().exec("logcat >> /sdcard/logcat.log");
There is a tool called fabric, this is a crash analytic tool, which will allow you to get crash reports , when application deployed live and during development.
Adding this tool to your application was simple as well..
When your application crash that report of the crash can be viewed from your fabric.io dashboard . thw report was catched automatically.it won't ask user for permission. Whether he/she want to send the bug/crash report.
And this is completely free...
https://get.fabric.io/
We use our home-grown system inside the company and it serves us very well. It's an android library that send crash reports to server and server that receives reports and makes some analytics. Server groups exceptions by exception name, stacktrace, message. It helps to identify most critical issues that need to be fixed.
Our service is in public beta now so everyone can try it. You can create account at http://watchcat.co or you can just take a look how it works using demo access http://watchcat.co/reports/index.php?demo.
If you want answers immediately you can use logcat
$adb shell logcat -f /sdcard/logoutput.txt *:E
If there's too much junk in your log right now, try clearing it first.
$adb shell logcat -c
Then try running your app then logcat again.
I found one more great web application to track the error reports.
https://mint.splunk.com/
Small number of steps to configure.
Login or sign up and configure using the above link. Once you done creating a application they will provide a line to configure like below.
Mint.initAndStartSession(YourActivity.this, "api_key");
Add the following in the application's build.gradl.
android {
...
repositories {
maven { url "https://mint.splunk.com/gradle/"}
}
...
}
dependencies {
...
compile "com.splunk.mint:mint:4.4.0"
...
}
Add the code which we copied above and add it to every activity.
Mint.initAndStartSession(YourActivity.this, "api_key");
That's it. You login and go to you application dashboard, you will get all the error reports.
Hope it helps someone.
For an alternate crash reporting/exception tracking service check out Raygun.io - it's got a bunch of nice logic for handling Android crashes, including decent user experience when plugging it in to your app (two lines of code in your main Activity and a few lines of XML pasted into AndroidManifest).
When your app crashes, it'll automatically grab the stack trace, environment data for hard/software, user tracking info, any custom data you specify etc. It posts it to the API asynchronously so no blocking of the UI thread, and caches it to disk if there's no network available.
Disclaimer: I built the Android provider :)
Just Started to use ACRA https://github.com/ACRA/acra using Google Forms as backend and it's very easy to setup & use, it's the default.
BUT Sending reports to Google Forms are going to be deprecated (then removed):
https://plus.google.com/118444843928759726538/posts/GTTgsrEQdN6
https://github.com/ACRA/acra/wiki/Notice-on-Google-Form-Spreadsheet-usage
Anyway it's possible to define your own sender
https://github.com/ACRA/acra/wiki/AdvancedUsage#wiki-Implementing_your_own_sender
you can give a try to email sender for example.
With minimum effort it's possible to send reports to bugsense:
http://www.bugsense.com/docs/android#acra
NB The bugsense free account is limited to 500 report/month
Late to the party, I support and believe ACRA is the best option among all. Its easy to setup and configure. I have created a detailed guide with inputs from all over to fetch the crash report using ACRA and mail the same to my email address using MandrillAp.
Link to post: https://androidician.wordpress.com/2015/03/29/sending-crash-reports-with-acra-over-email-using-mandrill/
Link to sample project on github: https://github.com/ayushhgoyal/AcraSample
I'm one of the founders of Bugsnag which we designed for exactly this purpose. Bugsnag automatically captures unhandled exceptions in Android apps and sends them to our dashboard, where you can prioritize fixes and dive into diagnostic information.
Here are some important things to consider when selecting or building a crash reporting system, along with some code snippets:
Detects unhandled exceptions automatically (example code)
Collects diagnostic data such as memory usage, device info, etc (example code)
Effectively groups crashes together by root cause
Allows you to track actions the user took before each crash to help reproduce (example code)
If you want to see some best practices around crash handling/reporting on Android you can check out the full source code for Bugsnag's crash reporting library which is fully open source, feel free to tear this apart and use it in your own applications!
Google changed how much crash reports you actually get. Previously you only got manual reported bug reports.
Since the last developer conference and the introducation of Android Vitals you also get crash reports from users which have enabled to share diagnostics data.
You'll see all crashes collected from Android devices whose users have opted in to automatically share usage and diagnostics data. Data is available for the previous two months.
View crashes & application not responding (ANR) errors
If your app is being downloaded by other people and crashing on remote devices, you may want to look into an Android error reporting library (referenced in this SO post). If it's just on your own local device, you can use LogCat. Even if the device wasn't connected to a host machine when the crash occurred, connected the device and issuing an adb logcat command will download the entire logcat history (at least to the extent that it is buffered which is usually a loooot of log data, it's just not infinite). Do either of those options answer your question? If not can you attempt to clarify what you're looking for a bit more?
Flurry analytics gives you crash info, hardware model, android version and live app usage stats. In the new SDK they seem to provide more detailed crash info http://www.flurry.com/flurry-crash-analytics.html.
You can do this directly in Android Studio. Just connect your phone, run the app, let it crash and you can view the stacktrace directly in Android Studio.

Categories

Resources