Java 8 Language features supported in Android N: Lambdas

One of the new additions the Android N brings is support for several Java 8 language features:
Lambda expressions
Default and static interface methods, and
Repeatable annotations

In this blog post we will take a look at the lambda expressions.

Setting up development environment

In order to start using these features however, the development environment needs some adjustments. The support of Java 8 language features requires a new compiler called Jack, which currently is supported only in Android Studio 2.1. So if you want to use Java 8 language features, you need to use Android Studio 2.1.

Android documentation describes in details how to setup your development environment for Java 8 support.

Enabling support for Java 8

To enable support for Java 8 in your Android project, the build.gradle file has to be adjusted by setting the compileOptions to version 1.8 and jackOptions enabled.

android {
  ...
  defaultConfig {
    ...
    jackOptions {
      enabled true
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

Lambda Expressions

Lambda expressions are a new feature included in the Java 1.8. A lambda expression basically is a block of code that can be passed around to be executed later. This, in fact, is very similar to anonymous classes. However, unlike anonymous classes, lambda expressions are succinct, as a result producing less verbose code.

Consider the following 3 examples:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Log.d(TAG, "Clicked.");
    }
});

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         Log.d(TAG, "Position: " + position);
         Log.d(TAG, "Id: " + id);
    }
 });

Runnable runnable = new Runnable() {
    @Override
     public void run() {
         Log.d(TAG, "From Runnable");
     }
};
new Thread(runnable).start();

Converting the above pieces of code to use lambda expressions will look like this:

button.setOnClickListener(view -> Log.d(TAG, "Clicked."));

