Search This Blog

23 April 2010

Progress Bar

Again building off any of our previous examples; this time we are going to do a progress dialog...

Open MyActivity.java and replace the onCreate method:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final ProgressDialog dialog = new ProgressDialog(MyActivity.this);
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setMessage("Downloading 200gb...");
        dialog.setCancelable(true);
        dialog.setMax(200);
        dialog.setProgress(0);
        dialog.show();

        Thread t = new Thread(new Runnable(){
            public void run() {
                while(dialog.getProgress() < dialog.getMax())
                {
                    dialog.incrementProgressBy(1);
                    try{Thread.sleep(50);}catch(Exception e){/* no-op */}
                }
                dialog.dismiss();
            }
        });
        t.start();
    }

Redeploy (mvn clean install) and launch.

Loading, please wait...

This time we are going to show the standard Please Wait dialog with the spinning circle.  This example is taken from the developer documentation.  Using any of our examples as a starting point, let's replace the onCreate method in MyActivity.

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "", "Loading. Please wait...", true);
        Thread t = new Thread(new Runnable(){
            public void run() {
                try{
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // no-op
                }
                dialog.dismiss();
            }
        });
        t.start();
    }

Redeploy (mvn clean install) and the dialog will show for 5 seconds before going away.

Checkbox dialog

Building on the previous example, this time we want to be able to select and unselect various items.  Because of that, this example will not actually close the dialog.

Open MyActivity.java and add a variable for storing the initial states:
final boolean[] states = {false, false, true};

Replace the setItems or setSingleChoiceItems with:
        builder.setMultiChoiceItems(items, states, new DialogInterface.OnMultiChoiceClickListener(){
            public void onClick(DialogInterface dialogInterface, int item, boolean state) {
                Toast.makeText(getApplicationContext(), items[item] + " set to " + state, Toast.LENGTH_SHORT).show();
            }
        });

Redeploy (mvn clean install) and you should be able to (un)select different ones.

Radio button selection dialog

Building on the previous list-selection example, we will add a radio-button icon to the list.

Open MyActivity from the previous example and change this line:
builder.setItems(items, new DialogInterface.OnClickListener(){
to:
builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener(){

The '-1' specifies which item to select by default. 0 would have been Red, -1 is none.

By default, the window will not close when they make a selection.  Replace this line:
                return;
with this line:

                dialogInterface.dismiss();


Redeploy (mvn clean install) and test.

List picker and fading popup notice

This example can be created from any of the previous as we are just going to replace the content of MyActivity.  In this case, we are going to create a popup, allow the user to choose one, and then show a temporary message telling them what they chose.  This example is directly from the developer documentation.

Open MyActivity.java and replace the contents of the onCreate method with the following:


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final CharSequence[] items = {"Red", "Green", "Blue"};
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Pick a color");
        builder.setItems(items, new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialogInterface, int item) {
                Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
                return;
            }
        });
        builder.create().show();
    }

Once you redeploy (mvn clean install) and launch your app, you will see the dialog.  Choose one and see the popup.

Notifications

Building on our Alert example, we are going to take a look at the Notification Service.  We are basing this example on the developer documentation.

First, open your MyActivity.java.  In the top of the file, add a static id for our notification:
    private static final int HELLO_ID = 1;
In the onClick method of our alert, replace the:
return;
with:
                String ns = Context.NOTIFICATION_SERVICE;
                NotificationManager mgr = (NotificationManager) getSystemService(ns);
               
                int icon = R.drawable.icon;
                CharSequence tickerText = "You closed the alert";
                long when = System.currentTimeMillis();
                Notification notification = new Notification(icon, tickerText, when);

                Context context = getApplicationContext();
                CharSequence contentTitle = "Hello Notification";
                CharSequence contentText = "This notification is to let you know you closed the popup alert.";
                Intent notificationIntent = new Intent(context, MyActivity.class);
                PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
                notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

                mgr.notify(HELLO_ID, notification);

