Tuesday 21 May 2013

Hello World : Android NDK : Eclipse

Introduction


This post is about using Android NDK (C/C++) for your first Hello World application. We'll be using the sample application in NDK distribution to kickstart. We'll also be looking at the essential changes to get C/C++ code to compile and run from Eclipse IDE easily.

While developing pure C/C++ applications are possible on Android, it is good to get a feel of Java based development in the first place. Either that or if you are interested in developing using Java alone, you may head to one of these posts first:


Why an IDE for C/C++? Why not command-line only?


Speed

Being a C programmer with more than a decade experience in embedded systems, I got used to command line tools and editors. Indeed those skills are very useful. While we'll explore coding for Android SDK+NDK from command line later, do give Eclipse IDE a couple of hours for native development. Am a convert at least when it comes to Android native (C/C++) development; IDE accelerates development exponentially. Trust me.
You'll see and appreciate the advantages of indexing and auto-completion feature in following sections.

Mix


Other than that, we've to admit that not all Android APIs are officially exposed through NDK. Unofficial hacks may work on specific firmware and aren't future proof. While we can create pure native apps, from time to time, we will need to make calls to Java world to get things done.
For instance, game apps could remain 99.99% native (C/C++) but the last 0.01% might involve and Java (+JNI) ... say to check license with Google Play servers, to launch an intent to open a webpage, to get pre-authenticated tokens (without password entry), showing customized version of google maps etc. So, other than accelerating C/C++ coding with the NDK, the IDE will also help in mix cases involving a bit of Java.

