Android Studio 3.0 – Initial Impressions of Tool Support

I have been using Android Studio 3.0 since since the alpha versions, and it is good to see it finally released.

This is just some initial comments on using some common and new Android tools and libraries with the 3.0 version of Android Studio and the associated Android Gradle plugin.

Hopefully this will be useful for anyone thinking of upgrading from Android Studio 2.x.

Java 8 Finally, Maybe

Java 8 was released back in 2014, and with Android Studio 3.0 it is finally supported in Android. Finally I can say goodbye to RetroLambda (although many thanks to the authors for this very useful library).

Just be aware that many of the Java 8 language features will only be available if the minSkdVersion is 24.

Since devices running Nougat or Oreo are still in the minority, supporting older versions will continue to be an issue for a while if you want to use Java 8. Some ideas floated around to support older API version, are to have min API version flavors or  do Build.VERSION checks for the API version in the code to provide alternative code paths.

Desugar

The Jack tool chain has been replaced with the desugar tranformation process to support Java 8. Some older libraries and code may have some problems with this build stage.

JUnit 5

JUnit 5 has also been released recently, and with the help of this plugin you can use it for unit testing in Android Studio.

However if you use JUnit 4 Rules in your tests, there is limited support in JUnit 5 as they are meant to be replaced with extensions. Some Rules may be supported with the JUnit 5 migration support, but if not you will have to wait until the Rules are rewritten as extensions or not use the Rules at all.

Of course this is only for unit testing. Instrumentation tests still depend on JUnit 4 and the AndroidJUnitRunner.

Update (7 Dec 2017)

The authors of the JUnit5 plugin have stated that they now have support for JUnit 5 in instrumentation tests. I won’t be using it for a while since it requires the minSkdVersion to be 26. If anyone has tried this, please let me know how well it works.

Architecture Components, RxJava

I have also been using some of Google’s Architecture Components, but only the ViewModel and LiveData. This is another alternative to design patterns such as MVP or MVVM with Databinding.

If you use RxJava, then this will of course continue to work as it is compatible with Java 6. You may consider replacing RxJava with the more light weight LiveData for activities and fragments, and they can be adapted to each other.

Dependency Injection with Dagger

I have had no problems with Google’s Dagger, but be aware of the API changes for the Android Gradle plugin 3.0 in the gradle build file (e.g. implemention instead of compile, annotationProcessor instead of apt, etc).

See the Android Gradle plugin 3.0 migration guide.

Butterknife, Timber

Some common utilities like Butterknife and Timber for logging are working fine. I’m also using the slf4j binding for Timber without any trouble.

JRebel for Android

During the Android Studio alpha and beta process, JRebel for Android was always playing catch up with the latest version. I still have issues with the current version (2.4.14) of their free edition, so I am using instant run instead at the moment.

I’m a big fan of JRebel so I’m hoping they will have a stable version of their android plugin for Android Studio 3.0 soon.

Update (31 Jan 2018)

JRebel for Android is no longer being actively developed.

AOP with AspectJ

There are various AspectJ plugins for Android,  and the one I have been using in Android Studio 2.x was this one. Unfortunately it doesn’t support the Android plugin for Gradle 3.0 yet, but the author seem to be working on it so hopefully the support will be there soon.

Update (15 Nov 2017)

Version 3.2.0 of the GradleAspectJ-Android plugin now supports the Android plugin for Gradle 3.0. I like this plugin because it supports both aj files and annotation style aspects.

Things will get better

Of course since Android Studio 3.0 has only recently got general release, we should expect tool and library support to improve going forward.

I have only scratched the surface with some common Android tools and libraries, and there are many more around. Please let me know of your experiences with others.

Reusable Aspect Library for Android, Part 2

In part 1 of this post, we created an Android library containing aspects that could be used to intercept code in an application. However the library would require code changes in order to work with other application, and so was not really reusable as it stood.

