Android app crashing when toast is run in try catch - java

I'm creating an android app that has a login screen. What I did was that whenever the user clicks the submit button, it runs a progressdialog. then call a new thread to verify the login. When I try to run a toast on the function inside the login, the app suddenly crashes. What I did with it is this:
loginButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
dialog = ProgressDialog.show(MainActivity.this, "",
"Validating user...", true);
new Thread(new Runnable(){
public void run(){
login();
}
}).start();
}
});
then my login function is this:
void login(){
try{
//some code
} catch(Exception e){
dialog.dismiss();
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
But for some reason once it goes to the catch function the app suddenly crashes only when I add the code for the toast. What is wrong with my code and why is it crashing only when I am using toasts?

The toast is in another work thread ?
Can you put the toast in runOnUiThread() ?

Have you tried debugging your code? You probably get null pointer from getApplicationContext() as you are calling it from your thread. Declare a variable context somewhere and use that variable to make Toast(if you need it).

Related

how to show pop up or custom toast in onStop() or onDestroy()?

I have an app how to make some notification when reaching specific time ...
I would to show some pop-up or custom layout when my app is onStop or onDestroy.
I would like this photo.
(click to enlarge)
If you just want to give a message then Toast is enough and easy.
#override
public void onStop() {
Toast.MakeText(context, "Your message here", Toast.LENGTH_LONG).show();
}
#override
public void onDestroy() {
Toast.MakeText(context, "Your message here", Toast.LENGTH_LONG).show();
}
EDIT: I won't recommend you to write long messages in Toast and show it for longer durations, instead consider a Statusbar Notification. Status Bar Notifications can be programmatically canceled when they are no longer relevant.
BUT If you still want to increase the duration of Toast message then here is a workaround.
private Toast mToastToShow;
public void showToast(View view) {
// Set the toast and duration
int toastDurationInMilliSeconds = 10000;
mToastToShow = Toast.makeText(this, "Hello world, I am a toast.", Toast.LENGTH_LONG);
// Set the countdown to display the toast
CountDownTimer toastCountDown;
toastCountDown = new CountDownTimer(toastDurationInMilliSeconds, 1000 /*Tick duration*/) {
public void onTick(long millisUntilFinished) {
mToastToShow.show();
}
public void onFinish() {
mToastToShow.cancel();
}
};
// Show the toast and starts the countdown
mToastToShow.show();
toastCountDown.start();
}
Here is how it works: the countdown has a notification time shorter than the duration for which the toast is displayed according to the flag, so the toast can be shown again if the countdown is not finished. If the toast is shown again while it is still on screen, it will stay there for the whole duration without blinking. When the countdown is finished, the toast is canceled to hide it even if its display duration is not over.
Simplest way would be to use a Toast (easy and immediate). More complex way is that you've to grant 2 special permissions "draw over other apps" and "app with usage access" (which are special permissions, so you need to create your own page to prompt the user to grant it), after which you can add your custom view directly to the windows manager of the system. Last but not least, you should seriously think if there's any benefit for the user to be notified on main screen about something after your main page has been stopped or destroyed, because that goes against the system design quite a lot.

Show toast prior to a for loop does not work

I am trying to show a toast prior to a for loop, however, the toast does not show. I also tried adding a snackbar, but that didn't work either. I would like to know why the toast does not fire first. I even tried the following, but it kept looping:
Toast toast = Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_SHORT);
while (!toast.getView().isShown()) {
toast.show();
}
How can I show a toast prior to a for loop?
ArrayList<String> pizzaBases = new ArrayList<> ();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
main.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_SHORT);
Snackbar.make(findViewById(android.R.id.content), "Had a snack at Snackbar", Snackbar.LENGTH_LONG).show();
}
});
SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
for (int i = 0; i < 100; i++) {
try {
String pizza = preferences.getString("TypeOfBase" + i, "");
if (!pizza.equals("")) {
pizzaBases.add(pizza);
}
} catch (NullPointerException e) {
//Do nothing here
}
}
}
});
Button button1 = (Button) findViewById(R.id.buttonOne);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
for (String myString : pizzaBases) {
System.out.println(myString);
}
}
});
}
I tried solutions like runOnUiThread, asynctask and while loops, but they all didn't show a toast nor a snackbar.
EDIT:
I found out that the UI only updates AFTER the for loop is done. I am wondering why it does that, although it is activated first.
The problem is that Toast.show() is asynchronous. The toast will not be displayed until the current method returns, and even then, Android may decide to show it at a later time (for example if there is already another toast displayed on the screen) or even not at all.
Do you really need to use the native toasts? Maybe the best would be to use another system that is more reliable. What about a custom view that appears on top of everything that looks like a toast and that you can show immediately and reliably?
You are not calling show() method on this line:
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_SHORT);
It should be:
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_SHORT).show();
You don't need to use runOnUiThread cause you're already on the main thread and you're not calling show() on your toast in the second code.
It's also better to pass in the nearest Context object to your toast.
public void onClick(View view) {
Toast.makeText(YourActivity.this, "Hello", Toast.LENGTH_SHORT).show(); // show must be called
Snackbar.make(findViewById(android.R.id.content), "Had a snack at Snackbar", Snackbar.LENGTH_LONG).show();
SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
...
}
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_SHORT);
When you are show toast you have to call .show() method.
If you are showing Toast in Activity it will be better to use Activity 's context
Correction
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_SHORT).show();
Snackbar.make(findViewById(android.R.id.content), "Had a snack at Snackbar", Snackbar.LENGTH_LONG).show();
If you want to show SnackBar than you have to provide the view of current activity not android.R.id.content
Correction
Snackbar.make(findViewById(R.id.parent_of_your_activity), "Had a snack at Snackbar", Snackbar.LENGTH_LONG).show();
You don't need to use runOnUiThread cause you're already on the main thread
You can get Context
via YourActivity.this or this in Activity itself
via getContext() in Fragment class