Compared to the initial NDK releases we've come a long way. The first version didn't even support pure native apps. Gradually [ very very slowly :( ] things are improving in the NDK; we now have partial support for audio, video etc. But it still makes a lot of sense to code in NDK (pure or mixed) where the app involves heavy computation (eg. game physics) or when porting from other platforms (eg. iOS).

Interactive App / Game / No GC!

Any decent/serious 3D (or even 2D) game should consider avoiding Java to the maximum extent possible. One could spend most of their dev time ensuring that there are no allocations in Java. But still there will be places where the system will kick in the garbage collector (GC) and your game will see a jank, i.e., few frames taking twice/thrice the usual time to refresh and the input/touch takes twice as long to effect. These GC calls can't be explicitly timed by the developer and the game experience is terrible.

Number crunching

Even non-interactive applications involving heavy number crunching benefit from native code as it has less overhead, has better performance and consumes less power for the same task.

When to avoid?

However the bridge between Java and native (C/C++) world is a bottle neck. Passing data across infrequently and processing for a long time in native code is a good use case. But frequently exchanging large chunks of data will involve so much overhead smuggling across the boundary that you'll lose the benefits of going native.

Ready?!

Download and Install the NDK

Follow instructions on http://developer.android.com/tools/sdk/ndk/index.html to download and install the NDK.

It is typically just a zip or compressed tar-ball that you extract on your PC/Mac to your favorite folder. Simple.

Eclipse CDT

Assuming you've already run Hello World using Eclipse as suggested in the introduction, you already have a setup of Eclipse IDE suitable for development using NDK as well.

If eclipse was installed using Android ADT Bundle, it would almost certainly have support for C/C++.

Verify that using menu Eclipse > Preferences. You'd see a C/C++ section as shown in the screen shot.


Tip: If you don't find it, don't fret, you may still upgrade existing eclipse to support C/C++. All you need to do is install CDT plugin as suggested in http://www.eclipse.org/cdt/downloads.php
This usually involves these steps:
From menu go to Help > Install new software > Add and key in the latest repository URL you found on the CDT download page (something like  http://download.eclipse.org/tools/cdt/releases/juno)
Wait for it it refresh, check most of the components, agree to licenses, choose to install and wait for it to finish. 

Running the Sample

Here are the steps to run the sample application.
From menu File > New > Project, choose "Android Project from Existing Code".
In the resulting screen, browse to the path of the sample application, hello-jni, in the ndk folder that you just downloaded and extracted.

JNI stands for Java Native Interface. This is the magic glue that lets Java and Native code interact.

Open the AndroidManifest.xml file to make a few minor changes and ensure that it looks so:

 <?xml version="1.0" encoding="utf-8"?>  
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
   package="com.example.hellojni"  
   android:versionCode="1"  
   android:versionName="1.0" >  
   <uses-sdk  
     android:minSdkVersion="9"  
     android:targetSdkVersion="17" />  
   <application  
     android:allowBackup="true"  
     android:icon="@drawable/ic_launcher"  
     android:label="@string/app_name" >  
     <activity   
       android:name=".HelloJni"  
       android:label="@string/app_name" >  
       <intent-filter>  
         <action android:name="android.intent.action.MAIN" />  
         <category android:name="android.intent.category.LAUNCHER" />  
       </intent-filter>  
     </activity>  
   </application>  
 </manifest>  



  • We've changed minSdkVersion to 9. Which will be relevant eventually when we wish to do pure native applications (no Java component). 
  • We've added a targetSdkVersion. Make sure, it is the same as the one you are compiling against (Project > Properties > Android > Project Build Target > API level). Latest was 17 in mid 2013. 
  • We've pointed the app to use an icon. If the icons are missing in res/drawable* folders, copy an icon for each drawable level (drawable-hdpi, drawable-xhdpi, ...) from some existing project say "Hello World" we generated using wizard in the SDK example
  • We've also removed debuggable tag and allowed backup. 
Hope these changes aren't required in future NDK releases. The samples should already have these in place. 



Trying to run the application at this stage will fail unless C/C++ build is configured. The error would look something like:

 W/dalvikvm( 6622): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/hellojni/HelloJni;  
 W/dalvikvm( 6622): Class init failed in newInstance call (Lcom/example/hellojni/HelloJni;)  
 D/AndroidRuntime( 6622): Shutting down VM  
 W/dalvikvm( 6622): threadid=1: thread exiting with uncaught exception (group=0x40c491f8)  
 E/android.os.Debug( 191): !@Dumpstate > dumpstate -k -t -n -z -d -o /data/log/dumpstate_app_error  
 E/AndroidRuntime( 6622): FATAL EXCEPTION: main  
 E/AndroidRuntime( 6622): java.lang.ExceptionInInitializerError  
 E/AndroidRuntime( 6622):      at java.lang.Class.newInstanceImpl(Native Method)  
 E/AndroidRuntime( 6622):      at java.lang.Class.newInstance(Class.java:1319)  
 E/AndroidRuntime( 6622):      at android.app.Instrumentation.newActivity(Instrumentation.java:1026)  
 E/AndroidRuntime( 6622):      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1883)  
 E/AndroidRuntime( 6622):      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1993)  
 E/AndroidRuntime( 6622):      at android.app.ActivityThread.access$600(ActivityThread.java:127)  
 E/AndroidRuntime( 6622):      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1159)  
 E/AndroidRuntime( 6622):      at android.os.Handler.dispatchMessage(Handler.java:99)  
 E/AndroidRuntime( 6622):      at android.os.Looper.loop(Looper.java:137)  
 E/AndroidRuntime( 6622):      at android.app.ActivityThread.main(ActivityThread.java:4507)  
 E/AndroidRuntime( 6622):      at java.lang.reflect.Method.invokeNative(Native Method)  
 E/AndroidRuntime( 6622):      at java.lang.reflect.Method.invoke(Method.java:511)  
 E/AndroidRuntime( 6622):      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:978)  
 E/AndroidRuntime( 6622):      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)  
 E/AndroidRuntime( 6622):      at dalvik.system.NativeStart.main(Native Method)  
 E/AndroidRuntime( 6622): Caused by: java.lang.UnsatisfiedLinkError: Couldn't load hello-jni: findLibrary returned null  
 E/AndroidRuntime( 6622):      at java.lang.Runtime.loadLibrary(Runtime.java:365)  
 E/AndroidRuntime( 6622):      at java.lang.System.loadLibrary(System.java:535)  
 E/AndroidRuntime( 6622):      at com.example.hellojni.HelloJni.<clinit>(HelloJni.java:64)  
 E/AndroidRuntime( 6622):      ... 15 more  
 W/ActivityManager( 191):  Force finishing activity r.intent.getComponent().flattenToShortString()  

That had to be expected if C/C++ code isn't compiled. The VM is looking for our C/C++ module's library (hello-jni.so) which is missing. 

Configuring Eclipse for NDK (C/C++)

First of all, point Eclipse > Preferences > Android > NDK to the install folder.

