CustomExceptionHandler
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private Context ctx;
private ContentResolver cr;
public CustomExceptionHandler(Context ctx, ContentResolver cr) {
this.ctx = ctx;
this.cr = cr;
}
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 deviceUuid = Utilities.DeviceUuid(ctx, cr);
String bluetoothName = Utilities.LocalBluetoothName();
AsyncTasks.ErrorLogTask logTask = new AsyncTasks.ErrorLogTask(e, bluetoothName, deviceUuid, stacktrace);
logTask.execute();
}
}
Called from my main activity:
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(getBaseContext(), getContentResolver()));
When an exception occurs now, i dont get the regular "unfortunately, has stopped" popup. Its just a black screen. If i remove my call from my main activity, in other words dont use the CustomExceptionHandler anymore, i get the default behaviour.
Is there any way to implement the default error behaviour in my class?
Thanks in advance!
You can add the following at the end of your exception handler to get the "unfortunately has stopped" dialog:
System.exit(1);
However, this will cause the process to terminate which means that your AsyncTask will not run to completion.
In any case, I would doubt that your code will run reliably anyway if you are in an uncaughtExceptionHandler, because you have no idea what the state of your application is. It might work, and it might not. What you could also try is to create a new Thread in your uncaughtExceptionHandler and have that thread sleep for a little while and then terminate the application using System.exit(). That may give your AsyncTask enough time to run to completion.
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
New to android programming - apologies for incorrect jargon.
My app can save data entered to EditText fields.
It then can load this data and set the values of this data to String Variables.
Then it preforms a POST HTTP request with these strings.
I'm loading/saving string files using openFileInput and openFileOutput
I've created Methods:
public String LoadMethod()
public String SaveMethod()
These Methods work fine when the Method is in same class as the Activity calling it.
My problem is that 2 Activities need to be able to run the public String LoadMethod()
So what i did was create 2 java class files for Loading and Saving data.
Some commenting is in the files as I've been trying to debug.
LoadUserDetails.java
public class LoadUserDetails extends AppCompatActivity {
public static String sSavedName;
public static String sSavedCompany;
public static String sSavedPhone;
public static String sSavedCarRegistration;
String sNameFile = "name_file";
//private Context context;
public String LoadMethod(){
/* OPEN DETAILS FROM INTERNAL STORAGE*/
//context = getActivity();
/*NAME*/
try {
String sOpenName;
FileInputStream fileInputStream = openFileInput("name_file");
InputStreamReader inputStreamReaderName = new InputStreamReader(fileInputStream);
BufferedReader bufferedReaderName = new BufferedReader(inputStreamReaderName);
StringBuffer stringBufferName = new StringBuffer();
while ((sOpenName = bufferedReaderName.readLine()) != null) {
stringBufferName.append(sOpenName + "\n");
}
sSavedName = (stringBufferName.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The code repeats for opening the other 3 string files.
I Launch this method from my UserDetails.java Activity and MainActivity.java Activity using this code:
//Load User Details
LoadUserDetails load = new LoadUserDetails();
load.LoadMethod();
This is the error I get in logcat:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.visitorrego.oem.smartsigninvisitor/com.visitorrego.oem.smartsigninvisitor.UserDetails}: java.lang.NullPointerException
..........
Caused by: java.lang.NullPointerException
at android.content.ContextWrapper.openFileInput(ContextWrapper.java:191)
at com.visitorrego.oem.smartsigninvisitor.LoadUserDetails.LoadMethod(LoadUserDetails.java:31)
at com.visitorrego.oem.smartsigninvisitor.UserDetails.onCreate(UserDetails.java:37)
I've tried using Context and the ContextWrapper error disappears but i still get the others :(
I know its something to do with calling a method using OpenFileInput from a different class.
I don't have an issue with calling the postrequest method in my webrequest class...
Any ideas?
Can post more code if needed.
As I can understand from your code, the class LoadUserDetails is not an activity,
so probably you might need to change the
public class LoadUserDetails extends AppCompatActivity
to
public class LoadUserDetails
Send The Context as parameter from the page you're calling. Because the context is initialized normally onCreate() (usually for activities).
the function will be
public String LoadMethod(Context context){
....
FileInputStream fileInputStream = context.openFileInput("name_file");
....
}
and you can call it by
LoadUserDetails load = new LoadUserDetails();
load.LoadMethod(getApplicationContext());
As the title suggests, I'm trying to create a class that will display an error message in android and my reasoning is that, instead of creating a pop up wherever it was needed as well as declaring the preset error strings in the MainActivity, it would be cleaner to create a separate class containing the preset info and the code necessary to actually display the message. The only parameter it would need would be the actual exception.
The way I tried to achieve this was by extending the AlertDialog.Builder class as follows:
public class showError extends AlertDialog.Builder
{
private enum exString
{
UnknownHostException, IOException,
ConnectException, Exception,
NoTimeTablesFoundException
}
private String UHE;
private String IOE;
private String CE;
private String NTTFE;
private String CNFE;
private String title;
private String E;
private String message ="";
private String exception="";
Context cxt;
exString enumExc;
public showError(Exception ex, Context cxt)
{
super(cxt);
this.cxt = cxt;
initString();
try
{
exception = ex.getClass().getName().toString();
exception = exception.substring(exception.lastIndexOf(".")+1);
enumExc = exString.valueOf(exception);
}
catch (IllegalArgumentException err)
{
enumExc = exString.valueOf("Exception");
}
setType();
setTitle(title);
setMessage(message);
setPositiveButton("OK", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
}
});
setIcon(android.R.drawable.ic_dialog_alert);
//show();
}
private void initString()
{
String UHE = cxt.getString(R.string.errorUHE);
String IOE = cxt.getString(R.string.errorIOE);
String CE = cxt.getString(R.string.errorCE);
String NTTFE = cxt.getString(R.string.errorNTTFE);
String title = cxt.getString(R.string.errorTitle);
String E = cxt.getString(R.string.errorUnknown);
}
private void setType()
{
switch (enumExc)
{
case UnknownHostException:
{ message = UHE; break; }
case IOException:
{ message = IOE; break; }
case ConnectException:
{ message = CE; break; }
case NoTimeTablesFoundException:
{ message = NTTFE; break; }
case Exception:
{ message = E + exception; break; }
}
}
}
The way I would like for this to work is:
new showError(whateverException, this);
However, for some reason I don't understand, it constantly gives a WindowLeaked exception?
I commented the show() command in the class and, instead, started using
new showError(whateverException, this).show();
and this seems to work sometimes but this also throws the WindowLeaked exception from time to time.
First of all, can someone shed some light as to why, since it is the same context, does it make a difference where I call the show command (in the constructor of the class itself, or by calling the .show() method)?
Why does calling show in the constructor always throw an exception, whereas calling it by using .show() of the instantiated class sometimes work?
I understand that this exception is thrown when the activity that creates the dialog ends before the dialog is dismissed. Is this correct?
And if it is, when I try using MainActivity as the context, am I supposed to believe that the MainActivity ends? How can it end while the app is still running?
ALso, if these dialogs are asynchronous (they are on a seperate thread from the UI thread so as to not block the UI thread, is my understanding correct?) how come they need to be dismissed before the activity ends?
Because, it seems, in order for my code to work, I would actually need to have the app wait for the dialog to be dismissed (sort of how you cannot use the main form of a Windows desktop app while a MessageBox is being displayed), but it is my understanding that android doesn't do that by design.
Even more confusing is if instead of using this approach, I create and show an AlertDialog.Builder in every catch block, that seems to work perfectly each time... why?
Second, I'm not exactly trying to find out how to fix the flaws of my design but what I actually am looking for is understanding why my design is flawed and what approach would be appropriate to achieve what I want?
Or better yet, what is the industry standard for handling exceptions and displaying the appropriate error messages to the user so that he knows what has gone wrong (whenever possible)?
Thank you for your time and excuse the lengthy read.
I am using an AsyncTask to download a database with a progressdialog that shows progress on the UI. Some of my users are receiving the error:
CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
As I understand it, this should only happen if you are trying to update Views off of the UI thread. Here is the error:
com...updateops.DbCreate.onProgressUpdate(DbCreate.java:70)
at com...updateops.DbCreate.onProgressUpdate(DbCreate.java:1)
and here is my code:
public class DbCreate extends AsyncTask<String, String, String>{
private static Context mCtx;
private static ProgressDialog mDialog;
public static AmazonSimpleDBClient mSDbClient;
public static AmazonS3Client mS3Client;
private static int mAppVersion;
private static boolean mCreate;
public DbCreate(Context ctx, int versionCode, boolean create) {
mCtx = ctx.getApplicationContext();
mAppVersion = versionCode;
mDialog = new ProgressDialog(ctx);
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setMessage("Checking for server access. Please wait...");
mDialog.setCancelable(false);
mDialog.setMax(1);
mDialog.show();
mCreate = create;
}
protected void onProgressUpdate(String... name) {
if (name[0].equals("item")) {
mDialog.incrementProgressBy(1);
} else if (name[0].equals("setMax")) {
mDialog.setProgress(0);
mDialog.setMax(Integer.parseInt(name[1])); <-- This is line 70
}}
#Override
protected String doInBackground(String... arg0) {
**do stuff**
publishProgress("setMax", ""+ 3);
}
It looks to me like I am following exactly what I am supposed to do in order to avoid this error. Anyone know why it's happening?
Edit: I should also mention that this code works most of the time. I am receiving crash reports on the Developer Console.
According to the onProgressUpdate(Progress...) is invoked on the UI thread after a call to publishProgress(Progress...).
You should analyze the whole log report to check if there is any chance that your async task was created on other thread.
And if you really cannot find the root cause you can use a handler created on UI thread to workaround.
You code looks fine and in most of the cases it should work. I would suggest you to use handler. You can write a handler in UI thread and call it from onProgressUpdate(). This will completely ensure that the UI work is done in UI thread.
This will fix your issue for sure, but I dont know why you are gettin error at first hand. I have seen this kind of issue before and never got a concrete reason for it.
I had the same problem that you are describing and I fixed it by using a runOnUiThread() call against the context owned by the AsyncTask (as you also have in your example).
The following solution should absolve your issues;
#Override
protected void onProgressUpdate(final String... messages){
myActivityReference.runOnUiThread(new Runnable() {
#Override
public void run() {
// Your UI changes here.
}
});
}
It's worth noting that my AsyncTask was originally called from within a AlertDialog, which is what I believe is causing the issue to begin with.
I found the same issue on Android 2.3.x devices and here's the crash log:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:2934)
...
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.os.HandlerThread.run(HandlerThread.java:60)
The log indicates that onProgressUpdate and onPostExecute are executed on HandlerThread which is essentially a worker thread with a custom Looper. So that's why the crash occurs.
Therefore, in your case it is likely the internal handler of AsyncTask is bound to non main looper associated with a worker thread like HandlerThread and onUpdateProgress is processed on worker thread instead.
I found this bug appear pervasively on Android 2.3 devices. Therefore I checked the source code of AsyncTask in 2.3 and found this:
private static final InternalHandler sHandler = new InternalHandler();
private static class InternalHandler extends Handler {
#SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
#Override
public void handleMessage(Message msg) {
...
}
}
The chance is that the internal handler might be bound to a non main looper.
I also checked the latest source code of AsyncTask and saw the change:
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
...
}
The InternalHandler constructor eliminate the chance that it might be bound to a non main looper therefore onUpdateProgress behaves normal on post Android 2.3 devices.
I want to create a log file for my Android app. I need this to debug the random crashes of the applications.
I want to create a function which always get called if there is a unhandelled exception. In the log I want the exception message. Is there any event kind mechanism which will get invoked on unhandelled exception in ANdroid?
try to use android Android Acra
Really good thing Please try this.
You can write your own log cat,
when your application is installed on real android device and not connected to Eclipse to get debug details..
Please check Tutorial :Read & Store Log-cat Programmatically in Android
also you may like to check this stack-overflow page I have posted solution code snip and related useful information.
You can use UncaughtExceptionHandler as shown below:
public class UncaughtExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {
String Tag;
Context myContext;
public UncaughtExceptionHandler(Context context, String TAG) {
Tag = TAG;
myContext = context;
}
public void uncaughtException(Thread thread, Throwable exception) {
StringWriter sw = new StringWriter();
exception.printStackTrace(new PrintWriter(sw));
Logger.appendErrorLog(sw.toString(), Tag);
Intent intent = new Intent(myContext, ForceClose.class);
intent.putExtra(BugReportActivity.STACKTRACE, sw.toString());
myContext.startActivity(intent);
Process.killProcess(Process.myPid());
System.exit(10);
}
}
Call this class in the first activity's onCreate() method:
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(getApplicationContext(),"FirstActivity"));
I did a lot of research, but I didn't get through it, so that i don't know how to realize my App. The App consists of 2+ Activities, that contain content, that should be updated by a service in the background. So I dont know how to do the connection, some say i should do ipc, but others say thats too much of work, as long as service and activites run within the same process. I concerned to easily create methods like ActivityOne.RefreshData(Data data) and call those within the service, but i did not manage to get it work until now. I hope you have some suggestions to me and sorry for my bad english!
cheers
If you only need to provide data/updates to your own activities then IPC is most certainly not needed.
To achieve this, I would reverse the orientation you seem to be describing and rather than have the service calling methods on the activity, have it pushing messages to a Handler provided to it by the Activity when/if it starts.
See:
http://developer.android.com/reference/android/os/Handler.html
http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/
Note that if what you need to send from the service to activites is always the same type of object, you can simplify your implementation of handleMessage() by using the Message.obj field to hold your type and not bother with Bundles or parcelling. As in:
Handler impl in activity where NotificationModel is the type that the service always sends:
private Handler mNotificationListener = new Handler(){
#Override
public void handleMessage(Message msg) {
handleIncomingNotification((NotificationModel)msg.obj);
}
};
The service side of posting msgs to this handler looks like:
public class NotificationRouter {
private Application mContext;
private SparseArray<Handler> mListeners = new SparseArray<Handler>();
public NotificationRouter (Application app){
this.mContext = app;
}
public void registerListener(Handler handler){
mListeners.put(handler.hashCode(), handler);
}
public void unRegisterListener(Handler handler){
mListeners.remove(handler.hashCode());
}
public void post(NotificationModel notice){
Message m = new Message();
m.obj = notice;
for (int i = 0; i < mListeners.size(); i++){
Handler h = mListeners.valueAt(i);
h.sendMessage(m);
}
}
}