Archive for October, 2011
Ubuntu’s aim to be more user-friendly than the typical Linux distribution (or as I like to call it, more Apple than Apple) has lead to some rather strange choices when it comes to core system components, such as the firewall.
Most Linux systems use iptables, which works great and is very configurable. I guess Canonical saw two problems with this – one, it doesn’t have a graphical user interface and two, the syntax is very convoluted due to it’s flexibility.
Canonical have gone for “ufw” – the Uncomplicated Firewall. I actually think this might be some sort of wrapper to core iptables functionality, but anyway – it’s different. Because Ubuntu is primarily a desktop operating system with less enemies in the wild than say, Windows, it’s actually not enabled by default.
Yeah, I know right?
Anyway, the first thing to do is to deny everything, rather than allow everything in and out. This can be achieved with: -
sudo ufw default deny
Obviously, the other option is to replace “deny” with “allow” to open everything, but probably not something the security aware will want to do :-) To enable the firewall, use: -
sudo ufw enable
and to disable, use: -
sudo ufw disable
The default setting for ufw is to allow everything until you start adding rule-sets to allow or deny specific services to the outside world. It’s also worth setting up logging on ufw, so that you can see what is going on. Do this with: -
sudo ufw logging on
This will write firewall logs to the “/var/log/ufw.log” location. Okay, now assuming you want to add some common services through the firewall, the syntax is much easier than iptables. The general syntax is: -
sudo ufw allow [port]/[optional: protocol]
For example, if I wanted to allow remote SSH connections (default port of 22) via TCP to my Ubuntu machine, I’d use: -
sudo ufw allow 22/tcp
You don’t need to specify either UDP or TCP protocols if you don’t want to, I could simply have used: -
sudo ufw allow 22
Which would open port 22 for both UDP and TCP connections. I can remove this rule again with:-
sudo ufw delete allow 22/tcp
As with the “allow” directive, there is a corresponding “deny” directive. So I could specifically disable SSH connections on port 22 with: -
sudo ufw deny 22/tcp
or…
sudo ufw deny 22
Again, I can remove this rule with: -
sudo ufw delete deny 22/tcp
To see the status of the UFW firewall you can use: -
sudo ufw status
which will list all the current rule-sets. Depending on whether you’ve set up the UFW firewall to be mostly open or mostly closed (i.e. allow all traffic except services specifically denied or deny all traffic except services specifically allowed), your rules may consist mostly of “allow” or “deny” directives.
You can also allow connections from specific hosts with: -
sudo ufw allow from 192.168.1.3
or deny with: -
sudo ufw deny from 192.168.1.3
You can delete the above rule in a similar way to deleting a rule for allowing or denying a port with: -
sudo ufw delete allow from 192.168.1.3
Since UFW reads services from Ubuntu’s “/etc/services” file, you can add or deny services using the ports corresponding service name, so in the above example I could just as easily have used: -
sudo ufw allow ssh
instead of port 22 or…
sudo ufw allow http
instead of using port 80.
By default UFW also allows ping requests. That is, if another computer pings our Ubuntu machine with a data packet, Ubuntu will reply, thus showing that the host exists on the network. You can turn this on or off by editing the ” /etc/ufw/before.rules” file, which will have something like: -
# ok icmp codes
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type source-quench -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT
Change the “ACCEPT” to “DROP” to direct UFW to not reply to ICMP ping request packets so that it reads: -
# ok icmp codes
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-input -p icmp --icmp-type source-quench -j DROP
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP
If you’ve used iptables in the past, you notice that the syntax is fairly similar at this level, hence my suspicion that UFW is actually just a wrapper for iptables :-) Anyway, if all this is too much for you, there is a graphical frontend for UFW called “gufw”. While UFW is installed on Ubuntu machines by default, the GUI is not and needs to be installed with: -
sudo apt-get install gufw
This GUI is usually disabled and locked upon first load (“sudo gufw”) and pre-Ubuntu 11.10, and had an obvious-looking check box you could tick to enable the GUI. This has now been changed and you have to click on the non-obvious “padlock” icon on the lower right of the window to unlock the GUI. Hmm.
To make sure the Ubuntu UFW firewall is enabled on startup, you need to change it’s configuration files (or at least check them). This is located at:-
sudo vi /etc/ufw/ufw.conf
The output, assuming the firewall is enabled and will stay that way at system start up is: -
# /etc/ufw/ufw.conf
#
# Set to yes to start on boot. If setting this remotely, be sure to add a rule
# to allow your remote connection before starting ufw. Eg: 'ufw allow 22/tcp'
ENABLED=yes
# Please use the 'ufw' command to set the loglevel. Eg: 'ufw logging medium'.
# See 'man ufw' for details.
LOGLEVEL=low
That should give you enough information on Ubuntu’s firewall to secure your Ubuntu system to how you like it. For more information, check the man pages for ufw.
I spent ages setting up my Ubuntu netbook set up for OpenGL C++ development and now that I’ve upgraded, I can’t compile my SDL/OpenGL C++ program. Since I sort of set this up before by trial and error, I thought I’d document it this time to help out others. When I try and compile my code with: -
g++ -lX11 -lXi -lXmu -lGLEW -lSDL -lGL -lGLU -lSDL_ttf -lm -Wall -DGL_GLEXT_PROTOTYPES -std=c++0x [source code files] -o [compiled executable file]
I’d get a bunch of “undefined references” for everything relating to OpenGL and SDL, pretty much. So the assumption being I’m missing a bunch of libraries I need (and used to have before I upgraded to 11.10 – thanks Canonical) to compile my C++ OpenGL code.
First, I needed to change how things are linked in the compile command, although why this worked on previous versions of Ubuntu is anyone’s guess. Compiler upgrade may be: -
g++ -g [Source code files separated by spaces] -o [Compiled executable file name] -lX11 -lXi -lXmu -lGLEW -lSDL -lGL -lGLU -lSDL_ttf -lSDL_image -lm -Wall -DGL_GLEXT_PROTOTYPES -std=c++0x
Next, I had to make sure the libraries were all installed: -
sudo apt-get install libsdl-ttf2.0-0 libsdl-ttf2.0-dev libsdl-image1.2 libsdl-image1.2-dev libsdl-mixer1.2 libsdl-mixer1.2-dev libsdl1.2-dev libsdl1.2debian-all xorg-dev libtool freeglut3 freeglut3-dev libglew1.5 libglew1.5-dev libglu1-mesa libglu1-mesa-dev libgl1-mesa-glx libgl1-mesa-dev libsdl-sound1.2-dev
Then you need to make sure your graphics driver can handle direct rendering through OpenGL with: -
glxinfo | grep direct
which should give you: -
direct rendering: Yes
You can check your OpenGL capabilities with: -
glxinfo | grep OpenGL
Now, you should be good to go with writing your own OpenGL programs under Ubuntu using SDL :-) If all else fails, the official Ubuntu wiki might help, although it seems a bit outdated. Be aware when setting your screen resolution in code that it matches your current screen resolution. This can be done via SDL with: -
const SDL_VideoInfo* screenInfo = SDL_GetVideoInfo(); int currentResHeight = (int)screenInfo->current_h; int currentResWidth = (int)screenInfo->current_w;
…and passing these numbers to your screen initialisation code. I guess it should be technically possible to choose a different resolution or switch the resolution back before exiting, but not currently under Ubuntu that I have been able to use. Not setting the screen resolution to the same as Unity’s resolution can give some very odd screen effects on exit of your code.
Usually you mount hard drives and USB devices automatically on boot using their device partition names in your /etc/fstab file, something like: -
/dev/sdb1 /home ext4 defaults 1 2
However, this won’t necessarily give you the mount points you expect, especially if your “/etc/fstab” file contains “/dev” devices that are USB external hard drives. This sometimes happened to me when I rebooted my server and found that the device usually mounted under “/home” was mounted in a different place defined in “/etc/fstab” simply because the boot process found the devices in a different order. So the contents of “/home” actually ended up mounted somewhere else, like “/usr/local/backup”. Not good.
This is because the devices under “/dev” are not unique to the hard drive or other device on boot – it’s simply ordered in the order in which your Linux system found them upon loading. However, every device attached to your system actually has a unique identifier to that piece of hardware called a UUID or Universal Unique ID. So you need to find a list of these UUIDs and the devices they relate to.
Under Red Hat-based systems, you can use the “blkid” command to get the UUID for devices. “blkid” is a command-line utility to locate/print block device attributes, including the UUID. If you run the command, you’ll see something like: -
/dev/sda1: UUID="d5428817-bfa9-466c-850d-42545dc06248" TYPE="ext2"
/dev/sdb1: UUID="01d0599a-2733-4779-bc01-50e7748e29eb" TYPE="ext4"
...
This will also usually work under Ubuntu or Debian-based systems. If not, finding out the UUIDs for your devices is a little more involved, but not much. You can use the “vol_id” command to find out the UUID for a specific device, but you have to go through all of them manually with a command like: -
sudo vol_id --uuid /dev/sdb2
Make a note of these UUIDs and then edit your “/etc/fstab” file with: -
vi /etc/fstab
under Red Hat systems as root and:-
sudo vi /etc/fstab
under Ubuntu systems (the only difference being already being the root user on Red Hat and using sudo to elevate your security in order to edit the file). You can now replace the “/dev/[device]” with the UUID like so:-
UUID=43813f50-0a19-40d1-9aba-7b345a78e695 /home ext4 defaults 1 2
This will then always load the specific device at the specific mount point, regardless in which the order of devices is found by the system.
If you’ve performed an upgrade from Ubuntu Linux 11.04 to 11.10 (which can have it’s own set of problems) and already have Google’s Chrome browser already installed, this won’t effect you. However, with a fresh install of Ubuntu 11.10, the first thing I do is fire up Mozilla Firefox to download Google Chrome instead.
This gives you a Debian package at: -
/home/[user]/Download/google-chrome-stable_current_[ARCH].deb
Debian packages are usually associated with the Software Center, which attempts to install the package. However, under 11.10, this merely throws up an “Internal Error” message and very little other information. Annoying.
Now, there are two solutions to this. Firstly, you could simply install the Chromium browser instead from Ubuntu’s repositories with: -
sudo apt-get install chromium-browser
Before you get worried, Chromium is simply the open source package of Google Chrome, minus the colourful logo and a few other minor changes. See the link for the differences, but honestly, the only major difference I can see is that the logo is a little different :-) Google account sync still works and everything. So, you could use that. However, if you insist on the “official” Google Chrome install instead, you need to first run: -
sudo apt-get -f install
…this fixes some sort of dependency problem with the google-chrome.deb package and Ubuntu’s Software Center (who the hell knows why?). You can then install Chrome properly with: -
sudo dpkg -i $HOME/Download/google-chrome-stable_current_i386.deb
…this should do it. I’m still playing with Ubuntu 11.10 and again, this was a weird annoyance I came across, although I’m actually using the Chromium Browser at the moment.
I upgraded my Ubuntu 11.04 netbook today to 11.10. I admit, it wasn’t a flawless upgrade due to (wat I assume) was server overload over at Canonical. I ended up with a partial install much to my annoyance – which took about half an hour to research and fix.
It was much faster and generally smoother once I got past that. I assume part of this was the use of Unity2D on my netbook. However, the upgrade necessitates a reboot eventually, and that’s where the whole OS just froze on boot with the message “Waiting for Network Configuration”. Hitting escape showed me this: -
Unable to connect to the system bus: Failed to connect to socket /var/run/dbus/system_bus_socket: Connection refused (oneiric)
…although I think this has something to do with DBus – which is a daemon which handles inter-process communication and initiation. Since Ubuntu has been moving from the tradtional UNIX sysVinit (the mechanism which handles how the initial and child processes of the Linux kernel start) to Upstart, these things sound related.
Anyway, what all this means is that somewhere along the line, things are looking in the wrong place (I think). Instead of process stuff like process id files being stored in “/var/run” (WTF? – Why?), it’s stored in “/run”. This makes sense for the network interfaces defined under “/etc/network/interfaces/run” which is actually a symlink to “/run/network”, hence the error.
When you get the “Waiting for 60 seconds more for network configuration” Ubuntu message in the GUI, you should at some point be able to open a terminal window with CTRL-ALT-F1 and log in as normal via the bash shell. Finally, a damned command prompt :-/
Delete the DBus directory first under “/var/run/dbus” which hold the process id file and some other stuff. This frees the lockup on reboot. Then move everything under “/var/run” to “/run” with: -
mv /var/run/* /run
rmdir /var/run
Verify the contents of “/var/run” is now in “/run”. Now create a symlink from “/run” to “/var/run” with: -
ln -s /run /var/run
To be safe, I also symlinked “/var/lock” to “/run/lock” with: -
ln -s /run/lock /var/lock
Once, I rebooted after this, I actually got to the GNOME login screen, which does look lovely under 11.10….ironically wasted beauty on my right now since I’m sure you’d be glad to see any GUI login prompt at this point in the upgrade circus. The next problem was that although I had already updated the system with: -
sudo apt-get update
sudo apt-get upgrade
…Ubuntu kept telling me to reboot because of a new kernel update via the little red icon to the upper right next to the new Me Menu (which I’ve not looked at yet). I eventually got rid of this by cleaning out the repositories with: -
sudo apt-get clean all
and rebooting yet again. The last problem was with power management, which tends to lock up my netbook in 11.10. However, once I turned this off (I don’t use it anyway), all was well. The boot freeze, which is obviously the main problem should never have got past Canonical’s Quality Assurance and testing procedures. Something somewhere along the boot process is still looking for something under sysVinit rather than Upstart on some systems, as apparently this has been a bug in LaunchPad before. That was from July, way before a major release that can freeze systems was sent on it’s way into the world. Yowza.
Anyway, I’m assuming this will be fixed at some point and really, when Ubuntu 11.10 does run, it runs much better than 11.04. It’s a nicer user experience than Fedora 15 on desktop (although that may change in time).
It’s just sad, because at a certain point in time, Ubuntu was pretty stable (although I think the differences from Red Hat are insane ;-)) and although Unity runs faster and (from an hour or two’s usage seems improved in most visible ways) it’s getting more and more unstable. Although, to be fair, I did have a rather rocky road from 11.04 to 11.10 because of the partial installation of the 11.10 repos. I’ll update my experiences with 11.10 again soon if anything interesting happens, but this should help anyone else with the same problem.
Dennis Ritchie, co-creator of UNIX and creator of the C programming language has died at the age of 70. His work on UNIX and C lead directly to pretty much everything you use a computer for right now. C is the computer language that powers video games, operating systems and applications that you all use every day (although it could be argued that C++ is used equally now, but that is basically an Object-Oriented C) If you’ve used Java, C++ or even JavaScript or ActionScript 3.0, you’ve used programming syntactic conventions invented by Ritchie.
The first program any budding programmer writes is the ubiquitous “Hello World” program, which simply displays the string “Hello world” to the display in whichever computer language you’re learning and is pretty much chapter one in any programming textbook. This stems straight from the definitive (and original) manual on how to use C, so you’ve Ritchie to thank for that too.
Basically his contributions to modern computer science spans pretty much everything we take for granted. UNIX lead to Linux and Apple’s OSX, all coded in C. Windows and OpenGL are implemented in C, as are device drivers, virtual machines – all manner of devices and software. His influence, while not well known to the general public, basically created the computer as we known it from the software side. He will never be remembered in the same manner as the late Steve Jobs as his work is invisible to most people, however his work without a doubt lead to the computer as you know it today. I really can’t overstate this enough.
Looks like your main() finally returned a 1, Dennis. You’ll be remembered by those of us who practice the art you helped create.
So, you’re running Linux on a desktop – by desktop, I mean with a GUI (let’s say GNOME or KDE or something) and you want to get started with Android development. Pure Android code is written in Java, so if you don’t know Java, you’ll need to learn that first – I’ll not be covering the syntax details of Java here.
Assuming you know enough Java programming to be dangerous, you’ll need the following to develop Android apps: -
- The Oracle JDK (Java Development Kit).
- The Android SDK.
- Eclipse IDE – available from your Linux distribution repositories or here.
- Eclipse Android Plugin – downloaded from within Eclipse.
While official sources state that the latest version of Eclipse (Indigo) will work just fine with the ADT and Android, I’ve had better luck with the majority of installs by using “Helios” instead. Your mileage may vary. If updates to the ADT plugin don’t work, try using Helios instead.
While you don’t need Eclipse or the ADT plugin to write Android apps, it’s heartily recommended and that’s what I’ll be covering.
Installing the Java JDK
If you’ve already got the JDK installed and are confident of your Java functionality, you can skip this part.
While there are RPM installers and such for the JDK download package, I’d recommend downloading the compressed generic Linux binary. It’s very easy to install and you can even make it play nicely with the OpenJDK if it’s installed on your system via the use of aliases.
Once you’ve downloaded the JDK, unzip the file with: -
gunzip jdk-7-linux-i586.tar.gz
tar -xf jdk-7-linux-i586.tar
You’ll end up with a directory called “jdk1.7.0″ or similar. If you want this to be for one specific user, create an “apps” directory under your $HOME directory and move the directory there, else “mv” the directory to somewhere like “/usr/local/jdk1.7.0″. For system-wide Java installs, I usually create a symlink to “/usr/local/java” as it’s more flexible as I can soft-link the JDK to difference versions. You can do this with: -
ln -s /usr/local/jdk1.7.0 /usr/local/java
Once this is done, it’s a good idea to set up a $JAVA_HOME environment variable. Some Java-based stuff uses this variable (The Caucho Resin application server, for example) and it never hurts to have it. You’ll also need to append the “bin” sub-directory which contains the actual Java compiler and interpreter to the system path. If you have the OpenJDK packages installed by default on your system, you can throw in some aliases to always execute the correct compiler (Oracle’s or the OpenJDK) explicitly or just remove the OpenJDK entirely if you like. If you’ve installed the JDK to be system-wide, you’ll need to add some things to the system-wide profile file (as root, natch, or sudo under Ubuntu).
sudo vi /etc/profile
Add the following lines near the bottom of this file after the system path environment variable has already been defined as we will be appending to it, not creating it. This varies between distributions, so have a look for anything mentioning the $PATH variable and put the following in below.
export $JAVA_HOME="/usr/local/java" # For system-wide Java location to the sym-link you set up earlier.
export $PATH="$PATH:/usr/local/java/bin"
If you’ve installed the JDK somewhere local under your home directory, you’ll need to edit your own $HOME/.profile file and add the above there instead of /etc/profile. If you’ve got the OpenJDK installed also or another version of the JDK for something else, you can set up your aliases to point to that location when you type either the “java” or “javac” command so you can be confident that you’ll be running the “official” JDK stuff rather than the OpenJDK. Or I suppose you could just use the OpenJDK, if you wish. There used to be a lot of talk about the official Sun/Oracle JDK being faster than the OpenJDK, but I don’t know if this still holds true.
vi ~/.bashrc
Add the following aliases, changing the locations to match your installed JDK location. As you can see, I’ve install mine under my own user account under “$HOME/Apps/java”. Remember that the tilde character (~) is simply shorthand for the $HOME environment variable which points to your home user directory.
alias java='~/Apps/java/bin/java'
alias javac='~/Apps/java/bin/javac'
Make sure you’re now running the correct version of Java and that any aliases are set up correctly by running the following. Keep in mind that you may need to re-login for your changes to take effect: -
java -version
If you get something like: -
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0)
Java HotSpot(TM) Server VM (build 17.0, mixed mode)
..you’re good to go and are definitely running the Oracle JDK. Next, we’ll have to install the Android SDK. Unlike Java, which I’ve given you the option to install system-wide or just under your user, we’ll install the Android SDK under your own user account. I’m going to put mine under “$HOME/Apps”, the same place I’ve chosen to install the JDK as a user.
Installing the Android SDK
Download the Android SDK from the above link. If this link no longer exists, Google will probably have brought out a later version and you’ll need to visit the official Android website and download the latest version for either 32-bit or 64-bit Linux, depending on your processor. Either way, once you have the install file, unzip it with: -
gunzip android-sdk_r13-linux_x86.tgz
Move the resulting directory to “$HOME/Apps/android-sdk_r13-linux_x86″ with: -
mv android-sdk_r13-linux_x86 ~/Apps
Now you’ll need to install a bunch of SDK versions and profiles for Android :-) Navigate to the “$HOME/Apps/android-sdk_r13-linux_x86/tools” directory and run the “android” command with: -
./android
This will show you a GUI of the Android Manager, as well as a list of any Android Virtual Devices (AVDs) for the emulator, which are essentially like hardware profiles for different devices that you’ll run on the emulator, but you won’t have any at the moment. Navigate down to “Available Packages” and check the box next to “Android Repository”. Then click on the “Install Selected” button and be prepared to wait a bit for the Android SDK versions to download :-)
Once that’s all done, you’ll need to create one or more Android Virtual Devices (AVDs) that the Android emulator will use for running your app. Based on your Android target version, you may need to create several of these. I usually just go for Android 2.2 for basic application development because most Android devices have had this version rolled out to them by their carriers by now.
You’ll need to give this virtual Android device a name, let’s just call it “Vanilla-2.2″, with a Target of “Android 2.2 – API Level 8″. Choose your virtual SD Card size and the screen resolution and click “Create AVD”. Make sure your AVD has a green tick by it, then close the Manager window, which will take you back to the command prompt.
Okay – you’ve installed the Android SDK.
Install Eclipse and the Android Plugin
While you can install Eclipse from the Eclipse website mentioned above, it’s better installed via your Linux distribution’s package manager as it’s included in almost all of them. Under RedHat/Fedora, install with: -
yum install eclipse eclipse-pm
and under Debian/Ubuntu, install with: -
sudo apt-get install eclipse
Once Eclipse is installed, load it up. Navigate to “Help” and down to “Install New Software”. To install the Android ADT plugin, we’ll need to add the Google Android resource URL to the list of available software repositories that Eclipse can check for updates and new plugins. Click on the “Add” button and add the following: -
Name: Google Android
Location: https://dl-ssl.google.com/android/eclipse/
Click “OK”. Back in the “Available Software” window, click on the “Work with:” drop-down box and choose your new Google Android repository. Under this should now appear the option to select “Development Tools”. Check this checkbox and click “Finish”. The Android development tools for Eclipse will now download. You’ll need to accept the bunch of legalese to continue to select everything to install and you may need to restart Eclipse during the process. Once all that is done, reload Eclipse and navigate to Window->Preferences and make sure Eclipse knows about the SDK level to use by selecting one that matches your AVD that you set up earlier. Now you should be able to see “File->New->Android Project” in addition to the regular “Java Project” creation option. If you don’t see it, click Project instead of Java project and select Android from the List. If it’s not there, you’ve made a mistake, so retrace your steps. But let’s assume all that went smoothly :-)
Good, we’re ready to write our first Android application, which due to tradition will be a simple “Hello World” app.
Under Eclipse, click File->New->Android Project and change the following details: -
- Project Name: HelloAndroid
- Choose an SDK target. If you’ve not install the Android SDK or ADT properly, this won’t show up and you’ll have to review. However, I’m going to choose “Android 2.2 by vendor “Google Inc.”, a platform of 2.2 and an API level of 8.
- The Application name will already be filled in for you. Create a package name for this application. While Java web applications no longer allow you to be the default namespace for a new Java project nor should Android. I’ll use the package name of “com.thenode.helloandroid”
- The Create Activity checkbox should already be checked and based on the Application Name, will be called “HelloAndroidActivity”
- The Min SDK Version, I’ve set to 8 to match the target Android version.
- Click “Finish” to set up your new Android project.
If you navigate down your package structure in the “src” directory to “HelloAndroidActivity.java”, you should see the following code.
package com.thenode.helloandroid;
import android.app.Activity;
import android.os.Bundle;
Public class HelloAndroidActivity extends Activity {
@Override
public void onCreate(Bundle savedInstancesState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Think of an Activity as a “window”. Your application can be made of many Activities (i.e. many windows). The Bundle parameter is the last saved state of the application. Because, remember, Android applications have to play nice with the rest of the activities of a phone, such as getting phone call. If your app isn’t explicitly closed, this will be used to save the application state while Android is doing other things. The other interesting thing to notice is “setContentView(R.layout.main);” line. The R.java source file is auto-generated and holds a list of all your app’s resources. For the moment, we’re just looking under “layout” which surprisingly holds an XML file called “main.xml”. This is the graphical user interface layout for this Activity (or window). While you can produce user interfaces programmatically as you would in Java Swing GUI Toolkit, for example, Google recommends using declarative user interface layouts like this when possible. It’s like laying out GUI components in HTML, to be honest. The important difference is that these components, though defined through XML, can be manipulated via code just like Swing. Cool eh?
Make sure your main.xml file looks like the below. Eclipse defaults to a graphical view of this file, but it’s not terribly functional and it’s quicker to just view and modify the XML source by clicking on the “main.xml” tab on the lower left of the Eclipse source code window.
< ?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"
>
<textview android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</linearlayout>
You’ll notice that we’re using a “Linear” layout. There are many layouts in Android, but this one simply that arranges its children in a single column or a single row. The direction of the row can be set by calling setOrientation(). You can also specify gravity, which specifies the alignment of all the child elements by calling setGravity() or specify that specific children grow to fill up any remaining space in the layout by setting the weight member of LinearLayout.LayoutParams. The default orientation is horizontal.
Within this, we’ve got simply one child component, which is a Text View, which is pretty much like a label. You notice that the text for this label is referenced under “@string/hello”, which doesn’t seem to mean much.
Remember that the major directories of your Android project are “src”, “gen” (the auto-generated R.java values for your XML files), “layout” and “res”. Well, where possible, Android strings should be stored under “res” in the strings.xml file. Things like button labels for example. This may seem cumbersome to start with, but trust me – if you ever want to support different languages, this will save your life. So, we need to change the text under strings.xml to change our “Hello World” example. So open that file in Eclipse and switch to text mode so you can see the XML code.
You’ll notice that this string we’re actually going to display has a name and a value. The name part is referenced by “@string/hello” as we saw above. We’re going to change the text to read “Hello world, this is my first Android app!”.
< ?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, HelloAndroidActivity!</string>
<string name="app_name">HelloAndroid</string>
</resources>
So change the hello String to…
<string name="hello">Hello world, this is my first Android app!</string>
Okay, save everything and click the green “play” button in Eclipse and run as an “Android Application”. This will start to fire up your AVD profile to run under the Android emulator. Be warned, firing up the Android emulator takes an age, so just leave it open in the background when coding – Eclipse will send each of your updated “apk” programs to the emulator each time you run it within Eclipse. Or, if you actually own an Android phone, you can follow the directions here to use an actual physical device hooked into your Linux machine via USB to code against rather than the dog-slow emulator.
You should now see your “Hello World” Android application running :-) I know we didn’t cover much in terms of Android programming, but if you’re hungry for more, I can recommend this book, “Hello Android” by Ed Burnette which goes through the basics of Android programming very well indeed.
UPDATE 17/09/2011: Some people are experiencing problems installing the ADT through Eclipse, the error being something along the lines of missing dependencies. This is because, while you installed Eclipse through your distro’s software repositories, they sometimes don’t include the Eclipse update sites in the installation, so Eclipse can’t get additional packages that are needed. I’ve only experienced this under Ubuntu, but it may effect other distributions too.
To fix this, you need to make sure Eclipse can update itself with it’s own repository, which some distributions have neglected to include when installing Eclipse with their package manager.
So you need to add them. Load Eclipse, click on “Help-> Install new software -> Add” and then for v3.7.x (which is the latest I just downloaded – named Indigo) in the name box enter Indigo and in the URL box enter “http://download.eclipse.org/releases/indigo”.
See below if you’re using a different version of Eclipse.
Perform an update of Eclipse under “Help->Check for updates” and update and restart Eclipse. Once you’ve done this, attempt to install the ADT developer tools again.
If you are using other versions of Eclipse you need to change the name label and URL for the Eclipse updates to the following: -
v3.7.x Indigo – http://download.eclipse.org/releases/indigo
v3.6.x Helios – http://download.eclipse.org/releases/helios
v3.5.x Galileo – http://download.eclipse.org/releases/galileo
v3.4.x Ganymede – http://download.eclipse.org/releases/ganymede
UPDATE 30/10/2011: I’ve had much less trouble with Android SDK updates (with the ADT Eclipse plugin) via Eclipse with “Helios” rather than “Indigo” for both Windows and Linux. Go figure.
