blueBell is a didactic application demonstrating design strategies with the Android platform. It is an application to remotely control a Sony Camera, connected through a Wifi connection, by means of its exposed REST interface.
If you want to quickly download the sources and compile them, please refer to the chapter "Compiling the project with and IDE" below.
Structure of the Project
The project is composed of three separate modules:
- Sony Camera API. It is code (heavily) refactored from a Sony example and wraps the Sony Camera API. It is interesting as an example on how to deal with a REST API (JSON and XML based) in an Android application. It also contains a simple client implementation of the SSDP protocol. This module is a plain Java 7 set of files, which demonstrates how part of the code of an Android application can be written in a reusable fashion.
- Camera View. It contains the basic abstractions of the blueBell application, in form of Presentation and Control objects. It's again a plain Java 7 set of files, which demonstrates how part of an Android application can be written in a way so that they can be tested without resorting to the Android platform.
- Application APK. This module contains Android specific code and generates the final APK bundle.
There's a test module too, but it is just a stub at the moment.
Use of the Presentation Abstraction Control (PAC) pattern
Some say that an
Activity is a controller object, but others disagree. Indeed, an
Activity is bound to the
Android life-cycle, and from this respect acts as a controller. But it also interacts with the User Interface, both in
setting its state and registering callbacks. So, I'd rather say it's a "life-cycle" controller or a "navigation"
controller. It makes sense to split the presentation logic into a separate class for complying with the
Separation of Concerns (SoC) principle and its specialisation
The general design of blueBell refers to the Presentation Abstraction Control (PAC) architectural pattern:
components which interact with the user (Presentations) are kept as simple and dumb as possible, without any logic. They mostly expose methods to render data and populate UI widgets and to capture the user's gestures and take care of any UI threading issue. In blueBell, activities are PAC presentations. Their interface is modelled upon methods with represents a single interaction with the UI with a well defined semantics; for instance
public void renderRecStartStopButtonAsStop(). Their implementation is straightforward, such as just changing the properties of a UI widget. They are usually just a few lines of code.
Presentations are responsible for taking care of Android UI threading issues (see below).
the presentation logic is encapsulated in controllers (Controls). In blueBell, these are separated, mostly plain Java classes. They are indeed split in two parts:
- a superclass which contains all the code that can be written without depending on Android;
- a specialised class which extends the abstract controller with the required Android-specific code.
The following points are likely to require specific Android code:
- the use of
- the use of string resources (
- the use of system specific infrastructures, such as the
- the use of system services, such as
Since Android forbids networking code to be called from the UI thread, and blueBell is mostly about interacting with a remote service hosted on the camera, controllers execute most of their jobs in a background thread.
The general rationale behind this approach is explained in this blog post, even though there's no use of DCI in blueBell. A common benefit is testing: since both Presentations and Controls are described by interfaces, it is possible the creation of mocks that can be used in automated testing. While at the present time there are no valid tests in this project, most of the presentation logic can be automatically tested by means of pure Java classes, avoiding the cumbersome Android approach to tests.
Given the very nature of Android, which is not plain Java, the application of PAC raises some more problems than with a JSE or JEE application. Some trade-offs are to be applied.
Structure of the application
The application is composed by two Activites:
CameraDiscoveryPresentationActivitymakes it possible to pick a Wifi network and scans for the presence of Sony camera devices. This activity (together with its control object) demonstrates:
- how to interact with the Wifi system service;
- how to interact with a system activity (the Wifi configuration panel);
- how to receive a Broadcast Notification;
- how to preserve the state of an Activity;
- how to write a simple adapter to populate a
- how to use an
Intentto communicate with another
CameraPresentationActivityconnects to a camera device and, if it supports the "live view" feature, it continuously displays the contents of the Electronic Viewfinder (EVF). It also shows the values of some camera settings such as the F number, the shutter speed, the ISO speed rating and others; some of the settings can be also changed. It also allow to shoot a photo or to record a movie. This activity (together with its control object) demonstrates:
- how to create an
Activitythat interacts with a remote service (REST in this case);
- how to customise an
Activityso it runs at full screen;
- how to create a custom Android UI component;
- how to manage a
- how to create an
Taking care of the UI threading model
The UI threading requirements for Android, which mandate that widgets are only touched by the same thread which creates
the Activity that contains them, are taken care of by a single class named
creates a decorator of the Presentation and its Control always interact with the Presentation by means of its decorator.
The decorator invokes the original method in the special UI thread.
AndroidUIThreadDecoratorFactory relies on a
well known Java technique. More information are in inline comments inside the source code.
The whole project is compiled in Java 7, which is compatible with recent releases of Android. Most Java syntactic features, such as the diamond operator, are thus allowed. A feature that is not allowed is the "try-with-resources" because it requires a specific Java 7 runtime support that is missing in Android.
The app makes use of some annotations defined in JSR-305. They are
at this level of discussion they can be just considered as a support for documentation, as they declare which reference
variables are allowed to hold
Lombok is an APT (Annotation Processor Tool) which reduces the amount of code in some
trivial parts by making use of annotations. For instance,
@Getter private int foo; automatically generates a
public int getFoo() getter method.
The used annotations are:
@Setterto generate getter and setter methods;
@RequiredArgsConstructorsto generate a constructor with initialises the class fields;
@Slf4jto transparently inject a
logfield which is used for logging (SLF4J is used).
@Cleanupto correctly close I/O resources (given that try-with-resources can't be used - see above).
While Lombok works transparently when the application is compiled from the command line, some additional work is required to avoid false syntax errors in the IDE. This might requires some special configuration in the IDE so it doesn't complain about syntax errors.
If you work with NetBeans 7.3 and later, you don't need anything.
If you work with Eclipse, you need to install the Lombok plugin as explained at http://projectlombok.org
If you work with Android Studio, you need to go to File / Settings (Preferences on Mac OS X), go to the Plugin tab and install the Lombok plugin. You also need to go to the Compiler Settings, tab "Annotation Processors" and check "Enable annotation processors".
Compiling the project with an IDE
blueBell is being developed with Maven, which is not an obvious choice for most people. In particular, it is not the default tool suggested by Google. Google's Android Studio, in fact, uses Gradle. For this reason, the project has been structured so it can work with both tools:
pom.xmlare related to Maven;
*.imlare related to Gradle and Android Studio.
If you're opening the project with a Maven enabled IDE such as NetBeans and Eclipse, you don't have to do anything
special (Gradle and Android Studio are just ignored). If you're opening the project with Android Studio, you should use
the menu "File / Import Project..." rather than "Open...". Even in this case, you might get some Maven warnings, since
Android Studio has some Maven support embedded. Just ignore them. Perhaps, the best thing that you can do when working
with Android Studio is to delete the
pom.xml files before opening the project.
Please also read the chapter above related to Lombok.
In order to build the project, run from the command line:
The project can be opened and built by a recent version of the NetBeans, Eclipse or Idea IDEs.
More information can be found on the homepage of the project.
Where can I get the latest release?
You can download source and binaries from the download page.
Alternatively you can pull it from the central Maven repositories:
<dependency> <groupId>it.tidalwave.bluebell<groupId> <artifactId>bluebell</artifactId> <version>-- version --</version> </dependency>
We accept pull requests via Bitbucket or GitHub.
There are some guidelines which will make applying pull requests easier for us:
- No tabs! Please use spaces for indentation.
- Respect the code style.
- Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source ode should be reformatted create a separate PR for this change.
- Provide TestNG tests for your changes and make sure your changes don't break any existing tests by running
mvn clean test.
If you plan to contribute on a regular basis, please consider filing a contributor license agreement. Contact us for more information
Code is released under the Apache Licence v2.