listView.setOnItemClickListener((parent, view, position, id) -> {
     Log.d(TAG, "Position: " + position);
     Log.d(TAG, "Id: " + id); 
}

Runnable runnable = () -> Log.d(TAG, "From Runnable"); 
newThread(runnable).start(); 

 

It is clear that the code with the lambdas is shorter.  Specifically, this comes from:

– removal of class instantiation, eg.: new View.OnClickListener(),
– removal of method name, return type, and access modifier, eg.: public void onClick(View view)
– as well as removal of parameter types, eg.: only view, instead of View view.

And what is left, are the actual parameters and the method body.

Lambda Expression syntax

The basic format of a lambda expression is: a list of comma separated parameters, the “->” symbol, and the body.

param1, param2, paramN -> { // body }

1. Parameter types are optional, but they can be also specified in the expression:

// without parameter types
(parent, view, position, id) -> {
      Log.d(TAG, "Position: " + position);
      Log.d(TAG, "Id: " + title);
}

// with parameter types
(AdapterView<?> parent, View view, int position, long id) -> {
      Log.d(TAG, "Position: " + position);
      Log.d(TAG, "Id: " + title);
}

2. If the body of the method has only one line, then the curly brackets can be ommited:

// with curly brackets
(parent, view, position, id) -> { processItemClick(position); }

// without curly brackets
(parent, view, position, id) -> processItemClick(position)

3. If the expression has only one parameter, then the parenthesis around parameter can be omitted:

// with parenthesis
(view) -> Log.d(TAG, "Clicked.")

// without parenthesis
view -> Log.d(TAG, "Clicked.")

4. The return keyword is optional if the body has a single expression to return the value;

// example interface
public interface Calculator {
        int calculate(int a, int b);
}

// with return
Calculator calculator = (a, b) -> {return a + b;};

// without return
Calculator calculator = (a, b) -> a + b;

5. Lambda expression that does not take any arguments:

() -> Log.d(TAG, "From Runnable")

Functional interfaces

Lambdas are treated as instances of a special interface type called functional interface. A functional interface in fact is nothing but an interface with a single abstract method. We already saw several examples of such interfaces; Runnable, Callable, OnClickListener, OnItemClickListener are all examples of functional interfaces.

A new annotation called @FunctionalInterface was introduced to mark an interface as such.

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

The annotation is optional, but it is highly recommended; it clearly communicates the intent of the interface and it also allows the compiler to perform additional checks.

@FunctionalInterface
public interface Calculator {

    int calculate(int a, int b);

    // *** this will break compilation ***
    void print(String result);
}

@FunctionalInterface
public interface Calculator {

    int calculate(int a, int b);

    // this will NOT break the compilation,
    // because print is a default method
    default void print(String result){
        Log.d(TAG, result);
    }
}

Lambda expressions might led you to the wrong idea that they are something that is going to replace anonymous classes, and now seeing that a lambda expression can be converted from an interface with only one abstract method, you might wonder how useful is this. If this is so, then I would like to recall that a lambda expression is a mechanism that allows you to pack functionality and pass it around, in a succinct way. So no, lambdas, are not intended to replace anonymous classes.

Advertisement

Example usage of AppCompatActivity in Android

The latest release of android support library, 22.1, deprecates the ActionBarActivity in favor of AppCompatActivity, which promises to bring a single consistent ActionBar for all devices starting with API Level 7 and above.
Also, the new update adds the ability to tint widgets automatically when using AppCompat, and adds support for consistent material design dialogs. Use support.v7.app.AlertDialog (instead of android.app.AlertDialog), to get nice looking material dialogs across multiple versions of devices.

android-support-22.1

Example:
1. In order to benefit from all these things, the first thing you should do is to update the support library to 22.1.0.

dependencies {
   // … 
   compile 'com.android.support:appcompat-v7:22.1.0'
}
2. Then let your activity extend AppCompatActivity.
public class MainActivity extends AppCompatActivity {
  // ...
}
3. And finally, change the application theme to AppCompat or any descendants of it.
<application android:theme="@style/Theme.AppCompat">
Configuring the material color palette

Following the steps above will setup the application with the default theme, but the actionbar can be styled further by specifying the material color palette:

<style name="AppTheme" parent="Theme.AppCompat">
   <item name="colorPrimary">@color/primary</item>
   <item name="colorPrimaryDark">@color/primaryDark</item>
   <item name="colorAccent">@color/accent</item>
</style>

and then update your application theme to use AppTheme.

<application android:theme="@style/AppTheme">

Introduction to Android Espresso

Espresso is a testing framework that exposes a simple API to perform UI testing of android apps. With the latest 2.0 release, Espresso is now part of the Android Support Repository which makes it more easier to add automated testing support for your project.

But before jumping into Espresso API, lets consider what puts it apart from the other testing frameworks.

  • One of the first things you’ll notice about Espresso, is that its code looks a lot like English, which makes it predictable and easy to learn.
  • The API is relatively small, and yet open for customization.
  • Espresso tests run optimally fast (no waits, sleeps)
  • Gradle + Android Studio support

Adding Espresso to your project

1. First of all make sure you have Android Support Repository installed

android sdk manager

2. Add the following dependencies to your application build.gradle file

dependencies {
   androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
   androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
}

3. Finally, specify the test instrumentation runner in default config

android {

    defaultConfig {
        // ....
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
}

And that is basically what it takes “to invite your project to a cup of Espresso”!

The main components of Espresso

Espresso is built up from 3 major components.

These components are:

  • ViewMatchers – allows you to locate a view in the current view hierarchy
  • ViewActions – allows you to interact with views
  • ViewAssertions – allows you to assert the state of a view.

For simplicity, you may use these shortcuts to refer to them:

  • ViewMatchers – “find something
  • ViewActions – “do something
  • ViewAssertions – “check something

And, for example when you will need to check something (like, is some text displayed on the screen?), you’ll know you’ll need a ViewAssertion for that.

Below is an example of a test in Espresso, and where the main components find their place.

Android Espresso main components

A simple test using onView()

Suppose we have an app where the user is asked to enter his name.
After he enters the name, he taps on the “Next” button and is redirected to another activity where a greeting message is displayed.

espresso simple test

If we would write a test for this scenario, then it might look something like this:

// locate the view with id "user_name" and type the text "John"
onView(withId(R.id.user_name)).perform(typeText("John"));

// locate the view with id "next" and click on it
onView(withId(R.id.next)).perform(click());

// locate the view with id "greeting_message" and check its text is equal with "Hello John!"
onView(withId(R.id.greeting_message)).check(matches(withText("Hello John!")));

Notice that we don’t specify explicitly what kind of view we are interacting with (eg.: EditText, Button), we simply say that we are looking for a view with a specific id.
Also, when clicking on the “Next” button and later checking the text, we don’t have to write some special code to tell Espresso that we have navigated to another activity.

Now, if we want to actually run this test, then it should be put in a class. In Gradle, the location where tests are stored is: yourApp/src/androidTest/java.

This is an example of a test class, and its main characteristics:

Espresso example test class

A simple test using onData()

Whenever you have a ListView, GridView, Spinner, and other Adapter based views, you’ll have to use onData() in order to interact with an item from that list.
onData() is targeting directly the data provided by your adapter. What does this mean, we will see in a moment.

In a hypothetical application we are asked to select a country from a Spinner, once selected, the country is displayed next to the Spinner.

espresso on data

A test to check that the displayed country is equal with what was selected, might look like this:

// locate the view with id "country_spinner" and click on it
onView(withId(R.id.country_spinner)).perform(click());

// match an item that is a String and is equal with whatever value the COUNTRY constant is initialized, then click on it.
onData(allOf(is(instanceOf(String.class)), is(COUNTRY))).perform(click());

// locate the view with id "selected_country" and check its text is equal with COUNTRY
onView(withId(R.id.selected_country)).check(matches(withText("selected: " + COUNTRY)));

The Spinner you saw in the example above is backed by a simple array of strings, and because of this, we specify that we are looking for an item of type String. If, instead of a String, it were some custom object, then we would specify that instead.
To illustrate, consider the following example where a list of books is displayed:

books-adapter

Since the items in the adapter are of type Book, so will look the query:

onData(allOf(is(instanceOf(Book.class)), withBookTitle(BOOK_TITLE))).perform(click());

DataInteractions

Espresso has a few useful methods that can be used to interact with data.

atPosition() – Might be useful when the element to interact with is not relevant, or when the items always appear in a specific order, so you know every item on what position sits.

onData(...).atPosition(2).perform(click());

inRoot() – Use inRoot() to target non-default windows. One scenario where this can be used is when testing autocomplete. The list that appears in the autocomplete view belongs to a window that is drawn on top of application window.
In this case you have to specify that the data you are looking for, is not in the main window.

onView(withText("AutoCompleteText"))
        .inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView()))))
        .check(matches(isDisplayed()));

