Android popup messages using Toast

In Android you can display pop up messages that lasts for a certain duration and then disappears-using the Toast class.

Toast is a transient message that appears and disappears without any interaction from the user and with no notification to the program that it disappeared.

the Toast can display a simple text message or a complex view.

Displaying simple text:

to display a simple toast that displays a text message we use the following code:
Toast toast=Toast.makeText(this, "Hello toast", 2000);
     toast.setGravity(Gravity.TOP, -30, 50);
     toast.show();

we create the toast using the static Toast.makeText(Context con,String message, int duration) method to create a toast in the current context to display a text message for a duration specified in milli seconds or we can use the constant values Toast.LENGTH_SHORT to display for a short duration or Toast.LENGTH_LONG for longer duration.
The toast by default appears in the center of the screen, you can change the default position by specifying the Gravity and the X and Y offsets.
finally we call the Show() method to display the toast.

the previous toast will be like this:

Displaying complex views:


Toasts can also display complex views. this is done like this:

First: create a layout xml file in res/layout directory. the file must be named toast_layout.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/toastView"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Hello toast"
    android:textColor="#000"
    />
    <TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/txtDate"
    android:textColor="#000"
    />
   
    
</LinearLayout>

then from the code
Toast toast=new Toast(this);
     LayoutInflater inflater=this.getLayoutInflater();
     View toastView=inflater.inflate(R.layout.toast_layout, (ViewGroup)findViewById(R.id.toastView));
     TextView txtDate=(TextView)toastView.findViewById(R.id.txtDate);
     txtDate.setText("toast appeared at "+Calendar.getInstance().getTime().toLocaleString());
     toast.setGravity(Gravity.CENTER, 0, 0);
     toast.setView(toastView);
     toast.show();

the toast will be like this:
Notes:
  • In the toast_layout.xml width, if you put any buttons or any control that has a callback, it would appear disabled and the user cannot interact with it.
  • The toast can be created in two ways: by calling Toast.makeText method or by specifyinga view via setView method. when you want to display a simple text use the first one otherwise use the second. if you try to interchange or combie between the two methods an exception will be thrown.

Reactions: 

Using Themes and Styles in Android

In web design we have the concept of Styles and Themes. Styles like Cascading Style Sheets (CSS) define the values of the web controls attributes such as width, heigth, font color, background and so on. A style can be applied on several controls in several web pages.

Themes are used to group a set of styles to be applied on the whole web application. Themes (or sometimes skins) define the look of all control within the application.

Android introduces similar concepts by using Styles and Themes. A Style can be applied to views individually while a Theme is applied to a whole activity.

Styles:

Styles are defined as xml resources files in res/values directory of your project.

consider this definition of a TextView:
<TextView    android:layout_width="fill_parent"   
     android:layout_height="wrap_content"    
     android:textColor="#FFF"    
     android:typeface="monospace"    
     android:text="First Text View"
     android:background="#00F" 
     />


this defines a text view with width and height equal to wrap_content, white font color, font type "monospace" and blue back ground.

if we want to have the same results using a style: we first create a xml file (call it styles.xml) in res/values directory and it would be like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="BlueLabel">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:typeface">monospace</item>
<item name="android:background">#00F</item>
<item name="android:textColor">#FFF</item>
</style>
</resources>

then redefine the TextView like this:
<TextView android:text="First Text View"
     style="@style/BlueLabel" / >


and you will receive the same results.
the attributes in the <item>tag can be any layout property.

Inheriting Styles:
Styles in Android has an interesting feature which is the ability to inherit styles in a fashion similar to that in CSS. consider this example:

we have a style for a button like this:
<style name="ButtonStyle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">15px</item>
<item name="android:typeface">serif</item>
</style>


the button will appear like this:

we can make this style inherit from BlueLabel defined previously by adding the parent attribute to the <style*gt; tag:
<style name="ButtonStyle" parent="BlueLabel">
then the button will be like this:
the button inherited the background color from the parent style.
another interesting feature in styles inheritance is the ability to inherit from the platform built-in styles defined in the android.R.style namespace. to know more about the platform styles check this link

or you can type in your editor (Eclipse) android.R.style and let the intelli-sense list you the complete list of platform styles, if you want to use them in your xml just replace the undrscores with a period like this:
Widget_Button becomes @android:style/Widget.Button.

In the previous button style example we will set the parent of the style to be @android:style/Widget.Button.Small
and the button will be like this:

Note: if you apply a style to a ViewGroup widget, it's child widgets will not inherit that style.

Using Themes

you can apply styles as themes on an activity level or application level.

if you apply a theme on an activity level then all widgets within that activity will inherit from that theme.
to do so, open the AndroidManifest.xml and go the <activity> tag and add the android:theme attribute:
<activity android:name=".StylesDemo"
                  android:label="@string/app_name" android:theme="@style/BlueLabel">


