Restart Activity on uncaughtException - java

in the onCreate method of an Activity, I'm running this :
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Intent intent = getIntent();
finish();
startActivity(intent);
}
});
What I am trying to do is, when in this activity, I would like to restart it and clear previous intents, with these lines of code, I end up having a blank screen and the app running in the background, either way I have to restart it or kill it from the multitasking screen and this is not really user friendly. Any ideas? Thanks!
Edit : Is it also possible to build an alert dialog in here as well and display some message? And perhaps on OK press, the redirect will happen

For future reference, this did the trick for me :
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Intent crashedIntent = new Intent(MainDrawer.this, MainDrawer.class);
crashedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
crashedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(crashedIntent);
System.exit(0);
}
});

Related

how to open new activity from a thread with an handler

at the beginning every thing worked well, but i changed things and now the applcation crash when i open the new activity from a thread (not the UI thread).
the application only crash on my phone after installation, in debug mode it work well for some reason i can't understand.
this is my handler:
handler = new Handler(Looper.getMainLooper());
// --- thread work function ---
public void OnLoseActivity()
{
handler.post(new Runnable() {
#Override
public void run() {
Intent myActivity= new Intent(mainActivity.this, newActivity.class);
startActivity(myActivity);
}
});
}
something that i am doing wrong?
need to handle other issues before closing this first activity?
thanks
Update:
the reason i open an activity from a thread is that the thread checking for something in a loop, if it happand the activity shuold open.
I am not used to work with handlers, explain to me if im doing newb things please.
as i wrote, nothing special in the logcat because on debug it's working fine
If you're running this in an Activity, try this. Put your Intent in a method and call the method in your Runnable.
void startMyActivity()
{
Intent myActivity= new Intent(mainActivity.this, newActivity.class);
startActivity(myActivity);
}
and change your Runnable:
new Handler().post(new Runnable() {
#Override
public void run() {
startMyActivity();
}
});

Android - Activity finish() results black screen

I have an AlertActivity and an Activity. When a broadcast is received, both activities needs to finish. But the below code results Black screen if AlertActivity is on top of Activity.
Below is the code in Activity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT")){
if(alertActvity != null)
alertActivity.finish();
finish();
}
}
And code in AlertActivity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT"))
finish();
}
}
First, Activity's onStop() is getting called before AlertActivity's onStop() is called which results in Black screen, even AlertActivity's finish() called before Activity's finish().
Please help me in this regard.
Finally, I found a solution for this:
Finishing an Activity with a delay of 1 second which really works. By that time, AlertActivity finishes and black screen cannot be displayed.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, 1000);
as in both AlertActivity and Activity, you are checking for same action "BROADCAST_INTENT", I assume you registered both receiver in their own class.
If you did so, then actually you have two broadcast receiver waiting for same event. when this event occurs, both of your receiver are going to get it.
So in your AlertActivity is getting finished twice.
I think #Amit K. Saha, is right, your AlertActivity may be finishing twice
Solution :
If your application is running >= API 16 then you can use finishAffinity() method :
Finish this activity as well as all activities immediately below it in the current task that have the same affinity. This is typically used when an application can be launched on to another task (such as from an ACTION_VIEW of a content type it understands) and the user has used the up navigation to switch out of the current task and in to its own task. In this case, if the user has navigated down into any other activities of the second application, all of those should be removed from the original task as part of the task switch.
Note that this finish does not allow you to deliver results to the
previous activity, and an exception will be thrown if you are trying
to do so.
You can call finishAffinity() from AlertActivity because it is on top of Activity. This will finish AlertActivity as well as Activity
My transparent Activity finish results black screen, after a search, i find it is caused by activity switching animation in Android 4.4. But above android 5.1 the phenomenon does not show up.
So I add the below code:
#Override
public void finish() {
super.finish();
overridePendingTransition(0, 0);
}
The black screen after finish is gone.
I think this may be helpful.
try this
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT"))
context.finish();
}
}

Is it a bad practice use Thread.sleep(Milliseconds) for wait a bit before start another activity?