In this part, we will modify the sample code to make the library more reusable across multiple applications.

Scenario 2 – The Pointcut in the Application

In this example, the aspect tracing code is kept in the aspect library project, but we will put the pointcut in the application.

Create the Projects

Create an Android application project and library project, and configure them as AspectJ projects in Eclipse, same as for part 1. Then add the library project to the application project, both as an Android library and to the application aspectpath.

Code Changes

1. Aspect Library

Once again put the AspectJ tracing code in the library project,  but this time the pointcut has been made abstract.

public abstract aspect BaseTraceAspect {

    /** Pointcut for tracing method flow tracing */
    protected abstract pointcut traceOperations();

    before() : traceOperations() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        log("Entering [" + sig.toShortString() + "]");
    }

    /** Implement in subaspect for actual logging */
    protected abstract void log(String msg);
}

Notice I have also made the log method abstract as well, this leaves it up to the application to determine how it wants to log the tracing output. In general any funcationality that is specific to the application should be made abstract here, and be implemented in the application.

2. Test Application

In the application project, add some code that can be intercepted by the aspect, as for part 1.

Then create another aspect file which subclasses the aspect in the library project. This aspect just implements the pointcut (and in this sample, the logging method as well).

public aspect TraceAspect extends BaseTraceAspect {

    private final static String TAG = "Aspect-Test";

    protected pointcut traceOperations(): execution(* au.com.example.test.**.testMethod(..));

    protected void log(String msg)
    {
        Log.i(TAG, msg);
    }
}

Run and Verify

Once again run the application and verify in LogCat that the aspect tracing has worked.

Sample app 2

LogCat tracing

The Sample Code

You can download the sample code for this example, aspect-lib-example_2.zip from GitHub. Follow the same instructions as for the previous example for running the sample app.

Conclusion

Now the aspect library project is reusable in other applications. An application would just need to include the library and then override the abstract pointcut to implement a concrete pointcut that is specific to it.

In the last part of this article, we will add another library to the application and show how to apply the aspects to it as well.

Reusable Aspect Library for Android, Part 1

There are various projects / tutorials / blogs out there about how to integrate AspectJ into the Android development process. They generally show you how to setup an application project to use AspectJ, with the aspects in the project itself.

However the way I tend to use AspectJ in Java projects is to try to put them into reusable libraries so that they can be applied to multiple projects. After all they are supposed to be used for cross-cutting concerns which are common to many applications. Searching the internet, I did not manage to find much information about how to do this in Android.

So here are some examples of one solution I found when using Eclipse (Windows version). If  you are not already familiar with creating and setting up Android projects in the Eclipse IDE, and with using AspectJ, have a look at the documentation for Android and AspectJ.

These are the requirements for the samples:

Note that the Android tools tend to be a bit brittle, so different versions may have changes (and bugs). So the examples may not work if you are using a different version.

Also I had the following design goals in mind:

  • keep it as simple as possible
  • stick to using Android libraries


With Eclipse you can put code in separate Java projects and either reference them from an Android application either as a project or a jar, e.g. create a ‘glue’ Android library that references a Java library.
While this might work in Eclipse, it would make things much more complicated if I wanted to use another build system (e.g. Ant) to build the application.

Scenario 1: Self-Contained Aspect Library

In the first example, we will create an android library that contains all the aspect code, and use it to apply the aspects to some code in an application.

Here are some instructions on setting up an Android library with aspects, along with some sample code.

The Test Application

This is just a very simple app to demonstrate the aspects working.

1. Create a new Android application project and add some code that the aspects can intercept.


public class MainActivity extends Activity {

private Button testButton;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 testButton = (Button)findViewById(R.id.test_button);
 testButton.setOnClickListener(testButtonListener);
 }

private OnClickListener testButtonListener = new OnClickListener() {
 public void onClick(View v)
 {
 // invoke the method to be traced
 testMethod();
 }
 };

 public void testMethod()
 {
 Toast.makeText(this, "Inside test method", Toast.LENGTH_SHORT).show();
 }