onChildView() – This DataInteraction allows to further refine the query by letting you interact with a specific view from a list row.
Let say that you have a list of items and every item has a delete button. You want to click on Delete button of a specific item:

onData(withBookTitle("My Book"))
      .onChildView(withId(R.id.book_delete)).perform(click());

inAdapterView() – This allows to select a particular adapter view to operate on, by default Espresso operates on any adapter view.
You may find this useful when dealing with ViewPagers and Fragments, and you want to interact with the AdapterView that is currently displayed, or when you have more than one adapter view in your activity.

onData(withBookTitle("My Book"))
      .inAdapterView(allOf(isAssignableFrom(AdapterView.class), isDisplayed()))
      .perform(click());

Espresso and RecyclerView

RecyclerView is an UI component designed to render a collection of data just like ListView and GridView, actually, it is intended to be a replacement of these two. What interests us from a testing point of view, is that a RecyclerView is no longer an AdapterView. This means that you can not use onData() to interact with list items.

Fortunately, there is a class called RecyclerViewActions that exposes a small API to operate on a RecyclerView. RecyclerViewActions is part of a separate lib called espresso-contrib, that also should be added to build.gradle:

dependencies {
    // ...

    androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.0');
}

Since your project already includes a dependency to recyclerview, and might as well include support libs, some dependencies conflicts might appear. In this case exclude
them from espresso-contrib like this:

dependencies {
    // ...

    androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.0') {
        exclude group: 'com.android.support', module: 'appcompat'
        exclude group: 'com.android.support', module: 'support-v4'
        exclude module: 'recyclerview-v7'
    }
}

Here is how to click on an item from the list by position:

onView(withId(R.id.recyclerView))
      .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));

Or how to perform a click on a View from an item:

onView(withId(R.id.recyclerView))
      .perform(RecyclerViewActions.actionOnItem(
                hasDescendant(withText(BOOK_TITLE)), click()));

More Espresso Examples on Github:
https://github.com/vgrec/EspressoExamples

Introducing SectionedActionBarList

This Android library allows you to replace the drop down navigation list with a custom list where the items in the list are grouped by sections. It was inspired from the Google I/O 2014 app how sessions are grouped in the ActionBar list.

While the new Material Design movement discourages the use of ActionBar lists, in some situations it can be the best available option.

At the moment the library is not available on a repository, you have to include it as a source library in your project, but that will be fixed soon.

Github project page: https://github.com/vgrec/SectionedActionBarList

Example
List
<Section> sections = new ArrayList
<Section>();
 
Section themes = new Section("Themes");
themes.add("Design");
themes.add("Develop");
themes.add("Distribute");
sections.add(themes);
 
Section topics = new Section("Topics");
topics.add("Android");
topics.add("Chrome / Web");
topics.add("Cloud Services");
topics.add("Media");
topics.add("Location");
topics.add("Performance");
sections.add(topics);
 
Section types = new Section("Types");
types.add("Sessions");
types.add("App Reviews");
types.add("Box Talks");
sections.add(topics);
 
SectionedActionBarList actionBarList = new SectionedActionBarList(this).from(sections);
actionBarList.setItemSelectedListener(new ItemSelectedListener() {
  @Override
  public void onItemSelected(AdapterView<?> parent, View view, int position, long id, String sectionName, String itemName) {
      Toast.makeText(MainActivity.this, "Section: " + sectionName + ", Item: " + itemName, Toast.LENGTH_LONG).show();
  }
});

The SectionedActionBarList accepts a list of sections List<Section> sections, and every Section has a name and some associated items.

sectioned actionbar list

Configuration

Small customizations can be done to fit with your application design:

ListConfiguration configuration = new ListConfiguration(this);
configuration.setActionBarItemColorResource(R.color.brown);
configuration.setIndicatorDrawableResource(R.drawable.spinner_indicator_dark);
configuration.setSectionTitleColorResource(R.color.teal);
configuration.setDropdownItemColorResources(R.color.light_blue, R.color.dark_grey);

SectionedActionBarSpinner actionBarSpinner = new SectionedActionBarSpinner(this, configuration).from(sections);
// ....