Redeploy (mvn clean install) your app.  When you click OK to close the alert, a notification will appear in the notification bar.

22 April 2010

Alert Dialogs

Using our last example as a starting point, we are going to add an alert dialog.  Make sure to do a 'mvn install' before we get started so your IDE doesn't try to guess where R.layout.main is.

Open MyActivity.java. Let's modify the onCreate method:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        AlertDialog dialog = new AlertDialog.Builder(this).create();
        dialog.setTitle("It's an alert!");
        dialog.setMessage("This alert has a message.");
        dialog.setIcon(R.drawable.icon);
        dialog.setButton("OK", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialogInterface, int i) {
                return;
            }
        });
        dialog.show();
    }

Redeploy (mvn clean install) and you'll see the alert when you launch your app.

Setting an image background for the window title

Continuing from our Theme example, I decided to change the window title to have a background image...

granite.png
This is just a little simple image I made in GIMP using the granite fill tool... save this file to your src/main/android/res/drawable directory.

 Add a new style to styles.xml:
    <style name="HelloWindowTitleBG">
        <item name="android:background">@drawable/granite</item>
    </style>

Add this line to the Hello Theme (styles.xml):
        <item name="android:windowTitleBackgroundStyle">@style/HelloWindowTitleBG</item>
Redeploy (mvn clean install) and your app now has a stylish window title.

Themes

Going back to our non-transparent example, let's make it theme-oriented...

in styles.xml, add:
    <style name="HelloTheme" parent="android:Theme">
        <item name="android:windowBackground">@color/cornsilk</item>
    </style>
   
In main.xml, remove:
android:background="@color/cornsilk"

In AndroidManifest.xml, change:
<activity android:name=".MyActivity">
to
<activity android:name=".MyActivity" android:theme="@style/HelloTheme">

Redeploy (mvn clean install) and it should... well.. look the same ;)

No background color

For a moment we will side-step from our last exercise  to see how we would completely remove the cornsilk background, making our app see-through.

First, in main.xml, remove this line:
android:background="@color/cornsilk"

Now, in AndroidManifest.xml, change this line:
<activity android:name=".MyActivity">
to:
<activity android:name=".MyActivity" android:theme="@android:style/Theme.Translucent">

Redeploy (mvn clean install)  and the background is gone.  Not too useful for our text-based example, but maybe if we were doing a graphic-based overlay.

Basic text styling

Expanding on the example we did to set the text and background color, we will now move those definitions into a style.

First, let's add a color for error messages...  Add this line to your colors.xml:
    <color name="error">#cc3333</color>
Next, let's add a string for the error message... Add this line to strings.xml:
<string name="errmsg">ERROR!</string>
Now, let's create a new src/main/android/res/values/styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="DefaultText">
        <item name="android:textColor">@color/black</item>
    </style>
    <style name="ErrorText">
        <item name="android:textColor">@color/error</item>
        <item name="android:textStyle">bold|italic</item>
    </style>
</resources>
In your main.xml, change this line:
android:textColor="@color/black"
to:
style="@style/DefaultText"

Now to link in a 2nd text example so we can see them together... Make a copy of the TextView inside the LinearLayout and change these two lines:
    android:text="@string/hello"
    style="@style/DefaultText"
to:
    android:text="@string/errmsg"
    style="@style/ErrorText"

Redeploy (mvn clean install) and you can now see the previous black-on-cornsilk "Hello World!" as well as a bold-italic-red "ERROR!".

Changing the text and background color

Building on the hello world provided by our maven archetype, we will change the colors...

mvn archetype:generate -DarchetypeCatalog=http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml
When prompted, choose the galatea archetype and your package/artifactId. In this case, I chose 'org.eoti.galatea', 'HelloWorld2' and '1.0-SNAPSHOT'.