2. Add the AspectJ nature to the application project.

If you already know how to setup AspectJ in an Eclipse project, then you can skip the next bit …

To add the AspectJ nature to the application project, there are 2 ways of doing this:

a. Using the AJDT plugin
Right click on the project in the Package Explorer to bring up the context menu.

  • Click ‘Configure’
  • Click ‘Convert to AspectJ project’

Menu to convert to AspectJ project

b. Do it manually

  • Edit the ‘.projects’ file for the project.

Replace the java builder …

<buildCommand>
  <name>org.eclipse.jdt.core.javabuilder</name>
  <arguments>
  </arguments>
</buildCommand>

with the AspectJ builder …

<buildCommand>
  <name>org.eclipse.ajdt.core.ajbuilder</name>
  <arguments>
  </arguments>
</buildCommand>

and then add the AspectJ nature …

<nature>org.eclipse.ajdt.ui.ajnature</nature>

The edited file should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>ATest</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.ajdt.core.ajbuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
	</buildSpec>
	<natures>
		<nature>org.eclipse.ajdt.ui.ajnature</nature>
		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
		<nature>org.eclipse.jdt.core.javanature</nature>
	</natures>
</projectDescription>
  • Add the AspectJ runtime jar to the classpath for the project.

The jar is named ‘aspectjrt.jar’ and it is probably a good idea to use the one that came with the AJDT plugin, which should be located under your Eclipse install at ‘plugin/org.aspectj.runtime_x.x.x’.

There are various ways of doing this, but if you have AJDT installed, the easiest way would be to add it as a library in your ‘Java Build Path’ dialog. In the ‘Java Build Path’ dialog, select the ‘Libraries’ tab, and then click the ‘Add Variable’ button. Then in the ‘New Variable Classpath Enty’ dialog that comes up, select the ‘ASPECTRT_LIB’ entry and click the ‘OK’ button.

Add aspectrt.jar as variable

To make the sample code a bit more portable, rather than doing it this way,  I’ve just copied ‘aspectjrt.jar’ to a directory named ‘lib’ in the project and added it to the classpath from there.

The Aspect library

This is the Android library project that will contain the aspects.

1. Create an Android library project

2. Add the AspectJ nature to the library project (the same as for the application project)

3. For these samples I am going to show a very common usage of AOP – tracing. So add some an AspectJ tracing code to an aspect file in the library project, with the pointcut configured to intercept some code in the application project.

public aspect TraceAspect {

    private final static String TAG = "Aspect-Trace";

    // pointcut to intercept a method in the application project
    protected pointcut traceOperations(): execution(* au.com.example.test.**.testMethod(..));

    before() : traceOperations() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        log("Entering [" + sig.toShortString() + "]");
    }

    protected void log(String msg)
    {
	Log.i(TAG, msg);
    }
}

4. Add the aspect library project as an Android library for the application project.

Add aspect library project to application

5. Also add the aspect library project to the AspectPath for the application. Do this in the ‘AspectJ Build’ dialog for the application project.

For the application project, right click the project in the Package Explorer to bring up the context menu.

Then either …

  • Click ‘Build Path -> Configure Build Path …’ to bring up the project properties dialog
  • Click ‘AspectJ Build’ in the side menu

or …

  • Click ‘AspectJ Tools -> Configure AspectJ Build Path …’

In the ‘AspectJ Build’ dialog, click the ‘Aspect Path’ tab. Then click the ‘Add Project…’ button and select the aspect library project.

Add aspect library to aspectpath of application

Run the application

Now run the application in your device or emulator, making sure that the code that you want to trace is invoked.

Sample app 1

For the sample app, just click the button ‘Click to test tracing’, and then check in LogCat that the aspect tracing has occurred.

LogCat tracing 1

The Sample Code

You can download the sample code for this example, aspect-lib-example_1.zip from GitHub.

Running the sample code:

  • Unzip the zip file containing the Eclipse projects.
  • Import the projects into your Eclipse IDE.
  • The sample projects have Android 4.0 (API level 14) as the Android build target. So you need to either have API 14 present in your Android SDK installation or change the build target for all the projects to another API version.
  • Optionally you may have to adjust any application or class paths to suit your development setup.
  • Build and run the sample application project.
  • Check LogCat to see if the aspect tracing is present.

Conclusion

The problem with this example is that the aspect library isn’t really all that reusable.

If you wanted to use the library in another application, chances are you would have to changed the pointcuts to match the code you want to intercept in the new application.

In the next part of this blog, we will make some improvements to it to make it more reusable.

Advanced Testing Tips for Android, Part 2

In part 1 of this article, I discussed some of the merits of Android testing on the emulator and rooted devices. In this concluding part, I’ll have a look at the software side of things.

Tracing

It is often useful to include tracing code while developing, one common usage is to trace the entry and exit of methods calls for example.

However it is generally recommended to remove tracing (and debug) logging from releases. This can be a hassle if these trace log statements sprinkled in your code. If you are using proguard to obfuscate your release version, then that is one option you can use to disable the tracing.

Another way is to use an AOP library like AspectJ to handle tracing instead (there are various examples of how to do this in Android available on the internet, just google it).

Some advantages of using AspectJ to handle tracing are:

  • The AspectJ tracing code could be put in separate library project, which may only be included in development builds (i.e. leave out the library in the build script for the release build).
  • Use of pointcuts is more configurable, as it can be used to trace as much or as little of your code as you require. This is useful to target the tracing to areas of your code when checking for errors.

Generally I would leave general method tracing disabled, but it is sometimes useful when running automated tests, e.g. when doing Continuous Integration or running Monkey, to trace the method flow in case there are crashes or other problems.

Monkey

This is another useful testing tool, but sometimes there are sections of your code that you don’t want to be run while testing with Monkey.

In this case, you can disable functionality for those sections of code when testing with monkey using ActivityManager.isUserAMonkey().

if (!ActivityManager.isUserAMonkey())
 {
    // only run if not running in Monkey
    doSomething();
 }

In my case I used this because the app I was working on had some functionality to run other apps on the device. If this code was run during Monkey testing, then Monkey would continue to run on the secondary app rather than the main app that I wanted to test.

Another example of it’s usage is in the Android API demos (to stop Monkey running any ‘dangerous’ code) :
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/DeviceAdminSample.html

Accessory Apps for Testing

To assist in testing, it may be useful to write some additional apps to handle various accessory tasks:

  • configuration of the device before running tests
  • loading test data, for instance I wrote a simple app to load test contacts and SMS messages.
  • test for failures in intents passing, e.g. if the main app runs other apps using intents, you could use intents to run an app that deliberately fails to see how the main app handles it

Using load-time AOP to help testing and debugging

After reading this blog ‘Practical Introduction into Code Injection with AspectJ, Javassist, and Java Proxy‘, it reminded me how handy AOP tools like AspectJ are, in testing and debugging applications – particularly on servers.

How many times have you encountered a problem or bug in staging (or common test or reference) servers that you can’t reproduce in your own dev server? Ideally deployments should be consistent and reproducable so that this should never happen, but unfortunately in real projects that is not always the case.

Sometimes various issues can cause these differences:

  • manual configurations to the build process
  • continuous integration not used rigorously
  • different environmental settings on different server instances
  • different external services used in development, as opposed to a staging environment

Factors like these may lead to inconsistent builds or differing behaviour in different server environments.

I’ve found that using load-time weaving with AspectJ can be useful testing and debugging the application code on a staging server, without requiring any source code changes. The good thing is that because it doesn’t change the actual build artifacts on the file system (of course the code is changed when the affected classes are loaded!), you can remove the load-time weaving any time and revert back to the original code without having to do another build.