actionbar list

Thanks to Webucator, a provider of Android classes, for producing the below video illustrating the integration of the SectionedActionbarList.


Analysing Android code with SonarQube

sonar analysis

SonarQube, formerly known as Sonar, is a platform to analyze code quality. Analysis covers such aspects as code duplications, potential bugs, coding rules, complexity, unit tests, comments, and architecture & design.
It supports supports more than 20 programming languages and has a reach set of useful plugins that gives you the opportunity to inspect different aspects of the code.

What is caracteristic about SonarQube is that it comes as a platform in the form of a web application. This means that the results of the analysis will be displayed in a web page.

Installing SonarQube

The installation is pretty straightforward, you have just to download an archive and extract it in a folder of your choice.
1. Go to http://www.sonarqube.org/downloads/ and download the latest release.
2. Unzip the archive

Starting SonarQube

1. Go to sonarqube-4.3/bin (or whatever version you downloaded)
2. Open a corresponding folder according to your operating system (linux-x86-64 in my case). There you should see a file called sonar.sh (or StartSonar.bat for Windows)
3. Open up a terminal window and execute: sonar.sh start (or just double click StartSonar.bat on windows). This command will start sonar listening on localhost:9000.
4. Open a browser and enter localhost:9000. The sonar web page should open.
Note that it may take some time until sonar loads, so if you get “page not found” in your browser, try to refresh the page later.

Installing SonarQube Runner

There are several ways to analyse the source code and in this tutorial we will choose to analyse with SonarQube Runner, recommended as the default launcher to analyze a project.

1. Once again go to http://www.sonarqube.org/downloads/ and download SonarQube Runner
2. Extract the downloaded archive into a directory of your choise, which we will refer as: <install_directory>
3. Update global settings by editing: <install_directory>/conf/sonar-runner.properties (if you are running sonar on localhost, like in this tutorial, you don’t have to modify any settings):

#----- Default SonarQube server
#sonar.host.url=http://localhost:9000

#----- PostgreSQL
#sonar.jdbc.url=jdbc:postgresql://localhost/sonar

#----- MySQL
#sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8

#----- Oracle
#sonar.jdbc.url=jdbc:oracle:thin:@localhost/XE

#----- Oracle
#sonar.jdbc.url=jdbc:oracle:thin:@localhost/XE

#----- Microsoft SQLServer
#sonar.jdbc.url=jdbc:jtds:sqlserver://localhost/sonar;SelectMethod=Cursor

#----- Global database settings
#sonar.jdbc.username=sonar
#sonar.jdbc.password=sonar

4. Create a new SONAR_RUNNER_HOME environment variable set to <install_directory>, so that you could invoke sonar runner from any location.
5. Add the <install_directory>/bin directory to your path.

To check that sonar runner was installed properly, open a terminal window and execute sonar-runner -h.

You should get a message like this:

usage: sonar-runner [options]

Options:
-D,--define Define property
-e,--errors Produce execution error messages
-h,--help Display help information
-v,--version Display version information
-X,--debug Produce execution debug output

Analysing source code of a project

Once the sonar runner is properly installed, we can proceed to code analysis.

1. Navigate to the root directory of your project and create a file called sonar-project.properties, which will specify the project settings such as the code source directory, language used, and the project name:

sonar.projectKey=myproject
sonar.projectName=My Project
sonar.projectVersion=1.0

sonar.sources=src
sonar.language=java
sonar.sourceEncoding=UTF-8

Note: for Android Studio, which follows the gradle directory structure, set the sourses as:

sonar.sources=src/main/java

2. Run sonar-runner command to start the analysis.
3. Once the analysis complets, head to localhost:9000 to see the results for your project.

Removing a project from SonarQube

First login as an administrator, admin/admin default username and password.

1. Go to your project dashboard
2. In the top right corner click on Configuration -> Deletion -> Delete Project

delete-shonar-project

Android Volley Tutorial

Volley is an android library released by Google that can make your life easier when dealing with network operations. In this blog post I will mention the main features of the library and show a few example usages, in particular, how to make a request, how to download images, and how to use the cache.

Features of Volley library

a) Automatically schedules the network requests

b) Supports request prioritization. This means that you can load content depending of priorities, for example the main content could have a high priority, but the images a low priority.

c) Provides transparent disk and memory cache that allows for quick reloading of data. Transparent cache means that the caller doesn’t have to know about the existence of the cache. That is, the cache is implemented automatically. You do, however, have the possibility to disable the caching.

d) Provides a good API for canceling requests. You can cancel a single request, or cancel requests depending on some filters.

Besides the great features that Volley comes with, you don’t have to use it for everything. Volley is great for RPC-style network operations that populate UI, a typical example would be loading thumbnail images into a ListView, but not very good for streaming operations like downloading a video or mp3.

Getting started with Volley

1. Clone the Volley project:
git clone https://android.googlesource.com/platform/frameworks/volley
2. Import the library into your project

The most frequent classes of Volley that you will work with are RequestQueue and Request, and ImageLoader when dealing with images loading.

RequestQueue is used for dispatching requests to the network. It is recommended to create it early and use it as a Singleton.
Request is the base class for creating network requests (GET, POST).
ImageLoader is a helper class that handles loading and caching images from remote URLs.

Step 1: VolleySingleton.java

As recommended, lets create first a Singleton class that will return on demand an instance of RequestQueue and one of ImageLoader.

public class VolleySingleton {

    private static VolleySingleton instance;
    private RequestQueue requestQueue;
    private ImageLoader imageLoader;

    private VolleySingleton(Context context) {
        requestQueue = Volley.newRequestQueue(context);

        imageLoader = new ImageLoader(requestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(20);


            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                cache.put(url, bitmap);
            }
        });
    }


    public static VolleySingleton getInstance(Context context) {
        if (instance == null) {
            instance = new VolleySingleton(context);
        }
        return instance;
    }

    public RequestQueue getRequestQueue() {
        return requestQueue;
    }

    public ImageLoader getImageLoader() {
        return imageLoader;
    }
}
Step 2: Add internet permission
<uses-permission android:name="android.permission.INTERNET" /> 
Step 3: Create an instance of RequestQueue
RequestQueue queue = VolleySingleton.getInstance(this).getRequestQueue();
Step 4: Create the request

Volley comes with a class called JsonRequest that you can use to make requests to a server that returns a json response.
However, in this example we will query an RSS feed which returns a response in XML format. Volley does not include a similar class for handling xml responses, like JsonRequest, but it has StringRequest class that can be used to retrieve the response body as a String.

There are two ways to construct a StringRequest:

StringRequest(int method, String url, Listener<String> listener,
            ErrorListener errorListener)

or

StringRequest(String url, Listener<String> listener, ErrorListener errorListener)

The second constructor does not take the request method as a parameter, when not specified, a GET request is created.

Listener is a callback interface for delivering the result, and
ErrorListener is a callback interface for delivering error responses.

Example:

String url = "http://www.pcworld.com/index.rss";
StringRequest request = new StringRequest(url, new Listener<String>() {

            @Override
            public void onResponse(String response) {
                // we got the response, now our job is to handle it 
                parseXmlResponse(response); 
            }
        }, new ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
               //something happened, treat the error.
            }
        });
Step 6: Execute the request
queue.add(request);

And that is all! The execution of the request implies its addition to the RequestQueue.

Step 7: Loading thumbnail images

Loading images can be done easy if you replace the android’s ImageView with Volley’s NetworkImageView:

<com.android.volley.toolbox.NetworkImageView
        android:id="@+id/icon"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:src="@drawable/default_placeholder" />

then use setImageUrl() and you are done!

String url = "..."; // URL of the image
ImageView imageView = (ImageView)view.findViewById(R.id.image);
ImageLoader imageLoader = VolleySingleton.getImageLoader(); 
imageView.setImageUrl(url, imageLoader); 

If, for some reason, you don’t want or can’t use NetworkImageView, then there’s an alternate method.
You can use the get() method of ImageLoader class which accepts the image url and an instance of ImageListener:

ImageLoader imageLoader = VolleySingleton.getImageLoader(); 
imageLoader.get(url, new ImageListener() {
             
            public void onErrorResponse(VolleyError error) {
                imageView.setImageResource(R.drawable.icon_error); // set an error image if the download fails
            }
             
            public void onResponse(ImageContainer response, boolean arg1) {
                if (response.getBitmap() != null) {
                    imageView.setImageBitmap(response.getBitmap());
                } 
            }
        });
Reading from cache

One of the Volley’s features is that it provides transparent disk and memory cache. The cache is implemented automatically for classes that extends Request, such as JsonRequest and StringRequest.

To read the cache:

Entry entry = queue.getCache().get(url);
if(entry!=null){
     String data = new String(entry.data, "UTF-8");
     // process data
}

To turn off the cache:

request.setShouldCache(false);

to remove the cache for a specific request:

queue.getCache().remove(url);

to clear all cache:

queue.getCache().clear();

to invalidate the cache: this will allow to display the cached data until the response is received. When the response is received, it will automatically override the cached data.

queue.getCache().invalidate(url, true);

For more details about Volley you can watch the full video at: https://developers.google.com/events/io/sessions/325304728

Using Maven to save the build time in a properties file

Create a folder called build in the root directory of the project, and a file build.properties with the following content:

build.time=@buildtime@