to apply a theme on the application level so that the style will be applied to all activities within your application, open the AndroidManifest.xml and go the <application> tag and add the android:theme attribute:
<application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/BlueLabel">

to set the theme of an activity programmatically call this line in the onCreate method
this.setTheme(R.style.BlueLabel);

Reactions: 

Android Error: Error generating final archive: Debug certificate expired on …

One day I opened eclipse to start a new android application, after creating the project and trying to run it I received the following error:

[2010-08-27 15:32:04 – (Project Name)] Error generating final archive: Debug certificate expired on 7/30/10 10:42 PM!

After searching I found this link which suggests the solution: http://www.androidian.de/?p=940.

The problem comes from the fact that Android required the applications to be signed even in the debug mode. So it uses a keystore file called debug.keystore to providde keys for signing applications in debug mode. This key store file has a validity period by default 365 days from its creation date.

The First Solution:


Navigate to the .android folder in your home directory “~/.android” (Linux,Mac OS) or c:\Documents and Settings\[User Name]\.android in windows XP or C:\Users\.android in windows Vista or Windows 7, and delete debug.keystore file. Then go to eclipse clean the project, this will create a new debug.keystore file with default validity period 365 days.

The Second Solution:


Create a new default.keystore file with custom validity period (say 1000 days).
  1. Navigate to the .android folder.
  2. Delete the old default.keystore file.
  3. We will use JDK Keytool.exe to generate the new key file. It is found in C:\Program Files\Java\jre6\bin in windows or inside the Java\jre6\bin folder in Mac OS or Linux.
  4. Open the terminal app in Mac OS or Linux or the command prompt and navigate to keytool.exe directory.
  5. Run the following command:
    keytool -genkey -keypass android -keystore debug.keystore -alias androiddebugkey -storepass android -validity 1000 -dname “CN=Android Debug,O=Android,C=US”
  6. This will generate a new default.keystore file with validity period 1000 days.
  7. Copy the generated file to the .android folder, go to eclipse and clean projects and it should work.
The above command has the following options:
  • genkey: generates a key pair.
  • keystore <Key Store Name>: the name of the key store file.
  • alias <alias name>: an alias for the key store. If the alias name is more than 8 characters the first 8 only are used.
  • storepass <password>: the password for the key.
  • validity <Validty Period>: the validity period for the key in days.
  • dname <name>: A Distinguished Name that describes who created the key. The value is used as the issuer and subject fields in the self-signed certificate.

Reactions: 

iPhone-Like Tab bar in Android

In a previous post we saw how to use the TabHost to create tabs in Android applications. Also we noticed that the Tabs in Android appear at the top of the activity.
but what if we want to give the tabs the look of the iPhone Tab Bar ?

this is possible by wrapping the TabWidget and the FrameLayout in a RelativeLayout container and adding android:layout_alignParentBottom="true" attribute to the TabWidget just like this:
<?xml version="1.0" encoding="utf-8"?>


    <TabHost android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@android:id/tabhost"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TabWidget
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@android:id/tabs"
    android:layout_alignParentBottom="true"
    />
     <FrameLayout
     android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@android:id/tabcontent"
     >
     
     </FrameLayout>
    </RelativeLayout>
    </TabHost>




Reactions: 

Tabbed Applications in Android

Some times we want to wrap multiple views in a single window and navigate throught them with a Tab Container. this can be done in Android using TabHost control

There are two ways to use a TabHost application in Android:
  1. Using the TabHost to navigate through multiple views within the same activity.
  2. Using the TabHost to navigate through Actual multiple Activities using intents.
we will explain both ways through this tutorial

Anatomy of Tabbed Application
An activity with a TabHost may look like this:


The Activity consists of:
  1. A TabHost: the root element of the layout.
  2. The TabHost wraps a TabWidget which represents the tab bar.
  3. The TabHost wraps a FrameLayout which wraps the contents of each tab.
There are some rules that we must stick to when using a Tabbed activity:
  1. If the activity is of type TabActivity [optional] then the TabHost must have the id @android:id/tabhost.
  2. The TabWidget must have the id @android:id/tabs.
  3. The FrameLayout must have the id @android:id/tabcontent.
no let's see an exaple to an activity with multiple tabs:
this is the layout
<?xml version="1.0" encoding="utf-8"?>


    <TabHost android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/tabHost"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <TabWidget
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@android:id/tabs"
    />
     <FrameLayout
     android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@android:id/tabcontent"
     >
     <LinearLayout
     android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/tab1"
    android:orientation="vertical"
    android:paddingTop="60px"
     >
     <TextView  
    android:layout_width="fill_parent" 
    android:layout_height="100px" 
    android:text="This is tab1"
    android:id="@+id/txt1"
    />
    
    
     </LinearLayout>
     
     <LinearLayout
     android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/tab2"
    android:orientation="vertical"
    android:paddingTop="60px"
     >
     <TextView  
    android:layout_width="fill_parent" 
    android:layout_height="100px" 
    android:text="This is tab 2"
    android:id="@+id/txt2"
    />
   
     </LinearLayout>
     
      <LinearLayout
     android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/tab3"
    android:orientation="vertical"
    android:paddingTop="60px"
     >
     <TextView  
    android:layout_width="fill_parent" 
    android:layout_height="100px" 
    android:text="This is tab 3"
    android:id="@+id/txt3"
    />
   
     </LinearLayout>
     </FrameLayout>
    
    </TabHost>

