Cyril Mottier

“It’s the little details that are vital. Little things make big things happen.” – John Wooden

Introduction to the GreenDroid Library

Note: Before starting with this post I’d like to explain myself about the fact this article has been written in English. Indeed, I have proclaimed, quite a few times, this blog was intended to French speakers only. Actually I have recently changed my mind and here is a brief explanation. When I created this blog I was trying to explain to French speakers how to use and code properly for the Android platform. It had been a truly difficult choice for me because I was and I’m still a big fan of English speeches/talks. Nevertheless, the main reason that pushed me to start writing in French was the fact French documentation dealing with Android was/is very poor. For more than a year, I have written several articles and I really hope you have appreciated all of them. Nowadays, I want to talk about innovative concepts and/or technologies which, I think, will be useful to many users/developers all around the world. As a result, I have to write my posts using the most common language on Earth: English. I’m sure, French speakers will succeed in reading this blog and I’d like to warn them: “Je n'ai pas prévu d'arrêter d'écrire des posts en français !”.

I’m really glad to introduce you to my first attempt of a “true” development library for Android! As you may have noticed it is named “GreenDroid” and is intended to help people in designing Android applications. Keep in mind, it is still a work in progress! Let’s explain everything about GreenDroid before diving into it!

The main purpose of GreenDroid

As some of you may know, I’m a mobile software engineer and I’ve already developed on many constrained platforms. Each platform I have used have inherent advantages or disadvantages. For instance, Android development rocks because it is based on the Java programming language which is easy to use. On the other hand, I’ve also heavily used the iPhone SDK and I’m a huge fan of its simplicity - it looks like the Mac OS X user environment: simple and efficient - and most of all, the fact you can create your own libraries.

For a long time I have coded on the Android platform by doing the same things over and over again. To prevent me from doing mistakes and _copy&paste_s I’ve decided to initiate a personal project called GreenDroid. Here are the main purposes of this project:

  • Prevent loosing time at copying the same snippets of code over and over again.

  • Try to make Android applications alike. The openness of the Android operating system makes it less coherent. Seing so many applications that use totally different ergonomics or designs drives me mad. Indeed, I truly think, Android applications need coherency in order to get more and more users around the world. GreenDroid is kinda of a try to bring coherency to your applications and therefore to the Android environment. Google recently tried to show a path to “great UX and UI” with the Twitter and Google I/O applications - A talk about Android UIs will be given at Google I/O 2010 and I’m looking forward to watch it; I would like to see if Google has understood Android developers need help creating simple and smart interfaces!

  • Help developers to code highly functional applications. The Android framework may look like “over-engineered” sometimes. Actually, I believe this is a direct consequence of the fact you can do almost everything you want. Unfortunatly, this openness (again!) makes it harder to apprehend. Let’s say for instance, you are a beginner and wants to develop your own application. You’ll have to read a lot of documentation in order to be “up and ready”. GreenDroid makes development a lot easier without dicreasing the powerfulness of the amazing Android framework!

  • Leverage the power of the Android framework. Developing on the Android platform may be pretty easy if you’re not taking care of the resources you’re using. Trying to optimize your application is quite hard sometimes and is a very demanding task. GreenDroid has been developed to be as efficient as possible by integrating basic optimizations.

  • Use as much XML as possible. It’s not a mystery to anybody. Android UI development is based on amazing techniques. Layouts and views are defined in XML and automatically inflated by the system. Being an “easy-to-read-for-humans” format, XML is very used among Android developers. GreenDroid puts XML in the middle of the library and takes advantage of all amazing possibilities offered by Android XML files.

Why have I chosen the “GreenDroid” name?

When I started this project, I have spent a few minutes to think about an appropriate name. At the first glance, I was like “Who cares? It’s a personal project and I will never share it!” but once I realized this project could be useful for a lot of people I decided to think about a clear and smart name. The thought ended up on the name GreenDroid which can be seen as a contraction of the “green” color and the name “Android”. I suppose I don’t need to explain why the library name contains an occurence to Android … so I’ll explain what the “green” word stands for:

  • Green because it’s an “ecological” library. One of the main purpose of this library, as said previously, is to be as efficient as possible by helping developers to optimize their applications. The green color refers to ecology and I thought using it was a good explanation to the library: develop preserving all resources that are available to you!

  • Green because Android is nothing without green Come on guys! You all know the Android mascot is always green. Seeing it wearing other colors makes all of us sad. I couldn’t name my library using another color!

  • Green because I like being green!