The project is still a Java project as far as Eclipse is concerned.
Android tools have a way to convert project to NDK projects but the support is incomplete. So we'll not take that route.
To inform it about the C/C++ nature, right click on the project's top folder and choose New > Other.
In the resulting screen choose "Convert to C/C++ project"
Choose "Makefile project" in the next screen. If the option to choose toolchain shows Android GCC, go for it. Otherwise just leave it at "Other toolchain" for the time being and fix the toolchains later.


Right click on the project's top folder and see Properties > C/C++ build. Does it show ndk-build as the default build command?
If it doesn't, untick "Use default build command" and enter custom command pointing to ndk-build in your ndk folder. Also untick "Generate make files automatically" if it was ticked.


Cross fingers and build/run the app.
If it still complains of ndk-build not being found in path, go to Eclipse > Preferences > C/C++ > Build > Environment and "Add" PATH pointing to your ndk install folder. That's where ndk-build command resides.


Observe that we've changed Preferences instead of Project properties. This change would reflect on all projects in this workspace.
(Of course if it still fails, go back to our method of mentioning ndk-build along with path explicitly.
On running the app you'd see a "Hello from JNI" message.


Eclipse Indexer Workarounds for Android NDK


Often Android ADT plugin for eclipse breaks how NDK components work. The only way out is to avoid Android toolchain and manual configuration of build, paths and symbols.




  • Choose your project, go to Project > Properties >  C/C++ Build > Tool Chain editor
    • toggle "Display compatible toolchains only" checkbox
      • that would show you toolchains other than Android's own
      • choose Linux GCC or something that can run on your dev machine
      • leave the Current builder at "GNU Make builder"
  • apply and then, go to Project > Properties > C/C++ Build
    • instead of default build command, provide full path to ndk-build in the ndk directory
    • ensure "Generate makefiles  automatically" is not ticked
  • in project properties or eclipse preferences (if adding to all configuations) 
    • set indexer to use active build configuration
  • under C/C++ General > Paths and symbols > Symbols, add
    • __ANDROID__ with a dummy true value like 1 for all configurations and languages
  • add following build variables and environment variables
    • CFLAGS =-DANDROID -D__ANDROID__ -D__arm__=1
    • CXXFLAGS =-DANDROID -D__ANDROID__ -D__arm__=1
    • CPPFLAGS =-DANDROID -D__ANDROID__ -D__arm__=1
  • under C/C++ General > paths and symbols > Includes, add
    • these for all configurations (assembler, GNU C and GNU C++) 
    • (see Update below for a longer list)
      • /Users/rajesh/ndk/platforms/android-9/arch-arm/usr/include
      • /Users/rajesh/ndk/sources/android/native_app_glue
      • /Users/rajesh/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.4.3/include
    • additionally for c++ in specific, if using STL ask for a version of STL include one of the stl headers too headers in path
      • /Users/rajesh/ndk/sources/cxx-stl/stlport/stlport
  • (Ensure those paths are valid and contain some headers)
Update: ... with the added support for renderscript, ndk_helper, ... the set of paths I include now have changed to the following
  • /Users/rajesh/ndk/platforms/android-19/arch-arm/usr/include/rs/cpp
  • /Users/rajesh/ndk/platforms/android-19/arch-arm/usr/include/rs
  • /Users/rajesh/ndk/sources/cxx-stl/stlport/stlport
  • /Users/rajesh/ndk/sources/cxx-stl/gabi++/include
  • /Users/rajesh/ndk/platforms/android-19/arch-arm/usr/include
  • /Users/rajesh/ndk/platforms/android-19/arch-x86/usr/include/rs/cpp
  • jni
  • /Users/rajesh/ndk/platforms/android-19/arch-x86/usr/include/rs
  • /Users/rajesh/ndk/platforms/android-19/arch-x86/usr/include
  • /Users/rajesh/ndk/platforms/android-19/arch-mips/usr/include/rs/cpp
  • /Users/rajesh/ndk/platforms/android-19/arch-mips/usr/include/rs
  • /Users/rajesh/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.6/include
  • /Users/rajesh/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.6/include-fixed
  • /Users/rajesh/ndk/platforms/android-19/arch-mips/usr/include
  • /Users/rajesh/ndk/platforms/android-19/arch-arm/usr/include/machine
  • /Users/rajesh/ndk/platforms/android-19/arch-mips/usr/include/asm
  • /Users/rajesh/ndk/sources/android/native_app_glue
  • /Users/rajesh/ndk/sources/android/ndk_helper


Important: Only with the builder and indexer working together, will you realize the true capabilities of native code development on Eclipse. Hope Android tool developers fix the issues and hope it works out of the box. But till then, do take the extra step the day you run the first NDK app and you won't regret. Given details in this page, and may be some help from comments here or stackoverflow.com you'll get it working within a few minutes.

Error checking apart, it helps with auto complete feature and will at least double your coding speed
Ctrl+space and Ctrl+dot can do wonders in Eclipse. Auto completion apart, it can assist with arguments to a function and navigation. Ctrl+click, say on jobject, will take us straight to jni.h where it is declared. Further, where sources are available, we can navigate to the respective definition with the same Ctrl+click on the function declaration. Return with Ctrl+{ or go forward again with Ctrl+}. Of course all these key mappings can be customized in Eclipse>Preferences.

Explore the code


HelloJni.java


In src>...>HelloJni.java, you'll find a line that loads our native library using

static { System.loadLibrary("hello-jni"); }
This happens whenever the library this Java class is loaded even before the constructors are called as the scope is static

Find declaration of a native function in this class
public native String  stringFromJNI();

On a call to this function, from java, if it is implemented in native code (that is now loaded and readily available from hello-jni.so), the respective native function will be called. 


hello-jni.c


In jni>hello-jni.c, you'll find the function with a weird long name

jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) {
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}

Observe that the name is Java followed by the package name, the Java class name and the function name itself separated by underscores. 

If this looks ugly to you, you can use a function called RegisterNatives to register many functions with the VM with custom names in a special function called JNI_onLoad(). We'll see that in subsequent projects. 

While that will help avoid the weird name, we'll still have to deal with JNIEnv and jobject. Observe how the env is helping us return a string suitable for consumption by the Java end. 

Android.mk


Finally we must explore Android.mk. This is the equivalent of make file for android native modules. Each native module (typically organized in sub-folders in jni), will contain such a file. 

  • LOCAL_PATH := $(call my-dir)
    • stores the current directory location in LOCAL_PATH
  • include $(CLEAR_VARS)
    • clears all variables that might be set from a previous module build (observe that LOCAL_PATH is stored before a call to this)
  • LOCAL_MODULE    := hello-jni
    • the name of the resulting library will be libhello-jni.so (if shared) or libhello-jni.a (if static)
  • LOCAL_SRC_FILES := hello-jni.c
    • the source files (C/C++) that need to be build. Headers are not provided here. 
  • include $(BUILD_SHARED_LIBRARY)
    • this ensures that make file code to build shared library becomes part of this make. 


There are many options eg. you could build static instead of shared library with one word change (BUILD_STATIC_LIBRARY), see ndk/docs directory for documentation on Android.mk and many other aspects of the NDK. Read introduction parts of each page there right now but use that as reference than a book to read entirely right away. 

Also go through JNI Tips on official android site along with code. 


While this was perhaps, the simplest example possible, explore each of the sample apps in the NDK (perhaps in the order shown here)
  • hello-jni: Just display a hello string from Java fetched from native C code
  • test-libstdc++: This example demonstrates how to useAndroid's implementation of libstdc++. Basically shows what to do in Application.mk and Android.mk files to use the library. 
  • two-libs: Shows how to implement multiple libraries and make calls across these libraries. The call is just to add two numbers. 
  • native-activity: This is the place to start if you wish to entirely avoid Java to the extent possible and code purely in C/C++. Requires minimum SDK version to be 9. The example creates a OpenGL ES 1.x surface and fills the screen with color depending up on the point on screen touched by the user. This example avoids java src folder entirely!
  • bitmap-plasma: This example does processing of a plasma gradient in native code but the bitmap is displayed using Java. This also shows how a specific feature of NDK helps access bitmap data from native code easily. In absence of AndroidBitmap extensions to the NDK, passing around the bitmap and associated details was a bit of a hassle. 
  • native-plasma: This example tries to do the same as the bitmap plasma example but through pure native activity. Both processing and display are done in native code. The most fascinating aspect of this example is the way it accesses the display. It draws directly to the native window without intermediate layers; ie., no OpenGL ES etc. Just a simple color data buffer dump. Such raw access is useful for the platform developers (not app developers). 
  • hello-gl2: This example shows basic use of OpenGL ES 2.0 based graphics capabilities from native code. Just displays a green triangle in flickering (dimming and brightening) gray background. 
  • gles3-jni: Similar to hello-gl2, this showcases OpenGL ES 3.x instead. 
  • hello-neon: New ARM architecture based chips optionally support a faster instruction set codenamed NEON along with the older instruction. This example shows how to use this specific sub-architecture. Implements an FIR filter and times its performance.
  • module-exports: This example demonstrates the use of module exports feature (LOCAL_EXPORT_CFLAGS and other such variables). Three modules are defined:
    • foo exports its include directory and a linker flag and is a static library
    • bar simply uses foo, as a static library and builds itself as a shared library
    • zoo uses bar, also resulting in a shared library
  • native-audio: Shows how to play audio using OpenSL ES from native code. Till 2013, very few hardware supported this feature properly. 
  • native-media: Shows how to play video using OpenMAX AL form native code. Till 2013, very few hardware supported this feature properly. 
  • san-angeles: This example is an Android NDK port of a very popular demo app that showcases graphics capabilities using pretty tiny code for such output. 
  • HelloComputeNDK: Shows a simple example of using renderscript (RS) from NDK. Turns a bitmap to monochrome using a RS call from NDK which is in-turn invoked from Java. 
  • Teapot, MoreTeapots: These two examples show the generic OpenGL teapot example. What is special about this is the inclusion of NDKHelper. NDKHelper's sources are part of NDK download (ndk/sources/android/ndk_helper) and contain bunch of (currently undocumented) files to ease development of native_activity apps and OpenGL shader based apps. This can improve to a game engine in the future. 

Enjoy!


Hello World : Android : Eclipse

Introduction

This page is about using Eclipse IDE to write your first Hello World app on Android.

Optional diversion: Android officially supports development using IntelliJ IDEA based IDE called Android Studio. It is less bloated but as a consequence incomplete in supporting several Android development aspects. For instance we'll eventually use Eclipse to code in C/C++ (Android NDK) which can't be done using Android Studio (in 2013). If you aren't going to be concerned about completeness, Android Studio even in its preview state is pretty good for Java based application development on Android. See this post ("Hello World Using Android Studio") about Hello World using Android Studio. 

Download, Install and Start

Make sure you have JDK6 installed on your system. (Use a google search like this to get it).

Follow instructions on http://developer.android.com/sdk/index.html to download and install the Android ADT bundle.

New Project


Lets create a new project using the inbuilt wizard.

Start Eclipse and point to some workspace.
 Wait for it to finish loading.
 Close the welcome screen using the X next to "Welcome".
 You'd probably end up with a blank perspective.
You can customize the view to your needs from menu Eclipse > Preferences. I like larger font and changing one setting makes it larger on most editors. (General > Apperance > Colors and Fonts > Basic > Text Font).
Consider changing Android > Logcat > Font as well.
Feel free to tune key mappings (General > Keys) etc to your liking.

Tip: At menu Eclipse > Preferences > Java > Compiler > Compliance level, ensure that Java 1.6 is chosen.

Now lets start the wizard using menu File > New > Project > Android > Android Application Project
Enter some name for the application and make sure your package name is unique. If you own some domain say mydomain.com, then your package could be com.mydomain.helloworld.
While uniqueness isn't of concern for our Hello World project, it will be important for an application that needs to be published. Google Play (Android Market) distinguishes apps by the package name only.

Next, I've  changed project location in the screen shot but isn't necessary.

Now click "Next" button to be taken to a screen to choose an icon. Default is good enough for Hello World.
Click "Next" button again and you'll be presented with a list of activity types. Here again, the default choice (Blank) is good enough for our Hello World project.
Applications in Android show screens or pages for the user to interact. Those belonging to a single sort of activity are called an Activity. Our Hello World project is just going to show a single screen with "Hello World" written on it. Call such an activity what ever. Default name for the first activity is MainActivity by this wizard, and is good enough for us.
 The project is coded and ready! Lets anyway get some housekeeping tasks done before executing it.


Android SDK Manager


Since this is the first time this IDE is being used, choose to download few more essential pieces using Android SDK Manager. There is a green Android (bugdroid) icon in the toolbar on top.

Tip: If you can't find that button, start it from command line using
android sdk


When Android SDK Manager settles down with a list of packages, choose (tick) the components of the latest API that aren't yet installed. Similarly scroll down and choose all the "Extra" components that aren't yet installed and then click the "Install ... packages".

That will throw a dialog with license information.

Read each if you must before accepting.



Accept using "Accept license" radio button on bottom left.

And then choose to Install.

Download may take a long time to finish. Don't close that window. But return to the IDE with Cmd+Tab or Alt+Tab or whatever but don't close that Android SDK Manager window.

















Project Structure

Lets explore the main content of our project





(If you aren't following this with your own IDE, click the image to see a larger image with readable text.)

Lets see what's in the 'HelloWorld'.
  • java: Java files. In our case just the MainActivity.java created using the wizard.
  • res: Resources. This holds all resources like drawables (icons, background images), strings, styles, etc. 
    • We are encouraged (but not required) to provide drawables for different screen densities. And hence ic_launcher.png is available as different sizes in those drawable-... folders. 
    • Similarly values (eg. style) can be per API type. Earlier APIs may not support Holo theme for instance. 
  • AndroidManifest.xml: This is the file that tells the Android system about the application. 

The source code (Java) is compiled into class file(s) and zipped along with these resources and the manifest to produce a final single file called the APK (Android Application Package). Of course there are a few more pieces than just these. But this level of understanding will do for now.

Execution

Now to run the application we'll need an android device or an emulator instance.

Or we can create an Android Emulator instance to run our app on. Skip the section about AVD and emulators if you are anyway using on an Android device (phone/tablet).

Execute on Device

If you have an Android device, plug it in to the development machine (running the IDE) with USB.
On the device go into

Settings > Security > Unknown sources

(On devices running Gingerbread or earlier firmware: Settings > Applications > Unknown sources)

And check that option to allow installation of apps from sources other than the primary app store on the device. In this case our Hello World over USB.

Now click the button in the toolbar that looks like a play button to run the application.




Choose to run as Android Application.

That would bring a dialog with all connected devices and emulator instances.


When running on a device (phone/tablet) make sure, "Choose a running device" radio button is selected and then choose one of your connected devices and then click the OK button.


That's it! Your device's screen should light up with your "Hello World"!!!

Continue reading the DDMS>LogCat section (below).






















Execute on an Emulator Instance


Android supports virtual devices running almost the same firmware as a regular device to be emulated on the development machine.

The AVD manager's button is right next to the Android SDK Manager button in the toolbar on top. Click that to launch the AVD (Android Virtual Device) Manager.


Tip: If you can't find that button, start it from command line using
android avd




Create a new AVD instance using the manager and provide some details.


This screen lets us choose some quick values.

Instead of writing every detail by hand, we can choose the type of device to emulate and the boxes are pre-filled with corresponding details.

In particular we wish to use Google API and enable Snapshot.

Google API instances are useful in running applications using Google Maps API etc on top of regular Android APIs.

Using the snapshot feature, we can reduce the startup time from several minutes to couple of seconds except for the first run.

We'd also like to "Use Host GPU" feature, which allows smoother graphics on the emulator by utilizing GPU on the development machine. However at the time of writing this, the two options were mutually-exclusive (and we can't forgo Snapshot feature).

We may of course edit it further.

For instance the emulator by default doesn't seem to care about the camera.


We can choose to use the webcam on our development laptop for both the front and back camera.

Several such customizations are possible.

Now choose the AVD created and click on the "Start.." button.






If this is were not the first time, we'd have chosen to "Launch from snapshot" as shown.

DON'T DO THIS THE FIRST TIME.

Have shown this dialog before the dialog for first time launch to help those who won't read the text and would wish to run forward clicking buttons as shown in the screen shots. 

First time select "Save to Snapshot"
















IMPORTANT: In the dialog shown when running the AVD (emulator instance) for the first time, remember to save to snapshot. This will help us launch from the snapshot next time onwards.

Launching takes several minutes the first time, since there is no old snapshot to start with. Take a short break. Be patient.


