Apps

Android Jelly Bean ate my toast, the sequel: Revenge of the toast

If you miss toast messages in Android 4.2, follow this tutorial to learn how to create your own.

I recently wrote about my disappointment over Google's decision to allow users to turn off toast messages as of Android 4.2 (Jelly Bean). I vowed never to use toast messages again. The problem is, I really like toast messages. That got me thinking.

If a toast message is nothing more than a foreground window displayed at an arbitrary location, why couldn't I create my own toast messages? It turns out I can, and now so can you. Feel free to follow along with this tutorial, or, download and import the entire project into Eclipse.

1. Start a new Android project. Be sure to target Android 1.6 or better. Rename the startup activity to Main.java and the corresponding layout to main.xml.

2. In our /res folder, we will create a linear layout that contains two buttons.

main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center" >
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Homemade Toast"
        android:id="@+id/homemade_toast_button"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Standard Toast"
        android:id="@+id/standard_toast_button"/>
</LinearLayout>

3. In our /src folder, we begin Main.java by extending the standard application class and implementing the on click listener interface.

Main.java
package com.authorwjf.revengeoftoast;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
public class Main extends Activity implements OnClickListener {
       private PopupWindow popUp=null;
       private Handler h = null;
       private static final int WIDTH = 300;
       private static final int HEIGHT = 80;
       private static final int ONE_SECOND = 1000;
}

4. Override the on create function and wire up our listener to the buttons.

@Override
protected void onCreate(Bundle savedInstanceState) {  
super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       h = new Handler();
findViewById(R.id.homemade_toast_button).setOnClickListener(this);
       findViewById(R.id.standard_toast_button).setOnClickListener(this);
}

5. Finally, the implementation for the on click listener.

@Override
synchronized public void onClick(View v) {
      if (v.getId()==R.id.standard_toast_button) {
                     Toast.makeText(this, "Plain old toast",
Toast.LENGTH_SHORT).show();
      } else {
             if (popUp == null) {
                    popUp = new PopupWindow(this);
                    LinearLayout layout = new LinearLayout(this);
                    LayoutParams params = new
LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
                    layout.setOrientation(LinearLayout.VERTICAL);
                    layout.setGravity(Gravity.CENTER);
layout.setBackgroundColor(Color.DKGRAY);
                    TextView tv = new TextView(this);
                    tv.setTextColor(Color.WHITE);
tv.setTextSize(12);
                    tv.setText("Revenge of toast messages!");
                    layout.addView(tv, params);
                    popUp.setContentView(layout);
                    popUp.showAtLocation(layout, Gravity.BOTTOM, 10, 10);
                    popUp.setAnimationStyle(android.R.style.Animation_Toast);
                    popUp.update(0, 50, WIDTH, HEIGHT);
                    h.postDelayed(new Runnable() {
                           @Override
                           public void run() {
                                  popUp.dismiss();
                                  popUp=null;
                           }
                }, ONE_SECOND);
          }
     }
}

Now you are ready to see the power of the popup. Make sure you load the APK to a device or emulator that is running Android 4.2. From the Settings | Applications menu, turn off notifications and then give the buttons a try. Don't believe it? Toggle the notifications setting back and try again. You can't keep a good toast message down!

About

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

2 comments
dounowhoiam
dounowhoiam

Unless your app is disabling the ability to stop notifications messages (such as The Simpsons Tapped Out) or is sending push adverts, there is no need for a user to disable the notifications and then it is the fault of the app developer if another type of notification does not work.

authorwjf
authorwjf

I am with you. There is no reason for a user to disable notifications. But the fact remains that a user can as of Jellybean. And more importantly and inexplicably the notifications flag seems to be tied to toast messages ( a type of common dialog). So disabling notifications means toast messages get disabled as well, even local ones which have nothing to do with push notifications and the notification bar.