Using the maven replacer plugin we can replace the token @buildtime@ within the build.properties file with the build timestamp value, and then let the Android application read that value and use it.

 
<plugins>
     <plugin>
         <groupId>com.google.code.maven-replacer-plugin</groupId>
         <artifactId>replacer</artifactId>
         <version>1.5.2</version>
         <executions>
            <execution>
               <phase>validate</phase>
               <goals>
                  <goal>replace</goal>
               </goals>
            </execution>
         </executions>
         <configuration>
            <file>build/build.properties</file>
               <outputFile>res/raw/build.properties</outputFile>
               <replacements>
                  <replacement>
                     <token>@buildtime@</token>
                     <value>${maven.build.timestamp}</value>
                  </replacement>
               </replacements>
        </configuration>
   </plugin>
</plugin>

Run this task with mvn validate command. This will do nothing but replace the tokens from build.properties file with the timestamp value, and output the result to a new file in res/raw.

From here on the file can be accessed as a raw resource and read as a regular properties file.

Reading the properties file:

InputStream rawResource = resources.openRawResource(R.raw.build);
Properties properties = new Properties();
properties.load(rawResource);
String buildTime = properties.getProperty("build.time");

Using Maven in Android to build for different environments (dev, staging, prod, etc)

If you are working on a relatively complex project, chances are that you may need to build the application against different environments, such as a development, a staging, and a production environment. Assuming you are using Maven as a build tool, here’s one solution how Maven could help with this.

For the sake of this example let assume that you are working on an Android app that consumes web services. You have a dedicated development environment where you spent most of the time, but once every two weeks you need to make a version of the app that is built for production.

Let assume that the endpoint for the testing environment is dev.mysite.com, and for the production environment is: prod.mysite.com.
But as an aspiring developer and after reading a bunch of books about best practices, you can no longer accept to just go and manually edit the source files by changing all over the place one environment with another, and you ask yourself if Maven could help with this.

It can, and here’s how.
The main idea is to store all the properties, in this particular example all the urls, in separate resource files. Then, using maven resource plugin copy the corresponding property file into values/environment.xml.

1. In your project root directory create following directory structure:
environment/dev/environment.xml
environment/prod/environment.xml

maven environment

2. Then fill the content of the resource files with appropriate values.
/dev/environment.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="url">http://dev.mysite.com</string>
</resources>

/prod/environment.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="url">http://prod.mysite.com</string>
</resources>

3. Add the maven resource plugin to pom.xml by specifying the phase when the copy action should be executed, the resources, and the output directory:

//...
<plugins>
    <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.4.3</version>
        <executions>
             <execution>
                <id>copy-string-resources</id>
                <phase>validate</phase> <!-- when to execute copy operation -->
                <goals>
                    <goal>copy-resources</goal>
                </goals>
                <configuration>
                    <resources>
                        <resource>
                            <directory>environment/${environment}/</directory>
                            <includes>
                               <include>environment.xml</include>
                               <filtering>true</filtering>
                            </includes>
                        </resource>
                    </resources>
                    <overwrite>true</overwrite>
                    <outputDirectory>${basedir}/res/values/</outputDirectory>
                </configuration>
      </plugin>
</plugins>

4.1 From this point on, you can automate the preparation of environment by creating 2 run configurations:
mvn validate -Denvironment=dev
mvn validate -Denvironment=prod

that will do nothing but copy the appropriate resources from evironment/${environment}/environment.xml, into values/environment.xml

Now, every time you’ll need to prepare a build against a specific environment, the only thing you’ll need to do will be to run one of those commands.

4.2 Another option, to make the things even more compact, is instead of passing the environment like this: -Denvironment=dev, would be to create 2 profiles in pom.xml:

<profiles>
   <profile>
       <id>development</id>
       <properties>
           <environment>dev</environment>
       </properties>
   </profile>

   <profile>
       <id>prod</id>
       <properties>
           <environment>prod</environment>
       </properties>
   </profile>
</profiles>

and then create 2 run configurations with appropriate profile:
mvn validate -P development
mvn validate -P prod

For easy access at environment resources you could create a class like this that will return all the environment properties your applications uses:

public class ApplicationEnvironment{
	
	//...
	
	public String getServerUrl(){
		return resources.getString(R.string.url);
	}	
}

Dealing with AsyncTask and Screen Orientation

A common task in Android is to perform some background activity in another thread, meanwhile displaying a ProgressDialog to the user. Example of these tasks include downloading some data from internet, logging into an application, etc. Implementing an AsyncTask is fairly a simple job, the big challenge is how to handle it properly when an orientation change occurs.

In this article I will walk though a series of potential solutions to address the screen orientation issues when using an AsyncTask.

So, lets create a proof of concept application that makes use of an AsyncTask which does not handle configuration changes yet, and then present a few solutions.

Here’s the AsyncTask implementation that we will be using during the tutorial:

public class AsyncTaskExample extends AsyncTask<String, Integer, String> {

	private final TaskListener listener;

	public AsyncTaskExample(TaskListener listener) {
		this.listener = listener;
	}

	@Override
	protected void onPreExecute() {
		listener.onTaskStarted();
	}