I'm making a SplashScreen for an app ... When the app starts, it start LoadingActivity ... sleep for 3 seconds, finish(); and then starts the MainActivity. Splash serves to update the database. If the database is already updated, I want the splash still for 3 seconds anyway.
I am using the following code:
protected void onPostExecute(Void result) {
super.onPostExecute(result);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Intent intent = new Intent(LoadingActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}
Is it a bad pratice? and why? The app is running nicelly in AVD.
Sleeping on the UI thread is always a bad idea. In this case you are in an onPostExecute, which is on the UI thread.
Throw your sleep into the doInBackground method of your AsyncTask instead, and you won't get any ANR's there (Android not responding).
Users don't like waiting for splash screens, so it is better not to wait at all. But sometimes the splash screen is required (ie due to contracts).
Yes it is bad practice, onPostExecute() is called on UI thread so basically you are blocking your UI thread for 3 whole seconds. I suspect you want to show a splash screen. You can instead do it like this.
new Handler().postDelayed(new Runnable(){
#Override
public void run(){
Intent intent = new Intent(LoadingActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
},3000);
or if you want to stick with AsyncTask then override doInBackground() and sleep in it and launch your Activity in onPostExecute() normally.
If this is is at the very start of the Programm you could do a while Loop that runns until System.currentTimeMillis() is higher than 3000 than it was at the Start of the program.

Displaying a progress dialog until new activity loads

I have a progress dialog I am trying to show when a user clicks a button to launch a new activity. The spinner should be displayed on the current page until the other activity appears. ( The activity can take sometimes up to 4-5 seconds to launch and without the spinner it just shows a pressed button that looks frozen )
This is what I have, it's only working if I remove hideProgressDialog();, but then the spinner will still be there when I back to the previous activity, obviously.
What am I doing wrong ?
Progress Dialog :
public void showProgressDialog(Context context) {
if(this.progressDialog != null) {
this.progressDialog.dismiss();
this.progressDialog = null;
}
this.progressDialog = ProgressDialog.show(context, "", "Chargement en cours, veuillez patienter");
}
public void hideProgressDialog() {
if(this.progressDialog != null) {
this.progressDialog.dismiss();
this.progressDialog = null;
}
}
Function :
public void startActivity(Context context, Class<? extends Activity> activityClass) {
try {
showProgressDialog(context);
Intent intent = new Intent(this, activityClass);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
hideProgressDialog();
}
catch(Throwable e) {
e.printStackTrace();
}
}
Example of a button click where this calls the function to show the spinner :
#Override
public void onClick(View view) {
if(view.getId() == R.id.changeBannerButton) {
getBaseApplication().startActivity(this, BannerListActivity.class);
}...
Call hideProgressDialog() in the onResume() method. This way, if the user presses the back button, the onResume() method gets called and immediately hides the progress dialog.
Well First off you should use the new DialogFragment class with FragmentManager. Because showdialog() is deprecated from API level 8
Next you should use showdialog and removedialog for adding and removing the dialog.
And you should use the onCreateDialog to handle the dialog and the operations. Like start a new thread to run do the job when you are displaying the progressdialog.
Try to load data in a seperate thread on start of activity. But before start of that process show the progress dialog. Now once the process is done use runOnUI to hide the progress dialog..
Indicate the user that data is being loading
http://www.helloandroid.com/tutorials/using-threads-and-progressdialog
and this:
Android - using runOnUiThread to do UI changes from a thread

Using global exception handling with "setUncaughtExceptionHandler" and "Toast"

I am trying to create a simple exception handler which will help me debug the application. Right now, when I have an exception I am forced to connect with Eclipse debugger merely to see the exception details.
To avoid that I've used setUncaughtExceptionHandler to handle any unhandled exception and display a Toast on the exception. Unfortunately, that doesn't work.
public class TicTacToe extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Toast.makeText(TicTacToe.this, "TOAST", Toast.LENGTH_LONG).show();
}
});
setContentView(R.layout.main);
Button continueButton = (Button) findViewById(R.id.cell01);
continueButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int i = 5;
i = 5 / 0;
Toast.makeText(TicTacToe.this, "BUTTON", Toast.LENGTH_LONG).show();
}
});
}
}
Essentially I made a form with a single button, pressing on which, it would throw a devision-by-zero exception. However, pressing the button doesn't cause the global toast handler to show. Instead, the button stays orange (pressed) and nothing happens.
Needless to say, if I comment out i = 5 / 0; I see the toast that says that a button was pressed.
Two questions:
1) Why isn't the toast showing in the UncaughtExceptionHandler body? How do cause it to show?
2) Is there an alternative/better way for global exception handling? I guess I could install aLogCat on the android simulator and simply log the uncaught exception, it seems, however, less comfortable - I will need to be switching applications just to see exception details.
Thanks!
It is possible. You need to do it inside another thread
Then it should be like this
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
new Thread() {
#Override
public void run() {
Looper.prepare();
Toast.makeText(TicTacToe.this, "TOAST", toast.LENGTH_LONG).show();
Looper.loop();
}
}.start();
}
});
You're not seeing anything because the exception happened on your UI thread and the stack unrolled all the way. So there is no more Looper and there is no support there that is used to display the Toast. If you want to display the exception information on screen you'll most likely need to start another Activity in another process.
There is also a problem with your UncaughtExceptionHandler. You really should keep a reference to the old one and call it at the end of uncaughtException this allows the system to display the Force Close button.
I know it's an old question but I hope I can save someone from frustration and wasting time.
Qberticus is right, you can't start an Activity on the same process, but you can kill the current process and have android run it in a new one:
Intent intent = new Intent(myContext, AnotherActivity.class);
intent.putExtra("error", errorReport.toString());
myContext.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
refer to this page for an awesome working example:

Categories