When you get back you might find a dark screen as the device is emulating sleep mode using dim screen.



Patience!!!
Emulating Sleep Mode without lock screen



You didn't expect the emulator to turn your laptop's screen to a touch-screen, did you? The emulator can use what is available on your laptop and fake other things like 3G, GPS etc. Some of these can be fed fake values through command line interfaces.


Click (with mouse/touchpad on laptop) and follow the suggestions on screen in the first launch.



Suggestion: From settings, lets do one small thing before shutting it down to save a clean snapshot. Add a gmail (Google) account as it will come in handy for other application tests later.

Add a Gmail/Google account before saving clean emulator state in a snapshot

Now we may Exit the emulator. After going through all the pain and time to start the emulator? Nuts! Yes I am but this time I have a reason. Current state of our emulator is clean and ready to consume applications. Like a freshly booted phone from factory with just one account added. Such an instance is very useful in testing applications. So exiting will help us save a clean state snapshot which we'll use for several months (if we remember to avoid overwriting the snapshot on every fresh launch).

So yes, please close that return to the AVD Manager and choose the one already created by us and click the "Start ..." button again. Don't launch as yet.


From now on always use "Launch from snapshot" and don't wipe. 

This time, remember to Not check "Wipe user data" or "Save to snapshot". Just check "Launch from snapshot" and the emulator should be up and running within a few seconds unlike in our first run.


Now that the one time job of preparing a clean emulator snapshot is done and it is ready, we are happy to execute our Hello World project.

Click the button in the toolbar that looks like a play button to run the application.





Choose to run as Android Application.

That would bring a dialog with all connected devices and emulator instances.


When the emulator is already running, make sure, "Choose a running device" radio button is selected and then choose one of your connected devices and then click the OK button.

(Otherwise, we can create or launch existing AVD from here as well). This too basically just uses the same AVD Manager.








That's it! Your device's screen should light up with your "Hello World"!!!





















DDMS > LogCat


We won't be going into details of debugging etc. But it is worth a mention that anything logged in the application can be viewed through DDMS tool. Eclipse can show different perspectives.




From menu Windows > Open Perspective > Other choose to open DDMS




Choose the device of interest from the list on top left.

If that list is empty, killing and restarting adb from command line may help. Use this:
adb kill-server; adb devices

At the bottom of the screen there is a section for logcat and console output. Console output shows the details of build process etc.

LogCat shows the content logged by android applications running on a device.

The Code

Now lets look at the code behind wizard generated Hello World app we've already run.

MainActivity class in MainActivity.java file extends Android Activity. It overrides onCreate() method with a custom call. The custom call starts with a call to the parent class' (Activity's) onCreate(). Then it sets the layout to show on the screen whenever this activity is launched.




The layout is referenced using 'R', a resources class, that is generated by the build system. R has a reference field for every Android resource in use from this project's resource directory.


This layout is the graphical representation of the XML file under res/layout... folder of our project's main directory (we discussed of earlier). This is called the design view of the layout. Click on "Text" next to "Design" tab at the bottom of the layout to see the corresponding XML document.

Now that's where the string "Hello World" came from:
   string.xml > activity_main.xml > MainActivity.java
using these respectively:
   hello_world > @strings/hello_world > setContentView(R.layout.activity_main)

Quick Exercise 0:
Edit the value of hello_world in string.xml (while keeping the same name).
Run the app again and your change will be reflected. 

Quick Exercise 1:
Edit MainActivity.class to log something using Log.d(String, String).
Say
public static final String TAG = MainActivity.class.getName();  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Log.d(TAG, "OnCreate() was called");  }

Run the app and observe LogCat. Do you see a debug log with your log message? 

One last piece that must be said about the simple project is about the AndroidManifest.xml file. Lets open it. Open project view (if hidden in vertical tab on the left gutter of the window) and scroll down to find AndroidManifest.xml file in main sub-section.

It is from this file that the Android system gathers that MainActivity needs to be run when this application is launched. Remember, there can be several activities in the same application. The ones that can be launched by the system are given a special category "android.intent.category.LAUNCHER".

Others are custom or "android.intent.category.DEFAULT". Such activities are typically invoked by one of the launched activities.

In our simple Hello World app, there isn't much else, well other than icon, name and most importantly the unique package name given in the wizard.

That would be it for now.