Here are some examples of what can be done to assist testing and debugging on a server that is not directly controlled by the developer. I’m assuming here that you are able to implement load-time weaving on the server.

Also if you are not familiar with AOP and AspectJ, else please read the AspectJ documentation or a book on AspectJ, such as the excellent AspectJ in Action.

Tracing

The generic introductory example for demonstrating how useful AOP is, seems to be tracing. The ability to add logging code to trace (program flow, method parameters and return value, etc) is very handy for debugging, particularly when using pointcuts to narrow the scope of the tracing to the sections of code that are problematic.

Here is a simple example with some test classes:

public class Customer {
  private String name;
  private String phone;
  private String address;

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getPhone() {
    return phone;
  }
  public void setPhone(String phone) {
    this.phone = phone;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
}

public class AccountService {

  public boolean addCustomer(Customer customer, String accountId, boolean isNewCustomer)
  {
    // real code to add customer to an account would be added here

    return true;
  }
}

For the tracing code, you can use the examples from the AspectJ programming guide or the book AspectJ in Action.

Then in a trace aspect class, use a pointcut to trace the code we’re interested in (in this case AccountService.addCustomer()).

pointcut traceOperations() : execution(* trace.blogexample.AccountService.addCustomer(..));

When the code is run, you might get some tracing, showing that the code was run and the parameters that were passed to the method in the pointcut.

Enter  [trace.blogexample.AccountService.addCustomer]
  [ This: trace.blogexample.AccountService@6262937c]
  [Args: (trace.blogexample.Customer@35c0e45a,ABC123,true)]
Exit  [trace.blogexample.AccountService.addCustomer]

Even more useful is if you combine the logging code with reflection to trace not only simple values, but also the contents of objects that you are interested in.
For the above example you might get tracing that shows the fields of objects passed to the method as parameters.
Hopefully the info from the tracing may be helpful in fixing a bug or problem.

Enter  [trace.blogexample.AccountService.addCustomer]
  [ This: trace.blogexample.AccountService@1d5a0305]
  [Args: (trace.blogexample.Customer@377653ae[
  name=John Smith
  phone=1234567890
  address=1 Test Street
  ],java.lang.String@54cbf30e[
  value={A,B,C,1,2,3}
  offset=0
  count=6
  hash=1923891888
  ],java.lang.Boolean@442a15cd[
  value=true
  ])]
Exit  [trace.blogexample.AccountService.addCustomer]

As I’ve mentioned, you can target where the want the tracing to occur:

  • by setting the pointcut to trace in details the areas of code that are (or that you think are) causing problems,
  • where exceptions are being thrown (using an After throwing advice)

You can also build on the AOP tracing to do other useful things, for example I have an open source project (TestDataCaptureJ) that uses tracing to capture data to use in unit testing.

Data Validation

Instead of just tracing, you can go further by doing some data validation as well.

For instance you can insert some code to validate the parameters for a business method, and log any validation errors.

Another way is to use tools, such as Contract4J, to test compliance (checking for preconditions, postconditions and invariants in the business requirements). Use load-time weaving to hook in the Contract4J configuration for business methods that you want to test.

Method Replacement

Another technique I sometimes use is to replace methods invokations in the app with test code.
This involves creating an Around advice for a pointcut that includes a method we want to replace.
Then inside the Around advice you can:
1. run another method altogether

So instead of just invoking the original method …

Object returnValue = joinPoint.proceed(args);

invoke another method with the same return type.

Object returnValue = newMethod(args);

2. run with different parameters

Invoke the original method, but pass in different parameter values (of course the parameter types must match the method signature)

Object returnValue = joinPoint.proceed(newArgs);

So using method replacement techniques you can do things like:

  • inject your own data to test a particular scenario
  • proxy external calls, e.g. for a method that uses an external service, replace with a method that returns some test data we can use for diagnosis

Summary

These are just some ideas that I have found useful when testing and debugging issues in app development. They can be easily applied to your development environment, but using load-time weaving with AOP also makes them useful when you encounter problems in a server that is not directly under your control.

Of course these techniques do not replace your standard tools and debuggers, it is just another tool in your toolbox.

TestDataCaptureJ – Capture data for your unit tests

When you are writing unit tests or doing Test Driven Development (TDD) , one of tasks you may need to do is to get some data to run your tests with. If the data that you need is fairly simple then there are various options, such as manually creating the data classes, create some mocks, stick some data in a database, etc.

However if you need a large amount of complex data, then these options can become very time consuming. This was the situation that I’ve come across myself in various projects, in particular where I need to test a the checkout stage in a online shop using data from the basket. The development environment was running on a snapshot of the production database (therefore ‘real’ data) and for the test scenarios I need the data from the shopping basket with various combinations of basket items. However the basket items were quite complex: the basket item class had about 35 fields, some of which were other objects each containing maybe 5 – 15 fields themselves.

To get all the test data I needed to test all the scenarios, I created a tool which evolved into the TestDataCaptureJ open source project that is hosted on GitHub. This is a Java development tool that can be used in java (web) applications to capture data as you run through the test scenarios. The data is logged to file, but in a format that you can just cut and paste into your unit tests (or better still, into classes that are used by your unit tests).

As an example, in the tutorial I used the jpetstore sample app from the Spring Framework. This just meant configuring the jpetstore web app to run with TestDataCaptureJ, and then going through the checkout process with some items in the basket. Then I used the generated log in some unit tests that I wrote to test part of the checkout process. This is an example of the code that was generated:

public org.springframework.samples.jpetstore.domain.Account createParam1Account_org_springframework_samples_jpetstore_domain_Order_initOrder() {

org.springframework.samples.jpetstore.domain.Account account0 = new org.springframework.samples.jpetstore.domain.Account();
account0.setUsername("j2ee");
account0.setPassword(null);
account0.setEmail("yourname@yourdomain.com");
account0.setFirstName("ABC");
account0.setLastName("XYX");
account0.setStatus("OK");
account0.setAddress1("901 San Antonio Road");
account0.setAddress2("MS UCUP02-206");
account0.setCity("Palo Alto");
account0.setState("CA");
account0.setZip("94303");
account0.setCountry("USA");
account0.setPhone("555-555-5555");
account0.setFavouriteCategoryId("DOGS");
account0.setLanguagePreference("english");
account0.setListOption(true);
account0.setBannerOption(true);
account0.setBannerName("");

return account0;
}

The tutorial also demonstrates some of the limitations of the tool as well.

Caveats

TestDataCaptureJ was really meant to handle data objects which are designed to hold data and follow JavaBean conventions, e.g.

  • objects are created using constructors
  • fields has setter methods using standard naming convention
    e.g. a field named ‘userAccountName’ would have a public setter method ‘setUserAccountName()’

Also to intercept the processing of the application in order to log the data, the test data required must be an object that is either passed to a method as a parameter, or returned from a method as a return value.

Therefore it can’t currently handle object where this isn’t the case, e.g.

  • object that are not created with constructors, e.g. if they are created using factory methods instead
  • fields without setter methods or setter methods that don’t follow the standard naming convention
  • static fields (just not implemented)
  • objects pass into methods as varargs

There is some configuration that

How it works

Basically this is just a glorified version of the common AspectJ tracing example, using weave time loading to intercept the data objects that we are interested in. Only instead of just logging the contents, there is a 2 stage process:

  1. use java reflection to store access the field data recursively and store it in some metadata classes
  2. log the data as java code to file

There is a explanation page in the documentation that goes into more detail.

Please have a look at the code (or better still, fork it and play around with it) or read the documentation if you think this might be useful to you.