	@Override
	protected String doInBackground(String... params) {
		for (int i = 1; i <= 10; i++) {
			Log.d("GREC", "AsyncTask is working: " + i);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return "All Done!";
	}

	@Override
	protected void onPostExecute(String result) {
		listener.onTaskFinished(result);
	}
}

doInBackground() – this will be called by the AsyncTask on a background thread, and performs all the heavy work. For the sake of this example, I just wrote a simple loop  with a delay of 1 sec between iterations to simulate a task that takes some time.
– The constructor of the class takes a listener as a parameter. The listener will be used to delegate the work of onPreExecute()/onPostExecute() to the calling Activity.

This is the interface definition used by AsyncTaskExample:

public interface TaskListener {
	void onTaskStarted();

	void onTaskFinished(String result);
}

And here’s the usage of AsyncTaskExample (the problematic case):

public class MainActivity extends Activity implements TaskListener, OnClickListener {

	private ProgressDialog progressDialog;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		findViewById(R.id.start).setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.start) {
			new AsyncTaskExample(this).execute();
		}
	}

	@Override
	public void onTaskStarted() {
		progressDialog = ProgressDialog.show(CopyOfMainActivity.this, "Loading", "Please wait a moment!");
	}

	@Override
	public void onTaskFinished(String result) {
		if (progressDialog != null) {
			progressDialog.dismiss();
		}
	}
}

The Activity implements the TaskListener interface and provides appropriate implementation for its methods,  displaying the ProgressDialog when the task is started, and dismissing it when the task is finished. The AsyncTask is fired when clicking on a button.

Now, if you run this example without changing the screen orientation, the AsyncTask will start and finish its work normally. Problems begin to appear when the device orientation is changed while the AsyncTask is in the middle of the work. The application will crash, and an exception similar to these ones will be thrown: java.lang.IllegalArgumentException: View not attached to window manager, or Activity has leaked window com.android.internal.policy….

The cause relies in the Activity life cycle. A change in device orientation is interpreted as a configuration change which causes the current activity to be destroyed and then recreated. Android calls onPause(), onStop(), and onDestroy() on currently instance of activity, then a new instance of the same activity is recreated calling onCreate(), onStart(), and onResume(). The reason why Android have to do this, is because depending of screen orientation, portrait or landscape, we may need to load and display different resources, and only through re-creation Android can guarantee that all our resources will be re-requested.

But don’t panic, you are not alone, there are several solutions that will help us to deal with this situation.

Solution 1 – Think twice if you really need an AsyncTask.

AsyncTasks are good for performing background work, but they are bound to the Activity which adds some complexity. For things like making HTTP requests to a server perhaps you should consider an IntentService. IntentService used in conjunction with a BroadcastReceiver or ResultReceiver to deliver results, could do a better job than an AsyncTask in certain situations.

Solution 2 – Put the AsyncTask in a Fragment.

Using fragments probably is the cleanest way to handle configuration changes. By default, Android destroys and recreates the fragments just like activities, however, fragments have the ability to retain their instances, simply by calling: setRetainInstance(true), in one of its callback methods, for example in the onCreate().

There’s however one aspect that should be taken in consideration in order to achieve the desired result. Our AsyncTask uses a ProgressDialog to signal when the AsyncTask is started, and dismisses it when the task is done. This complicates a bit the things because even if we are using setRetainInstance(true), we should close all windows and dialogs when the Activity is destroyed, otherwise we will get an: Activity has leaked window com.android.internal.policy…  exception. This happens when you try to show a dialog after you have exited the Activity.

In order to address this issue, we will add some logic to keep track of AsyncTask status (running/not running). We will dismiss the ProgressDialog when the fragment is detached from activity, and check in onActivityCreated() the status of AsyncTask. If the status is “running”, this means we are returning from a screen orientation and we will just re-create and display the ProgressDialog to show that the AsyncTask is still working.

public class ExampleFragment extends Fragment implements TaskListener, OnClickListener {

	private ProgressDialog progressDialog;
	private boolean isTaskRunning = false;
	private AsyncTaskExample asyncTask;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setRetainInstance(true);
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		// If we are returning here from a screen orientation
		// and the AsyncTask is still working, re-create and display the
		// progress dialog.
		if (isTaskRunning) {
			progressDialog = ProgressDialog.show(getActivity(), "Loading", "Please wait a moment!");
		}
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_layout, container, false);
		Button button = (Button) view.findViewById(R.id.start);
		button.setOnClickListener(this);
		return view;
	}

	@Override
	public void onClick(View v) {
		if (!isTaskRunning) {
			asyncTask = new AsyncTaskExample(this);
			asyncTask.execute();
		}
	}

	@Override
	public void onTaskStarted() {
		isTaskRunning = true;
		progressDialog = ProgressDialog.show(getActivity(), "Loading", "Please wait a moment!");
	}

	@Override
	public void onTaskFinished(String result) {
		if (progressDialog != null) {
			progressDialog.dismiss();
		}
		isTaskRunning = false;
	}

	@Override
	public void onDetach() {
		// All dialogs should be closed before leaving the activity in order to avoid
		// the: Activity has leaked window com.android.internal.policy... exception
		if (progressDialog != null && progressDialog.isShowing()) {
			progressDialog.dismiss();
		}
		super.onDetach();
	}
}
Solution 3 – Lock the screen orientation