How hard it is to create an Android library

The answer is quite simple and straight forward; it’s impossible! Why? Because it is impossible to bundle R.java in external jars … :(. This R.java file contains a set of references to external resources as simple integers int. The only external R.java available in your application is the one bundled with the Android framework.

Here are some ways I know that try to overcome that R.java problem:

  • Using no resource. The problem with that method is it very painful to code without XML. Being convinced Android developers enjoy XML, I’m sure there are just a few people creating their GUI using Java code. Personally, I love the LayoutInflater and its simplicity.

  • Using methods such as Resources.getIdentifier(String name, String defType, String defPackage). Unfortunaty those methods are quite slow to execute which is the opposite of GreenDroid’s main purpose. It’s a great alternative but makes the Java almost unreadable and still force the developer to manually copy resources from the library to his/her project.

  • Copying manually all resources from a project to another. This is basically the method I decided to use. The only difference with the “dumb way” is I created a Python (I’m still a newbie with Python - but I really like it) script that applies the GreenDroid library to your application by switching automatically to the project package name. Developing a graphical library being impossible, I have developed many features that will “fake” GreenDroid is a library. This is an approach I have designed alone and I’m still listening to your ideas to overcome that R problem of the Android SDK

Note: I haven’t taken a look at the Maven Android plugin yet. If one of you think it could be a great way to overcome the R problem, feel free to reply

How to use GreenDroid ?

In order to use GreenDroid you have to do the following steps:

  1. Download the GreenDroid library on your computer with a simple: git clone http://github.com/cyrilmottier/GreenDroid.git

  2. Apply GreenDroid to your project: Go to the scripts/ folder of the GreenDroid folder. Run the script named “greendroid.py” (make sure you can run it - chmod +x greendroid.py) to apply the library to your project : ./greendroid.py apply <project_directory>

  3. By default, the GreenDroid theme inherits from @android:style/Theme. If your project inherits from a different theme, you’ll have to modify the GreenDroid library on your own (and do that everytime you are updating GreenDroid as updating delete all of your changes). Open the res/values/gd_themes.xml and replace the parent theme @android:style/Theme with your own theme

  4. You finally need to make your project use the GreenDroid base theme. In your Android Manifest, go to the application tag and add android:theme="@style/Theme.GreenDroid" as a new attribute (if this attribute already exist override it: if you processed the step 3 correctly, you will have a theme that inherits from this theme)

Hello GreenDroid !

As I said previously, GreenDroid is pretty much a work in progress. For now, it mostly enhances ListView and Adapters by helping the user creating advanced UIs. I have thousands of ideas about how to make Android development easier and how to create easier amazing UIs but I don’t have a lot of free time to develop those importants features…

Items-based ListViews

Creating ListView with various cells can be quite painful. You have to understand perfectly how an Adapter work. You also need to create layout for all of those cells and this is a very boring task. Creating advanced ListViews with GreenDroid is very simple and relies on a simple notion: the item. An item is a wrapper of data that contains everything that will be displayed in the associated item view. The following snippet of code shows you how to use an ItemAdapter:

BasicItemActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package com.cyrilmottier.android.gdcatalog;

import greendroid.widget.ItemAdapter;
import greendroid.widget.item.DescriptionItem;
import greendroid.widget.item.DrawableItem;
import greendroid.widget.item.Item;
import greendroid.widget.item.ProgressItem;
import greendroid.widget.item.SeparatorItem;
import greendroid.widget.item.TextItem;
import greendroid.widget.item.ThumbnailItem;

import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
import android.os.Bundle;
import android.os.Handler;

public class BasicItemActivity extends ListActivity {

    private final Handler mHandler = new Handler();

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

        List<Item> items = new ArrayList<Item>();

        items.add(new SeparatorItem("Class 1"));
        items.add(new ThumbnailItem("Powered paragliding", "aka paramotoring", R.drawable.class1));
        items.add(new DescriptionItem(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));

        items.add(new SeparatorItem("Class 2"));
        items.add(new DrawableItem("Trikes", R.drawable.class2));
        items.add(new DescriptionItem(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));

        items.add(new SeparatorItem("Class 3"));
        items.add(new ThumbnailItem("Multi-axis", "Looks like a tiny place", R.drawable.class3));
        items.add(new DescriptionItem(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));

        items.add(new SeparatorItem("Class 4"));
        items.add(new ThumbnailItem("Auto-gyro", "A scary helicopter", R.drawable.class4));
        items.add(new DescriptionItem(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));

        items.add(new SeparatorItem("Class 5"));
        items.add(new DrawableItem("Hot air baloon", R.drawable.class5));
        items.add(new DescriptionItem(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));

        final Item item1 = new SeparatorItem("Class 6");
        final Item item2 = new TextItem("Airbus/Boeing planes");
        final Item item3 = new DescriptionItem(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in.");
        items.add(item1);
        items.add(item2);
        items.add(item3);

        final ProgressItem progressItem = new ProgressItem("Removing intruders", true);
        items.add(progressItem);

        final ItemAdapter adapter = new ItemAdapter(this, items);
        setListAdapter(adapter);

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                adapter.remove(item1);
                adapter.remove(item2);
                adapter.remove(item3);
                adapter.remove(progressItem);
                adapter.insert(new ThumbnailItem("Ultralight aviation", "List of French 'ULM' classes", R.drawable.greendroid_icon), 0);
                adapter.notifyDataSetChanged();
            }
        }, 8000);

    }
}