then in the code of our activity
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TabHost tabHost=(TabHost)findViewById(R.id.tabHost);
        tabHost.setup();
        
        TabSpec spec1=tabHost.newTabSpec("Tab 1");
        spec1.setContent(R.id.tab1);
        spec1.setIndicator("Tab 1");
        
        TabSpec spec2=tabHost.newTabSpec("Tab 2");
        spec2.setIndicator("Tab 2");
        spec2.setContent(R.id.tab2);
        
        TabSpec spec3=tabHost.newTabSpec("Tab 3");
        spec3.setIndicator("Tab 3");
        spec3.setContent(R.id.tab3);
        
        tabHost.addTab(spec1);
        tabHost.addTab(spec2);
        tabHost.addTab(spec3);
        
 }

is going to look like this:

  1. We create tabs using TabSpecs class.
  2. We set the title of each tab using TabSpecs.setIndicator() method.
  3. We set the content of each tab using TabSpecs.setContent() method.
  4. if you use TabActivity to as a base class to your activity, you do not need to call TabHost.Setup() method.
We can add an icon to the title of the tab like this:
TabSpec spec1=tabHost.newTabSpec("Tab 1");
        spec1.setContent(R.id.tab1);
        spec1.setIndicator("Tab 1",getResources().getDrawable(R.drawable.flash));
        
        
        TabSpec spec2=tabHost.newTabSpec("Tab 2");
        spec2.setIndicator("Tab 2",getResources().getDrawable(R.drawable.sun));
        spec2.setContent(R.id.tab2);
        
        TabSpec spec3=tabHost.newTabSpec("Tab 3");
        spec3.setIndicator("Tab 3",getResources().getDrawable(R.drawable.chart));
        spec3.setContent(R.id.tab3);

it will look like this:

we can also specify the indicator to be a view:
TabSpec spec1=tabHost.newTabSpec("Tab 1");
        spec1.setContent(R.id.tab1);
        TextView txt=new TextView(this);
        txt.setText("Tab 1");
        txt.setBackgroundColor(Color.RED);
        spec1.setIndicator(txt);



Setting the content of tabs:

we saw how to set the contents of tabs by specifying multiple layout resources to be displayed within the same activity.

what If we have multiple Activities in our application and we want to navigate between them using tabs ?
in this case we will have one activity as the root activity of the application. this activity will have the TabHost and will navigate to other activities using Intents.
Note: the root activity must inherit from TabActivity.

the root activity will have layout file like this:
<?xml version="1.0" encoding="utf-8"?>
    <TabHost android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@android:id/tabhost"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <TabWidget
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@android:id/tabs"
    />
     <FrameLayout
     android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@android:id/tabcontent"
     >
     </FrameLayout>
    </TabHost>

the other activities will have a simple layout consisting of a TextView.

now to the code of the roor activity
public class TabDemo extends TabActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TabHost tabHost=getTabHost();
        // no need to call TabHost.Setup()        
        
        //First Tab
        TabSpec spec1=tabHost.newTabSpec("Tab 1");
        spec1.setIndicator("Tab 1",getResources().getDrawable(R.drawable.sun));
        Intent in1=new Intent(this, Act1.class);
        spec1.setContent(in1);
        
        TabSpec spec2=tabHost.newTabSpec("Tab 2");
        spec2.setIndicator("Tab 2",getResources().getDrawable(R.drawable.chart));
        Intent in2=new Intent(this,Act2.class);
        spec2.setContent(in2);

        tabHost.addTab(spec2);
        tabHost.addTab(spec3);
    }
}

and the activity will look like this


Adding tabs at run-time:

we can add tabs to TabHost at run-time using TabSpec.setContent(TabContentFactory) method.

the TabContentFactory is an interface that requires the implementation of a callback method createTabContent(String tag) which returns the view to be added to the content of the tab.

so in the last example if we changed code that adds the content of the second tab to this:
TabSpec spec1=tabHost.newTabSpec("Tab 1");
        spec1.setIndicator("Tab 1",getResources().getDrawable(R.drawable.sun));

        spec1.setContent(new TabContentFactory() {
   
   @Override
   public View createTabContent(String tag) {
    // TODO Auto-generated method stub
    
    return (new AnalogClock(TabDemo.this));
   }
  });

the activity will look like this

Reactions: