Android: Toast is not showing before system.exit() - android

I have nested nested class where I am trying to display a toast for the outer most class before I exit the app. The toast works just fine if I comment out exit statement, so I know I'm accessing the context correctly. I have also tried putting the toast in a thread where it sleeps for 2000 ms (and vice versa for the exit statement), but that still does not work.
All I want to do display a toast and exit the program. (It would be nice to do it simultaneously, if possible...)
public class A extends Service {
private Context context;
//...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = this;
//...
return START_STICKY;
}
Handler disToast = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Toast.makeText(context, "see ya", Toast.LENGTH_SHORT).show();
return true;//also tried false, but that did not work...
}
});
private Runnable r = new Runnable() {
public void run() {
new CountDownTimer(3000, 1000) {
public void onFinish() {
Message msg=disToast.obtainMessage();
msg.obj="my message";
disToast.sendMessage(msg);
handler.removeCallbacks(updateTimerThread);
System.exit(0);
}
}.start();//end of inner most class
};//end of first inner class
}//outermost class
I'm not working with any Activities (outer most class is a Service, and the two inner are normal Java classes) so some of the answers do not work.

USE getApplicationConext() INSTEAD OF CONTEXT
Toast.makeText(getApplicationConext(), "Timer up. Existing app...", Toast.LENGTH_SHORT).show();

Handler disToast= new Handler(new Callback() {
#Override
public void handleMessage(Message msg) {
String mString=(String)msg.obj;
Toast.makeText(this, mString, Toast.LENGTH_SHORT).show();
}
});
private Runnable r = new Runnable() {
public void run() {
new CountDownTimer(3000, 1000) {
public void onFinish() {
Message msg=disToast.obtainMessage();
msg.obj="your message";
disToast.sendMessage(msg);
handler.removeCallbacks(updateTimerThread);
System.exit(0);
}
}.start();
};
More details Refer Here

please use
Toast.LENGTH_LONG instead of
Toast.LENGTH_SHORT
Toast.makeText(context, "Timer up. Existing app...", Toast.LENGTH_LONG).show();
Now your toast will be display after System.exit();

Related

How to kill Toast after exit app?

Need some help. I used double click on back button for exit app with Toast with next code:
#Override
public void onBackPressed() {
if (back_pressed + 2000 > System.currentTimeMillis()) {
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Нажмите еще раз для выхода", Toast.LENGTH_SHORT).show();
}
back_pressed = System.currentTimeMillis();
}
Found that fragment code here at stackoverflow. I guess this is the best solution for issue. But there is one ecxeption - toast is still on screen after exiting app. How to kill the toast when user click back button twice and application closed?
We can't kill toast when application closes. We can use toast like below code. Toast.LENGTH_SHORT).show(); less duration of toast when your app closes.
Toast.makeText(this, "Press again to exit.. ", Toast.LENGTH_SHORT).show();
Or, you can set Duration of Toast by code below:
Toast toast = Toast.makeText(getApplicationContext(), "Press again to exit..", Toast.LENGTH_SHORT);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
}
}, 500);
Or, you can use this :
private Toast toast = null;
toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT);
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
//Toast.makeText(this, "Press again to exit..", Toast.LENGTH_SHORT).show();
toast.setText("Press again to exit..");
toast.show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
#Override
protected void onStop () {
super.onStop();
toast.cancel();
}
You should be able to reach your goal by Using an helper class. In my applications I call this ToastManager.
In this class, you will manage every toast of your application and you can decide whether to dismiss or show them.
I did it to avoid the Toast queue, I'm dismissing the Toast when another one is shown.
You can implement it like below and call the dismissToast method in your custom application or Activity.
public class ToastManager {
private static Toast m_currentToast;
public static void showToast(Context ctx, String text)
{
try {
if (m_currentToast != null) {
m_currentToast.cancel();
}
m_currentToast = Toast.makeText(ctx, text, Toast.LENGTH_LONG);
m_currentToast.show();
}catch(Exception ex){
ex.printStackTrace();
}
}
public static void dismissToast(){
if(m_currentToast != null){
m_currentToast.cancel();
}
}
}
Obv you will have to create each tost by calling the showToast method.
hope this helps
Next code erase toast immediately after closing application:
#Override
protected void onStop () {
toast.cancel();
super.onStop();
}
I guess this is enough for my app, it's looking great.
Tnx Abhishek kumar )

Show Toast in a Thread of a Service

Hi i know there are lot of answers to this topic. But I tried a lot and it doesn't work. I want to show a toast inside a thread of a service. How can i solve this problem. Using getApplicationContext() etc. doesn't work.
I start the Service from an Activity (no bounding).
public class CarDataService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
startThreadUpdatingDatabase();
Toast.makeText(this, message, Toast.LENGTH_LONG).show(); //it works
}
private void startThreadUpdatingDatabase(){
Log.d("Database", "startThreadUpdatingDatabase(was called)");
new Thread(new Runnable() {
public void run(){
..
// here i want to use a toast!!!
}
}).start();
}
}
Thank you!
You have to start the thread:
new Thread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Your message",Toast.LENGTH_LONG).show();
}
}).start();
public Contect context;
member variable
onStartCommand(){
context = getApplicationContext)
}
acquivre reference to the context before you start the thread
new Thread(new Runnable() {
#Override
public void run() {
Toast.makeText(context,"Your message",Toast.LENGTH_LONG).show();
}
}).start();
and there you go
use AsyncTask instead that helps in context management
http://www.androidsnippets.com/use-toast-wherever-you-want
Handler h = new Handler(context.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(context,message,Toast.LENGTH_LONG).show();
}
});
see if this works out
Show your Toast using UI-Thread
new Thread(new Runnable() {
#Override
public void run() {
// SHOW TOAST
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(yourContext, "Hello from UI-thread", Toast.LENGTH_SHORT).show();
}
});
//... start DB work
}
}).start();
If you have no access to an activity, so do it this way:
new Thread(new Runnable() {
#Override
public void run() {
// no activity, so use Handler & mainlooper
new Handler(Looper.getMainLooper()).post(
new Runnable() {
public void run() {
// yourContext is Activity or Application context
Toast.makeText(yourContext, "Hello from UI-thread", Toast.LENGTH_SHORT).show();
}
}
);
//... start DB work
}
}).start();
Look at this: Static Way to get Context on android?

Handler postDelayed doesn't post on delayed?

I want to change some values onBackPressed method... And i override it like this:
#Override
public void onBackPressed() {
final Handler backHandler = new Handler();
backHandler.postDelayed(new Runnable() {
public void run() {
exitCount = 0;
Log.d("exitCount", "exitCount: " + exitCount);
}
}, Toast.LENGTH_SHORT);
}
But the problem is handler posts immediately... There's no delay. Where am i doing wrong?
Sorry if this is a lame question, i'm pretty new on Android. Thanks in advance.
That is because Toast.LENGTH_SHORT value is zero. Try declaring your constant with a delay value you choose. see here
Make the handler part of an activity (or part of a thread you are posting a message to if its not for the UI thread), and use a millisecond delay rather than Toast.LENGTH_SHORT which has a value of zero so it will happen instantly.
public class SomeActivity extends Activity {
private Handler mHandler = new Handler();
#Override
public void onBackPressed() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d("tag", "Hello, Handler!");
}
}, 1000); // one second
}
}
Use belo code I hope it will work.
runOnUiThread(new Runnable() {
#Override
public void run() {
backHandler.postDelayed(new Runnable() {
public void run() {
exitCount = 0;
Log.d("exitCount", "exitCount: " + exitCount);
}
}, Toast.LENGTH_SHORT);
}
});

IntentService won't show Toast

This IntentService I created will show Toasts in onStartCommand() and in onDestroy(), but not in onHandleIntent(). Am I missing something about the limitations of an IntentService?
public class MyService extends IntentService {
private static final String TAG = "MyService";
public MyService(){
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
cycle();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); //This happens!
return super.onStartCommand(intent,flags,startId);
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
Toast.makeText(this, "service stopping", Toast.LENGTH_SHORT).show(); //This happens!
super.onDestroy();
}
private void cycle(){
Toast.makeText(this, "cycle done", Toast.LENGTH_SHORT).show(); //This DOESN'T happen!
Log.d(TAG,"cycle completed"); //This happens!
}
}
The accepted answer is not correct.
Here is how you can show toast from onHandleIntent():
Create a DisplayToast class:
public class DisplayToast implements Runnable {
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text){
this.mContext = mContext;
mText = text;
}
public void run(){
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
Instantiate a Handler in your service's constructor and call the post method with a DisplayToast object inside.
public class MyService extends IntentService {
Handler mHandler;
public MyService(){
super("MyService");
mHandler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new DisplayToast(this, "Hello World!"));
}
}
You should start the Toast on the main thread:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
});
This is because otherwise the thread of the IntentService quits before the toast can be send out, causing a IllegalStateException:
java.lang.IllegalStateException: Handler (android.os.Handler) {12345678} sending message to a Handler on a dead thread
onHandleIntent() is called from a background thread (that is what IntentService is all about), so you shouldn't do UI from there.
Another option is RxJava, e.g.:
private void showToast(final String text) {
Observable.just(text)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
#Override
public void call(String s) {
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
}
});
}
Caveat: I'm new to Android.

Toast created in an IntentService never goes away

I have an IntentService that downloads some files. The problem is that I create a Toast inside the IntentService like this
Toast.makeText(getApplicationContext(), "some message", Toast.LENGTH_SHORT).show();
The Toast will never disappear event if I exit the app. The only way to destroy it is to kill the process.
What am I doing wrong?
The problem is that IntentService is not running on the main application thread. you need to obtain a Handler for the main thread (in onCreate()) and post the Toast to it as a Runnable.
the following code should do the trick:
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyIntentService.this, "Hello Toast!", Toast.LENGTH_LONG).show();
}
});
}
This works for me:
public void ShowToastInIntentService(final String sText) {
final Context MyContext = this;
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast toast1 = Toast.makeText(MyContext, sText, Toast.LENGTH_LONG);
toast1.show();
}
});
};
IntentService will create a thread to handle the new intent, and terminated it immediately once the task has done. So, the Toast will be out of controlled by a dead thread.
You should see some exceptions in the console when the toast showing on the screen.
For people developing in Xamarin studio, this is how its done there:
Handler handler = new Handler ();
handler.Post (() => {
Toast.MakeText (_Context, "Your text here.", ToastLength.Short).Show ();
});
To show a toast when the user is in one of the application activity.
Just need a reference of the current activity, and call it with this sample code:
public void showToast(final String msg) {
final Activity a = currentActivity;
if (a != null ) {
a.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(a, msg, Toast.LENGTH_SHORT).show();
}
});
}
}
There is a lot of options to get the current activity, check this question:
How to get current foreground activity context in android?
But I use this approach:
The application must have:
private Activity currentActivity = null;
public Activity getCurrentActivity() {
return currentActivity;
}
public void setCurrentActivity(Activity mCurrentActivity) {
this.currentActivity = mCurrentActivity;
}
Each activity must have:
#Override
protected void onResume() {
super.onResume();
((MyApplication) getApplication()).setCurrentActivity(this);
}
#Override
protected void onPause() {
super.onPause();
((MyApplication) getApplication()).setCurrentActivity(null);
}
You shouldn't create Toasts from a Service. You should use a Notification instead.

Categories

Resources