First things first, let's look at what we have before we go modifying it.  Go into your new directory (named after your artifactId -- HelloWorld2 in my case) and do:
mvn install
This will deploy the existing app to your emulator (you did have your emulator running as per the linked post above, right?).  Go into the app menu in your emulator and launch your app.  You'll see a basic white-on-black "Hello World!".  Go ahead and exit the app (back arrow). Let's make that a little brighter.

We'll cheat a bit.  Copy src/main/android/res/values/strings.xml to src/main/android/res/values/colors.xml

Now, in the new colors.xml, replace the <string /> tags with these:
    <color name="black">#000000</color>
    <color name="cornsilk">#fff8dc</color>
Next, we update the main.xml...
Add this to your LinearLayout:
    android:background="@color/cornsilk"
Add this to your TextView:
    android:textColor="@color/black"
Now when we redeploy (mvn clean install), the app is now showing "Hello World!" in black on cornsilk.

21 April 2010

Galatea - A Maven/Android Archetype



After my experience writing an archetype for Red Dwarf; I decided to do the same thing for Android.  This archetype is based on the maven-android-plugin. I'd like to thank Hugo for helping me get the configuration correct.   So let's get started.

As before...
F:\work>mvn archetype:generate -DarchetypeCatalog=http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-archetype-plugin:2.0-alpha-5-SNAPSHOT:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml -> ardor3d-archetype (null)
2: http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml -> kryten-archetype (null)
3: http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml -> galatea-archetype (null)
4: http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml -> kryten-archetype (null)
Choose a number: : 3 ((use whatever number is assigned to galatea))
[INFO] snapshot org.eoti.galatea:galatea-archetype:1.0-SNAPSHOT: checking for updates from eoti-public
[WARNING] *** CHECKSUM FAILED - Checksum failed on download: local = 'c4696ce0aeee29d53523e63f02230636518f8ad2'; remote = 'deb2361707aa66b51d4055be6452e818b9283be2' - RETRYING
[WARNING] *** CHECKSUM FAILED - Checksum failed on download: local = 'c4696ce0aeee29d53523e63f02230636518f8ad2'; remote = 'deb2361707aa66b51d4055be6452e818b9283be2' - IGNORING
Define value for property 'groupId': : org.eoti.android.test
Define value for property 'artifactId': : TestAndroid
Define value for property 'version':  1.0-SNAPSHOT: :
Define value for property 'package':  org.eoti.android.test: :
Confirm properties configuration:
groupId: org.eoti.android.test
artifactId: TestAndroid
version: 1.0-SNAPSHOT
(hit enter)
package: org.eoti.android.test
(hit enter)
 Y: : (hit enter)
[WARNING] Don't override file F:\work\TestAndroid\src\main\android\res\values\strings.xml
[WARNING] Don't override file F:\work\TestAndroid\src\main\android\res\layout\main.xml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:02.860s
[INFO] Finished at: Sun Apr 18 19:58:56 PDT 2010
[INFO] Final Memory: 6M/11M
[INFO] ------------------------------------------------------------------------

F:\work> cd TestAndroid
The resulting files:

F:\work\TestAndroid>tree /F
Folder PATH listing for volume WINDOWS
Volume serial number is 9827-5E66
F:.
│   pom.xml

└───src
    │   AndroidManifest.xml
    │
    └───main
        ├───android
        │   └───res
        │       ├───drawable
        │       │       icon.png
        │       │
        │       ├───layout
        │       │       main.xml
        │       │
        │       └───values
        │               strings.xml
        │
        └───java
            └───org
                └───eoti
                    └───android
                        └───test
                                MyActivity.java *

Make sure you have your emulator running (emulator -avd Device1, in my case):
F:\work\TestAndroid>mvn install
This will build, package and deploy it to your emulator.
 
F:\work\TestAndroid>mvn clean
In addition to cleaning your build tree, that will undeploy your app from the emulator.

Update: The repository has been moved from kallisti.eoti.org to repository-malachid.forge.cloudbees.com.  As such, the new command line to launch the archetype is:
F:\work>mvn archetype:generate -DarchetypeCatalog=http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml