Friday, December 27, 2013
Spring Messaging w/JMS and Nevado
Thursday, September 5, 2013
WxTrax: Example Android 4.x Application Using Android Studio/Gradle
- Employs Android 4.x constructs (i.e. loaders, fragments, etc)
- Plays nice w/Android Studio (currently on preview version 0.2.6)
- Builds using Gradle (currently 1.7)
- Is decomposed into an application and a library
- Uses Google Maps V2
- AppWidget example
- Weather stations and observations are stored in SqlLite using a ContentProvider
The US National Weather Service (NWS) makes weather reports available as a XML based web service. Hourly weather observations are usually performed by automated stations colocated at airports, so the observations use the IATA location code (i.e. KPDX for Portland, KSEA for Seattle, KSFO for San Francisco, etc). To obtain the current observation for Los Angeles you would use the URL http://www.weather.gov/xml/current_obs/KLAX.xml
WxTrax will allow you to specify stations of interest and collect these weather reports for you. WxTrax can also display a Google Map w/the station location.
There is also the concept of a "favorite" station which always displays the most recent report on the "splash" page. If you display the associated AppWidget, the favorite station temperature is given.
Now on to the sources...
WxTraxLib contains code I wrote in 2010 for the first version of this application. There is no user interface code here, but it does contain the network support, weather observation collection, XML parser, ContentProvider, etc. I like to decompose my applications into modular components like this. The user interface tends to change quite a depending upon the product team while the supporting components tend to be more stable. Breaking a project into modules allows for reuse across multiple products and makes for easier testing of the "headless" pieces.
WxTrax2 is new, freshly updated to use Android 4.x components. All the UI components reside in this module, and depends upon WxTraxLib.
MainActivity exists to host fragments and handle the communication logic between them. Fragment switching is performed within TabHelper. You can add a station from the menu and a dialog will accept your command. StationListFragment will display the known stations. Selecting a station will show the collected observations (via ObservationListFragment). A long press on a station row will allow you to delete a station or select it as the "favorite" station. Selecting the "map" fragment allows Google Maps to display station locations.
Monday, September 2, 2013
Android Fragment Tour - Encore
Sunday, August 18, 2013
Android Fragment Tour
- Use of Android fragments (i.e. Fragment, ListFragment, DialogFragment or PreferenceFragment.
- Navigation between fragments and activities
- Use of the ActionBar, TabListener and menu support.
- Use of Custom ArrayAdapter
- Use of Custom CursorAdapter
- Using a ContentProvider/ContentResolver and Loader
- Use of maven
At application start you should see these:
|
|
|
|
Tab 2 illustrates a simple scrolling list of US states implemented as a ListFragment (source) with a resource (source) for the data source. A short press on a row brings up a detail view (source) and a long press prompts for delete. Short/long press interaction requires the use of a custom listener (source) to dispatch a request to MainActivity (source) for service. The delete is not actually performed, but does provide an opportunity to illustrate the use of a PreferenceFragment (source)
Tab 3 is another ListFragment (source) example, this time w/a custom ArrayAdapter (source) and multiple row types (you can see from the above image there is a simple row w/a hex string and a more complex row w/radio buttons). The data source for Tab 3 comes from a ContentProvider (source) whose values are randomly generated at application startup (source). One final feature of this example is that it employs a list header (source) and footer (source). The footer contains a EditText and Button widgets which can be detected within ThreeFragment.java (source)
Tab 4 is yet another ListFragment example (source), this time w/a custom CursorAdapter (source) which employs a Loader fed from the ContentProvider (source). As shown in the illustration, the row type consists of an image and a string.
All of these Fragments are "owned" by MainActivity (source) which also provides the ActionBar at the top of the display. The ActionBar provides the tabs which are used for navigation between Fragments. The tab navigation code resides within TabHelper (source).
|
|
Depending upon your phone, you might see three vertical dots at the top right of the display (or you might have a menu key). There are two menu options, one for an "About" display and the other for "Settings" (user preferences). Option menu dispatch is provided by MainActivity which invokes MenuActivity to display the menu fragments.
Note that MenuActivity (source) does not have tab navigation, so when a user selects a menu option the only way to return is the "back" button or by pressing the "FragDemo" icon on the ActionBar (top left).
The "About" Fragment (source) is implemented as a WebView w/the HTML supplied as part of the application.
The "Settings" Fragment (source) is an example of a PreferenceFragment.
FragmentDemo can be built and deployed entirely from the command line using the Android maven plugin. I created FragmentDemo using the "Android-QuickStart-Archetype as described here which was quite helpful.
Monday, May 20, 2013
What to code after "Hello, Android"
- Navigation between three separate displays (each backed by a dedicated Activity)
- How to pass arguments between Activity(s)
- How to create and use a Button
- How to create and use an EditText
- How to use Android log statements
- Special guest appearance w/AndroidManifest.xml
|
|
|
Monday, December 3, 2012
Google Web Toolkit - First Steps
Saturday, March 10, 2012
(Yet Another) Android NDK Blog Posting
This blog post provides an introduction to NDK along w/some anecdotes and a working Android application.
Note that I am writing this in March of 2012. The current SDK is version "r16" and the current ndk is version "r7b". My examples should be valid for the current versions. As always, these examples might not age well so YMMV.
Some of you might be surprised to discover that Java existed before Android (relax, it's a joke). Java has always provided a mechanism to integrate with C/C++ applications called JNI (Java Native Interface). Wikipedia provides a decent overview of JNI and Sun (now Oracle) provides a comprehensive introduction to JNI here. Serious developers will want to read the "JNI Specification" (also available of the Oracle web site.
At runtime, your C/C++ objects will be linked and executed using the JVM. There is a cost to transition the Java/C barrier, make sure you do enough work on the C side to make the transition worth while. Of course, if you include JNI then you have excluded portability (because the C/C++ files must be compiled for every target platform). Portability is not much of a concern for Android since most targets are ARM platforms.
In the early days of Java, JNI was a frequent requirement because many vendors had not yet created Java friendly libraries. The usual steps were:
- Create "native" Java methods to wrap around C functions. I usually collect these in a common class called "JniWrapper" (or "NdkWrapper" for Android).
- Use the "javah" utility to generate a C header file based upon the contents of "JniWrapper" (i.e. "javah -jni java.class")
- Write a C wrapper to act as a bridge between C and Java, the contents of the wrapper correspond to the generated header file (from step 2). Variable conversion, etc. between C/Java is typically performed here.
The above looks rather straight forward (and it is) but in practice some projects were quite difficult to complete and make stable (different threading models, etc). As Java came to dominate, there was better support for Java and less of a reason to employ JNI. Thanks to Android, this issue is receiving much more attention.
When I design a JNI application, I break the functionality down into three use cases:
- Java invokes C (most common example)
- C invokes Java (frequently asynchronous callbacks)
- Shared variables (visible to both C and Java)
I have created a sample Android NDK application to illustrate these use cases which can be found on GitHub (more about the example later).
Another design issue relates to using objects as arguments. In general, I try to avoid using complicated containers as arguments. Instead I favor primitive types such as int (not Integer). Strings are the exceptions and JNI provides convenience mechanisms for handling String.
Now create a Java class to act as the interface between Java and C. Your C methods will be invoked by Java methods marked as "native" (these look like "abstract" methods). This class should also contain a call to "System.loadLibrary()" which will cause your C/C++ objects to be loaded within the JVM.
The "javah" utility will generate a C header based upon "native" declarations within a Java class file. The resulting file looks something like this:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_digiburo_example_native_demo_NdkWrapper */
#ifndef _Included_com_digiburo_example_native_demo_NdkWrapper
#define _Included_com_digiburo_example_native_demo_NdkWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_digiburo_example_native_demo_NdkWrapper
* Method: nativeSetup
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_digiburo_example_native_1demo_NdkWrapper_nativeSetup(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Note these important features:
- The "jni.h" file which is distributed w/the JDK and provides Java data type definitions, etc.
- JNIEXPORT and JNICALL are macros defined within jni.h
- The C method name looks like a Java signature (i.e. package name, method name).
- The C function will always have at least two arguments: the "JNIEnv" pointer and the "jobject" reference. "JNIEnv" points to the virtual machine and "jobject" points to the Java class which invoked the native method (frequently described as similar to "this").
- Remember the JVM cares about method signatures. Item #2 and item #3 come directly from the "native" declarations in Java and must match exactly or your method will not be invoked.
While designing your NDK application note that only a small collection of libraries are distributed w/the NDK (library population varies w/NDK version). For example, I recently needed JPEG support but libjpeg.so is not part of the NDK. In this case you might have to build the libraries you need (be sure to build them using the appropriate cross compiler, etc). In my case I simply used the libjpeg headers and library from the Android platform sources. The point is: until you are a NDK master be sure to pad the schedule in case there is a surprise.
To integrate JNI w/your Android application is simple enough with recent versions of the NDK. Simply create an Android application in eclipse, then create a "jni" directory. The "jni" directory should be a peer to "src", "res", etc. and acts as the root directory for your C/C++ sources.
Eclipse also provides a C/C++ environment which will be handy for flipping between XML, Java and C/C++. My own preference is to do heavy lifting in emacs and my compiles on the command line.
To continue w/implementation, copy the "javah" generated header file to the "jni" directory and craft a source file to support it.
The Android NDK provides a build system which greatly simplifies integrating w/a Android application. Build directives are contained within the "Android.mk" and an optional "Application.mk" files.
#example Android.mk
LOCAL_PATH := $(call my-dir)
#
include $(CLEAR_VARS)
#
LOCAL_CFLAGS := -fexceptions
#
LOCAL_MODULE := digiburo-bridge
LOCAL_SRC_FILES := NdkWrapper.cpp
#
LOCAL_LDLIBS += -llog
#
include $(BUILD_SHARED_LIBRARY)
Note these import features:
- LOCAL_MODULE defines the name of your C/C++ library. This must match the name specified in System.loadLibrary().
- LOCAL_SRC_FILES define source files
- LOCAL_LDLIBS specifies link path (in this case to Android logging).
Compile within the "jni" directory by typing "ndk-build" which is a utility supplied w/the NDK.
Assuming a successful compile, you should see the results within your Android project in the "libs" and "obj" directories.
At this point you should be able to deploy and run your Android application using both Java and C.
I have created a sample Android NDK application called "NativeDemo" which is available from my GitHub repository. NativeDemo provides examples for:
- Java calls C (NdkWrapper.nativeSetup(), NdkWrapper.nativeString(), NdkWrapper.nativeAdder())
- C invokes Java (NdkWrapper.nativeVectorDemo() and NdkWrapper.callBack())
- Shared variables (NdkWrapper._nativeBuffer)
- Exception handling (NdkWrapper.exceptionDemo())
- Demonstration of JNI_OnLoad() and JNI_OnUnload()
- You need all the usual Android development tools such as eclipse, Android SDK, ADT plugin and of course the Android NDK.
- Import my git repository into your eclipse workspace.
- From the command line, enter the "jni" directory and type "ndk-build" assuming you have the NDK, etc this should compile NdkWrapper.cpp and place the results in the "libs" and "objs" directories.
- Now run the application from eclipse, it should deploy like any other application.
- To see the results, use "adb logcat" - note that log messages are generated both from Java and from NdkWrapper.cpp