You could do this in 2 ways:

a) permanently locking the screen orientation of the activity, specifying the screenOrientation attribute in the AndroidManifest with “portrait” or “landscape” values:

<activity
   android:screenOrientation="portrait"
   ...  />

b) or, temporarily locking the screen in onPreExecute(), and unlocking it in onPostExecute(), thus preventing any orientation change while the AsyncTask is working:

@Override
public void onTaskStarted() {
	lockScreenOrientation();
	progressDialog = ProgressDialog.show(CopyOfCopyOfMainActivity.this, "Loading", "Please wait a moment!");
}

@Override
public void onTaskFinished(String result) {
	if (progressDialog != null) {
		progressDialog.dismiss();
	}
	unlockScreenOrientation();
}

private void lockScreenOrientation() {
	int currentOrientation = getResources().getConfiguration().orientation;
	if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
	} else {
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
	}
}

private void unlockScreenOrientation() {
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
Solution 4 – Prevent the Activity from being recreated.

This is the easiest way to handle configuration changes, but the less advised. The only thing you need to do is to specify the configChanges attribute followed by a list of values that specifies when the activity should prevent itself from restarting.

<activity
   android:configChanges="orientation|keyboardHidden"
   android:name=".MainActivity"
   .... />

Using this approach however, is not recommended, and this is clearly stated in the Android documentation: Using this attribute should be avoided and used only as a last-resort.

You may ask what’s wrong with this approach. Well, if you build the above example against Android 2.2 it will work fine, but if you build it against Android 3.0 and higher, you may notice that the application still crashes on orientation change. This is because starting  with Android 3.0 you need also to handle the screenSize, and smallestScreenSize:

<activity
   android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize"
   android:name=".MainActivity"
   .... />

As it turns out, not only a screen orientation causes the Activity to recreate, there are also other events which may produce configuration changes and restart the Activity, and there’s a good chance that we won’t handle them all. This is why the use of this technique is discouraged.

Caching Objects in Android Internal Storage

Android provides several options for persisting application data, such as SQLite Databases, SharedPreferences, internal and external storage.

In this post we’ll take a look how we can use the internal storage to persist application data. By default, files saved to internal storage are private to the application and they cannot be accessed by other applications. When the application is uninstalled, the files are removed.

To create and write a file to internal storage, openFileInput(); should be used. This opens a private file associated with the Context’s application package for writing. If the file does not already exits, then it is first created.

openFileInput() returns a FileInputStream, and we could use its write() method, which accepts a byte array as argument, to write the data. However, in the below example we will wrap the FileInputStream into an ObjectOutputStream which provides 2 convenient methods  for writing and reading objects: writeObject() and readObject().

So, lets  pretend that we need to save a List of some objects. The model class of our object looks like this:

public class Entry implements Serializable{
   private String name;

   public Entry(String name) {
      this.name = name;
   }

   public String getName() {
      return name;
   }
}

Make sure that the model class implements Serializable, otherwise you may get a java.io.NotSerializableException when attempting to write the object on internal storage.

Below is the utility class that provides 2 methods, one for storing objects to internal storage, and another for retrieving objects from internal storage.

public final class InternalStorage{

   private InternalStorage() {}

   public static void writeObject(Context context, String key, Object object) throws IOException {
      FileOutputStream fos = context.openFileOutput(key, Context.MODE_PRIVATE);
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(object);
      oos.close();
      fos.close();
   }

   public static Object readObject(Context context, String key) throws IOException,
         ClassNotFoundException {
      FileInputStream fis = context.openFileInput(key);
      ObjectInputStream ois = new ObjectInputStream(fis);
      Object object = ois.readObject();
      return object;
   }
}

An this is how InternalStorage class can be used to persist and retrieve data from internal storage.

// The list that should be saved to internal storage.
List<Entry> entries = new ArrayList<Entry>();
entries.add(new Entry("House"));
entries.add(new Entry("Car"));
entries.add(new Entry("Job"));

try {
   // Save the list of entries to internal storage
   InternalStorage.writeObject(this, KEY, entries);

   // Retrieve the list from internal storage
   List<Entry> cachedEntries = (List<Entry>) InternalStorage.readObject(this, KEY);

   // Display the items from the list retrieved.
   for (Entry entry : cachedEntries) {
     Log.d(TAG, entry.getName());
   }
} catch (IOException e) {
   Log.e(TAG, e.getMessage());
} catch (ClassNotFoundException e) {
   Log.e(TAG, e.getMessage());
}