How do I make the AlertDialog box appear outside the app?

#Override
public void run() {
//Create thread that can alter the UI
AlarmPage.this.runOnUiThread(new Runnable() {
public void run() {
cal = Calendar.getInstance();
//See if current time matches set alarm time
if((cal.get(Calendar.HOUR_OF_DAY) == alarmTime.getCurrentHour())
&& (cal.get(Calendar.MINUTE) == alarmTime.getCurrentMinute())){
//If the sound is playing, stop it and rewind
if(sound.isPlaying()){
ShowDialog();
alarmTimer.cancel();
alarmTask.cancel();
alarmTask = new PlaySoundTask();
alarmTimer = new Timer();
alarmTimer.schedule(alarmTask, sound.getDuration(), sound.getDuration());
}
sound.start();
}
}
});
}
public void ShowDialog() {
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("REMINDER!");
alertDialog.setMessage("Turn off alarm by pressing off");
alertDialog.setNegativeButton("Off", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "OFF", Toast.LENGTH_SHORT);
}
});
alertDialog.show();
}
I am making a simple alarm clock app that notifies the user. I want to make a alert box that gives the user the option to turn off the alarm when it goes off. I was able to make the alert box, but it only appears in the app not outside of the app. I understand the app has to be in the background running. If I need to show more code or be more specific, just ask please.
Add a line as:
public void ShowDialog() {
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("REMINDER!");
alertDialog.setMessage("Turn off alarm by pressing off");
alertDialog.setNegativeButton("Off", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "OFF", Toast.LENGTH_SHORT).show();
}
});
alertDialog.show();
// line you have to add
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
}
check now.
Do not accept answers if they don't address your question, it is misleading.
The accepted answer is not correct, as it will never work outside your application.
Reason:
It requires an activity context not application context.
If you provide application context, your app will crash with IllegalArgumentException- you need to use Theme.AppCompat or their decendents...
If you need functionality as actually stated in the question you have to have a separate activity themed as a Dialog like here
or you can add a custom view to your window using window manager and making it system level alert like here.
Do this create an Activity without ContentView or a View associated with it and call your alertDialog method in your onCreate also remember to set the background of the Activity to Transparent using ColourDrawable
And that activity will look like a dialog or will suit your preference, you can also fall back to Themes so you can set an Activity as Dialog and treat it like Dialog also use DialogFragment

Start and cancel a toast programmatically

In my app, I've got a procedure that can last between 2 and 15 seconds more or less. What I want is to set a kind of toast that when the procedure starts shows:
Loading values. Wait...
Just now, I've setted the toast duration to SHORT, because if the procedure lasts about 5 or less seconds, a LONG will be just that, very long. But having setted the duration to SHORT, when it lasts more than 10 seconds the toast dissapears and there is no message showing that the app is still processing so the user can start touching things.
What I want is to set something like a toast but that I can programmatically cancel when the procedure is finished. Any ideas?
I would recommend that you simply set the Toast duration to the maximum possible time and then use the Toast object returned from Toast.makeText(...) to cancel it when your process is finished.
Toast t = Toast.makeText(....., YERY_LONG_TOAST_TIME);
t.show();
public void onYourTaskFinished() {
t.cancel();
}
Something like that.
I personally would recommend using a ProgressDialog btw: http://developer.android.com/reference/android/app/ProgressDialog.html
Here's an example:
final Toast toast = Toast.makeText(ctx, "This message will disappear in 1 second", Toast.LENGTH_SHORT);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
}
}, 1000); //specify delay here that is shorter than Toast.LENGTH_SHORT
final Toast toast = Toast.makeText(ctx, "hello android", Toast.LENGTH_SHORT);
Handler h= new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
toast.show();
}
}, 1000);
h.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
}
}, 3000);
You can have a handler of the Toast when you create it, pass it to you job and call the show() method when the job starts and call the cancel() method when the job finish.
However, from your description, toast message might not be your best choice. Toast is more like a hint which has little impact if the user misses it. With little background infomation about your app, I think you might need a ProgressDialog if you do not want the user to touch anything while you are loading data, or a ProgressBar if you just want the user to know your job's progress.
Do not use Toast for this purpose. You should use progress dialog or you can add progress indicator to notification bar. So user will be able to see progress even not being inside your app.

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

Categories