XML generated items

Android has an amazing feature that consists on inflating data and views from an XML file. I extended it to the GreenDroid library. With GreenDroid you can create and inflate static items and display those items in a simple ListView:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="utf-8"?>
<item-array xmlns:greendroid="http://schemas.android.com/apk/res/com.cyrilmottier.android.gdcatalog" >

    <text-item greendroid:text="TextItem" />

    <text-item
        greendroid:enabled="false"
        greendroid:text="TextItem (disabled)" />

    <text-item greendroid:text="TextItem Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in." />

    <longtext-item greendroid:text="LongText Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in." />

    <description-item greendroid:text="DescriptionItem Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in." />

    <separator-item greendroid:text="SeparatorItem" />

    <progress-item
        greendroid:isInProgress="true"
        greendroid:text="ProgressItem" />

    <drawable-item
        greendroid:drawable="@drawable/greendroid_icon"
        greendroid:enabled="false"
        greendroid:text="DrawableItem (disabled)" />

    <drawable-item greendroid:text="DrawableItem (with no drawable)" />

    <subtitle-item
        greendroid:subtitle="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."
        greendroid:text="SubtitleItem" />

    <subtext-item
        greendroid:subtext="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."
        greendroid:text="SubtextItem" />

    <thumbnail-item
        greendroid:subtitle="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."
        greendroid:text="ThumbnailItem"
        greendroid:thumbnail="@drawable/greendroid_icon" />

    <thumbnail-item
        greendroid:enabled="false"
        greendroid:subtitle="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."
        greendroid:text="ThumbnailItem (disabled)"
        greendroid:thumbnail="@drawable/greendroid_icon" />

</item-array>

Thanks to XML, the associated Java code is very clear and simple:

XmlItemActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.cyrilmottier.android.gdcatalog;

import greendroid.widget.ItemAdapter;
import android.app.ListActivity;
import android.os.Bundle;

public class XmlItemActivity extends ListActivity {

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

        ItemAdapter adapter;
        try {
            adapter = ItemAdapter.createFromXml(this, R.xml.items);
            setListAdapter(adapter);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

The GreenDroid library can be download on Github:

http://github.com/cyrilmottier/GreenDroid

The library includes a project called GDCatalog that uses the GreenDroid library. It has been develop to help developers understanding how to use GreenDroid in their projects. Keep it mind, the GDCatalog project doesn’t include the library. Prior to launch it, apply the library using the greendroid.py script. If you kept the directory hierarchy of the Git repository you need to execute the following command from the root directory:

cd GreenDroid/scripts && ./greendroid.py apply ../../GDCatalog

Eclipse may not see the new files that have been added. In order to refresh the project, right-click on the project and select “Refresh”.

Happy coding !