Mocking Static Methods in Android: Let’s Wrap it up

When writing local unit tests in Android, one of the limitiations that you face is that the tests are run against a version of android.jar that does not have any code. As the documentation explains, any dependency on Android code must be mocked.

A quick example of a simple unit test:

public class ClassUnderTest {

public String methodUnderTest(String str)
{
    if (PhoneNumberUtils.isGlobalPhoneNumber(str))
    {
      return "yes";
    }
    else
    {
      return "no";
    }
  }
}

@RunWith(JUnit4.class)
public class TestThatFails {

private ClassUnderTest classUnderTest;

  @Before
  public void setup() {
    classUnderTest = new ClassUnderTest();
  }

  @Test
  public void testTheClass() {
    String result = classUnderTest.methodUnderTest("1234");
    assertEquals("yes", result);
  }
}

When this test is run, it will fail with the following error:

java.lang.RuntimeException: Method isGlobalPhoneNumber in android.telephony.PhoneNumberUtils not mocked. See http://g.co/androidstudio/not-mocked for details

The class we are testing has a dependency on the Android utility library PhoneNumberUtils. In order for the test to run successfully, this Android dependency must be mocked.

All the example code for this post is available at this gist.

Mockito: No to Static Methods

Google’s suggested way to mock Android dependencies is to use Mockito. This would generally be fine, however in our example this will not work because Mockito does not support mocking static methods.

This discussion shows that the Mockito contributors consider static methods to be an anti-pattern for various reasons, e.g.

  • The dependency on the static method becomes hard wired in the code.
  • This makes mocking and testing difficult.

Hence they do not support it as they don’t want to encourage poor design.

So what are some other way to make our test work?

  • If this was plain old Java instead of Android, I could have used PowerMockito to mock the static methods. However I have found using PowerMock to be problematic in Android.
  • If you only use a few static methods, you could just copy the code into your app assuming the the source was available. Of course this means more code to maintain, and is not sustainable if you use a lot of static methods.
  • You could wrap the static method call and internally delegate to the static method. The wrapper could then be mocked. This is the option we will be discussing.

Wrapper Classes

One solution is to create a wrapper class for the Android classes that have the static method, and add that wrapper as a dependency.

public class PhoneNumberUtilsWrapper {

  public boolean isGlobalPhoneNumber(String phoneNumber)
  {
    return PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber);
  }
}

public class ClassUnderTestWithWrapper {

  private PhoneNumberUtilsWrapper wrapper;

  public ClassUnderTestWithWrapper(PhoneNumberUtilsWrapper wrapper) {
    this.wrapper = wrapper;
  }

  public String methodUnderTest(String str)
  {
    if (wrapper.isGlobalPhoneNumber(str))
    {
      return "yes";
    }
    else
    {
      return "no";
    }
  }
}

Here I have created a wrapper class for PhoneNumberUtils which is now a dependency of the class under test.

@RunWith(JUnit4.class)
public class TestWithWrapper {

  @Mock
  PhoneNumberUtilsWrapper wrapper;

  private ClassUnderTestWithWrapper classUnderTest;

  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);

    classUnderTest = new ClassUnderTestWithWrapper(wrapper);
  }

  @Test
  public void testTheClass() {
    when(wrapper.isGlobalPhoneNumber(anyString())).thenReturn(true);

    String result = classUnderTest.methodUnderTest("1234");
    assertEquals("yes", result);
  }
}

Because the wrapper class can be mocked, and the method call in the class under test is not static, the test can now pass.

One problem with this solution is when the class under test depends on static methods from many Android libraries. For instance, what happens if the class under test also needs to use TextUtils, DateUtils, etc. Suddenly you end up with lots more boilerplate code, more constructor parameters, etc.

Wrapper Methods

Another way is to wrap the static method call in a non-static method in the class under test.

public class ClassUnderTestWithWrappedMethod {

  public String methodUnderTest(String str)
  {
    if (isGlobalPhoneNumber(str))
    {
      return "yes";
    }
    else
    {
      return "no";
    }
  }

  // can't be private access
  boolean isGlobalPhoneNumber(String phoneNumber)
  {
    return PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber);
  }
}

In order for this to work, in the test we have to use Mockito spy. Also note that the wrapped methods have to be accessible in the test, and therefore can’t be private.

@RunWith(JUnit4.class)
public class TestWithWrappedMethod {

  private ClassUnderTestWithWrappedMethod classUnderTest;

  private ClassUnderTestWithWrappedMethod classUnderTestSpy;

  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);

    classUnderTest = new ClassUnderTestWithWrappedMethod();
    classUnderTestSpy = Mockito.spy(classUnderTest);
  }

  @Test
  public void testTheClass() {
    doReturn(true).when(classUnderTestSpy)
    .isGlobalPhoneNumber(anyString());

    String result = classUnderTestSpy.methodUnderTest("1234");
    assertEquals("yes", result);
  }
}

Here we are running the test on the spy class, which will delegate method calls to the real class under test. However we can create stubs for the methods that wrap the static method calls to Android libraries.

As I have mentioned, one disadvantage is that the wrapped methods cannot be private, which is not ideal from an OO design point of view. But then you have to make similar compromises if you are using libraries such as Dagger or Butterknife.

Conclusion

Both of these wrapping solutions can work, but it’s probably a good idea to be consistent and stick with doing it one way if you can. Which method works better may depend on your app architecture, e.g. are you using dependency injection.

Static Methods: Good or Bad? Does it matter?

In this post I am not getting into the argument about whether static methods are good or bad design (although my personal opinion is that their use should be limited). There are plenty of arguments about this issue on the internet already.

However, in the Java world they are a fact of life.

Many utility classes in Java, Android and many popular libraries are not real OO classes, but collections of procedural functions. The functions are often written as static methods and grouped by functionality.

Whether you like static methods or not, we all have to learn to deal with them in a pragmatic way.

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.

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.

Android UI Test: Mocking the ViewModel with or without Dagger? Part 2

In the first part of this post, I explored the approach of setting up a UI test with a mock ViewModel without using Dagger 2 for dependency injection. I used the GithubBrowserSample app from the Architecture Components sample code to demonstrate disabling Dagger for UI testing, even though the app itself uses Dagger.

Now, using Dagger

There are various ways of using Dagger to provide fake or mock version of dependencies for testing. Generally they involve writing test versions of the component and module classes.

Then when the Espresso test is run, somehow the Dagger object graph that is built (incorporating the mock dependencies provided by the test module) is used instead of the one used just for the app. Some of the ways to do this includes:

  • Include a hook into the application class to replace the Dagger components with the test versions.

http://blog.sqisland.com/2015/04/dagger-2-espresso-2-mockito.html

  • Once again create a test version of the application class in the androidTest directory. Here the test application would be a subclass of the app application class where the code to build the Dagger graph is overriden with the test version.

http://blog.sqisland.com/2015/12/mock-application-in-espresso.html

Of course, this would mean writing a custom test runner to use instead of AndroidJUnitRunner in the gradle build file.

public class YourApp extends Application implements hasActivityInjector {

  @Inject
  DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
  .
  .
  .
  @Override
  public DispatchingAndroidInjector<Activity> activityInjector() {
    return dispatchingAndroidInjector;
  }
}

// The test app in the androidTest directory
public class TestApp extends YourApp {

  @Override
  public AndroidInjector<Activity> activityInjector() {
    return new AndroidInjector<Activity>() {
      @Override
      public void inject(Activity instance) {
        // inject the fake / mock dependencies into the activity
        // e.g.
        .
        .
        .
        ((YourActivity)instance).viewModelFactory = ...
      }
    };
  }
}

Other options I came across in my research include:

  • There is the DaggerMock library that uses a JUnit Rule to override Dagger objects. This is a nice idea, but currently DaggerMock only has limited support for Dagger Android. In particular it does not handle abstract modules and methods which some of the Dagger Android annotations depend on.
  • Include a hook in the activity to set dependencies.

https://blog.stylingandroid.com/architecture-components-summary/

Disadvantages, again

As I mentioned in the previous post, any of these approaches that uses a custom test application class for instrumentation testing would apply the same Dagger object graph to all the tests. This is not suitable for my situation where I only want to mock the ViewModel for the UI tests, but use the real one for other tests.

Other ways require making code changes to the app just to accommodate testing. This is a bit of a hack and not good design.

One Possible Solution

The solution I decided to use was based on this gist. The test module was used to create a AndroidInjector that would inject a custom ViewModel factory into the test activity. In turn the custom ViewModel factory would provide the mock ViewModel.

.
.
return new AndroidInjector<MyActivity>() {
  @Override
  public void inject(MyActivity instance) {
    // create the viewmodel mocks
    MyViewModel viewModel = Mockito.mock(MyViewModel.class);

    // create the livedata used to return results
    MutableLiveData<Data> returnedData = new MutableLiveData<>();
    when(viewModel.getData()).thenReturn(returnedData);

    // set test data
    Data expectedData = ...
    returnedData.setValue(expectedData);

    // set the custom viewmodel factory that just returns the mocks
    instance.viewModelFactory = ViewModelUtil.createFor(viewModel);
  }
};

This approach did have the downside of requiring a lot of boilerplate code. But it also allowed me to only mock the ViewModel for the UI tests, without affecting the other tests.

Disclaimer

Please note that the opinions expressed in this post are not meant to apply to all instrumentation testing with Dagger.

They are only for the specific use case of trying to mock the ViewModel for my UI tests, while not affecting other instrumentation tests.

 

Android UI Test: Mocking the ViewModel with or without Dagger?

An Android app I’m currently working on has the following architecture:

When it came to testing the views , I wanted to write some UI tests using Espresso. These would just test just the activities and fragments with a mock backend.

With the Architecture Components I thought this would be fairly simple since all the interactions between the view and the backend services should be done through the ViewModel. Hence all I would need to do is to provide a mock ViewModel (in my case using Mockito).

Additionally I wanted to find a solution that:

  • was simple and straightforward, without the need for workarounds or hacks if possible
  • did not require any changes or additional code in the app just to accommodate testing

Looking at the Google sample code – no Dagger for UI Tests!

Since Google provides sample code for the Architecture Components, that’s the first place I looked. In particular the GithubBrowserSample seemed to be what I was after, this is from the README:

UI Tests

The projects uses Espresso for UI testing. Since each fragment is limited to a ViewModel, each test mocks related ViewModel to run the tests.

However, when I looked at the sample code for their UI tests, I was in for a surprise. Although the sample app itself uses Dagger DI, the UI tests do not.

This differs from most examples of testing Dagger applications, where it is advocated to write additional Components and Modules to inject fake dependencies for testing.

How it is done? The Setup.

Since I couldn’t find any documentation for these UI tests , here is a quick summary of how the GithubBrowserSample apps mocks the ViewModel without using Dagger. This basically involves using test version of the application and activity classes which do not invoke the Dagger injection code.

ViewModel Factory

Although it is possible to inject a ViewModel into an activity or fragment with Dagger, I will be using a custom ViewModel factory and injecting that instead. This is done for the following reasons:

  • Injecting a ViewModel class is only possible for ViewModels that have a default (empty) constructor. If the ViewModel constructor has parameters, then you need to inject a factory class that implements ViewModelProvider.Factory.
  • It seems to be a common pattern when using Dagger with the ViewModel to create a Module to encapsulate the ViewModel injection code. This Module would bind the ViewModel classes used in the app into a map. It would also provide the ViewModel factory class, which in turn uses the map to create the ViewModel classes. This is the pattern used in the GithubBrowserSample.

Here is a brief description of the UI tests for the fragments in the sample code:

  • Create a test application class.

This is just a dummy application class that does not invoke the Dagger code that builds the object graph.

https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/androidTest/java/com/android/example/github/TestApp.java

  • Create a test activity class.

This is just a dummy activity class to contain the fragment to be tested. It allows the fragment to be inserted into it.

https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/debug/java/com/android/example/github/testing/SingleFragmentActivity.java

This test runner will used the test application class instead of the application class for the app.

https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/androidTest/java/com/android/example/github/util/GithubTestRunner.java

@Override
 public Application newApplication(ClassLoader cl, String className, Context context)
 throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   return super.newApplication(cl, TestApp.class.getName(), context);
}
android {
  .
  .
  .
  testInstrumentationRunner "com.android.example.github.util.GithubTestRunner"
}

How it is done? The UI Test.

The GithubBrowserSample has several UI tests for different fragments, but they follow the same basic pattern. Let’s use this one as an example:

https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/androidTest/java/com/android/example/github/ui/user/UserFragmentTest.java

Remember that when the UI tests are run, there is no Dagger dependency injection.

  • Use the test activity class to hold the fragment to be tested, instead of the activity used in the app. This is done in the ActivityTestRule used in setting up Espresso tests.
@Rule
public ActivityTestRule&lt;SingleFragmentActivity&gt; activityRule =
new ActivityTestRule&lt;&gt;(SingleFragmentActivity.class, true, true);
  • Before the test is run, setup the mock ViewModel.
@Before
public void init() {
.
.
  viewModel = mock(UserViewModel.class);
  when(viewModel.getUser()).thenReturn(userData);
  when(viewModel.getRepositories()).thenReturn(repoListData);
.
.
}
  • Set the ViewModel factory field in the fragment (which would have been injected in the app) to a fake factory class that just passes the mocked ViewModel. Of course the field needs to be accessible from the test class for this to happen (i.e. public or default package access).
@Before
 public void init() {
.
.
  fragment.viewModelFactory = ViewModelUtil.createFor(viewModel);
.
.
 }
  • Put the fragment into the test activity.
@Before
 public void init() {
.
.
.
  activityRule.getActivity().setFragment(fragment);
 }
  • Because this fragment uses LiveData to get data from the ViewModel, the test data is inserted into the LiveData returned from the mock ViewModel.
@Test
public void loadingWithUser() {
  User user = TestUtil.createUser("foo");
  userData.postValue(Resource.loading(user));
.
.
}

A simple approach

That’s it.

With this approach there is no need to worry about the Dagger configuration. Just mock the ViewModel to return the data you want for the Espresso test.

Disadvantages

  1. Using a custom test runner and test application means that all of instrumentation tests in the androidTest directory will have Dagger disabled.

But what if you have other instrumentation tests where you do want to use the Dagger injected classes, in additition to the UI tests. You don’t have the flexibility of deciding whether to enable / disable the Dagger DI on a test by test basis.

2. If you are using the Dagger Android library, then this approach will work with fragments, but not with activities. This is because an AndroidInjector is used in the onCreate() method of the activity to inject the dependencies.

@Override
public void onCreate (Bundle savedInstanceState) {
  AndroidInjection.inject(this);

  super.onCreate(savedInstanceState);
.
.
}

In the next post, I will explore some of the options if we want to mock the ViewModel in the UI tests with Dagger.

Groovy and Dagger 2 Android Example

I decided to use the Groovy language for an Android app I was working on. Luckily it was fairly straightforward, but I noticed that the number of blogs and examples available to demonstrate using Groovy for Android development are far fewer than Java ones. Not only that, but many of them were out of date.

This is particularly true if you want to use libraries that are not straightforward coding, such as Dagger 2.

I was intending to write a simple proof-of-concept app to start with, to verify that I could use Dagger 2 and Groovy together. Then I found this example app on Github.

https://github.com/cvoronin/android-groovy-swissknife-dagger2

However this simple Dagger 2 example did now show how to use the @Inject annotation (which is my preferred way to do Dependency Injection into activities), so I created a fork that did.

https://github.com/davidwong/android-groovy-swissknife-dagger2

Note that you will need to use an up-to-date version of Groovy (2.4.x) to get Groovy and Dagger 2 working on Android.

Code Changes

I only had to make a few code changes to use @Inject, you can check the commits in the project to see what they were.

Firstly in the component interface (in the example, it is called demo.simplegroovyapp.component.VehicleComponent), I added a statement that would inject the dependency objects into the activity.


void inject(MainActivity mainActivity)

Then in the activity class (demo.simplegroovyapp.MainActivity) add the @Inject annotation to the field that was to be injected. The other important change I made was to add the public access modifier, I’ll explain later why this is necessary.

In other words, from this:


Vehicle vehicle

to this:


@Inject
public Vehicle vehicle

In the onCreate() method, this line was added to inject the dependencies into the activity.


vehicleComponent.inject(this)

I also commented out the statement that was previously used to manually retrieve the Vehicle object, as it was no longer necessary.


//vehicle = vehicleComponent.provideVehicle()

That’s it!

Property or Field?

In Groovy it is quite common to see data in a class being defined without an access modifier (public, protected, private).


Vehicle vehicle

Likewise in many Dagger 2 Java examples I’ve seen, the @Inject annotation is used on fields without the access modifier.


@Inject

MyPresenter mypresenter;

However when this is done in Groovy, you are specifying a property, not a field.

http://groovy-lang.org/objectorientation.html#_fields_and_properties

Hence Dagger can’t inject the Vehicle object into the activity, even with the @Inject annotation. Once the public access modifier is added, then Dagger works as expected.

 

Another Defection to Android Studio

Like many other developers out there, I have been using Eclipse as my main IDE for many years now. However for Android development I have decided to take the plunge and migrate to Android Studio (especially since it has finally been released).

Here is a blog post I found that closely echoes what I have long thought regarding the issues with Eclipse:

http://engineering.meetme.com/2014/02/a-tale-of-migrating-from-eclipse-to-android-studio/

Build, build, build

For me, another reason was that the Ant build files I was using to handle building different versions (free vs paid, dev vs release, etc) were getting too complicated to manage easily. So I can now change over to Gradle at the same time, since that’s what Android Studio uses by default.

Gradle has the concept of build variants to handle building different versions of an Android app.

The Recurring Eclipse Re-install

Here are some other problems that I personally have had with using Eclipse.

  • Plugins, well not the plugins themselves, but having too many plugins. I’ve found that having lots of plugins in one Eclipse installation can cause Eclipse to misbehave , especially after several updates. There are several ways I use to get around this:
    • Keep separate Eclipse installations for different types of development, e.g one for Java, one for Android, one for Cloud, etc. Therefore each installation will only have a few plugins relevant to the type of development. However this is not always convenient if a project does require multiple types of development.
    • Every so often, when Eclipse starts to play up, do a fresh re-install of Eclipse (along with the latest version of the plugins required).
  • Intermittent miscellaneous bugs, e.g. cut and paste stops working, builds not alway done automatically, etc. A lot of these issues are more of a nuisance rather than being a serious problem, but all the same it tends to kill your productivity (and isn’t that why we use IDE’s in the first place?).

No Pain, No …

Make no mistake, despite what the Android Studio documentation might try to tell you, migrating a non-trivial project will take some time and probably involve some pain. But worth the effort I think.

User changes for Address Location Finder

I’m currently working on upgrading my app Address Location Finder. While most of the changes are internal improvements or bug fixes, there are 2 major changes for users.

1. The map will be dropped from the app.

The simple built-in map screen will be removed from the app for the next version. In the future it will come back as an optional add-on.

Why?

I was getting quite a few error reports from users trying to run the app on devices that did not have the mapping requirements.

One of the requirements stated in the Google Play app store for the app was:

– device that supports the standard Google Mapping API (not the same as having the Google Maps app installed)

This means the manufacturers need to have licensed the Google Mapping API v1 for the device in order for the map in Address Location Finder to work. Unfortunately it may be difficult for users to know whether their device has this requirement or not, possibly resulting in the app crashing.

So, removing the map from the app will remove this requirement and allow it to run on more devices (as well as reducing app crashes).

The map will become an optional add-on app for a future version of Address Location Finder.

2. The app will require Android 4.0.3+ to run.

The minimum API level to run the app will be raised to 15, which means it will now require Android version 4.0.3+ on the device to run.

Why?

The original minimum API level required for Address Location Finder was 8 (Android 2.2).

According to the Google dashboard for platform version, devices running Android 2.x now account for only about 10%.

Supporting old versions requires a fair bit of additional work

  • needs more testing
  • requires additional code, e.g. Android support library, to implement newer Android functionality
  • may require internal version checks for functions that would not work on old versions, possibly with alternate code

This all means it takes longer for updates of the app to come out. The diminishing returns in supporting the old versions is not really worth the extra effort and time.

Users with Android older than 4.0.3 who have already installed the app can just continue to use the old version of the app. They should not even see the new version of the app when it comes to the Google Play app store, since the store applies various filters to determine which apps to display (include the minimum Android version require to run).

Help! my Android USB Connection is dropping out

After updating Android on a phone that I use for testing, I started having problems when I connected it up to my PC. The USB connection would be there when I connected the cable, but then would seem to drop out after a short time. Sometimes it would disappear after 10 seconds, sometimes a couple of minutes, sometimes when I started up DDMS or Eclipse.

Very frustrating, but I hoped it would be a quick fix. But an hour later …

I guess I’m writing this as a cautionary tale for myself about going through proper procedures for problem solving instead of just guessing.

Firstly I tried to isolate the problem:

  • use a different USB port
  • use a different USB cable
  • try another Android device

From this I determined that the problem was with the phone, an old Nexus S that I use for testing older hardware and Android versions. Since I had just updated the Android version on the phone, I just jumped to the conclusion that it must have been a USB driver problem.

So next I made sure my Android SDK installation was up-to-date, and then updated the Android USB driver from it. Made no difference.

Then I tried uninstalling and re-installing the USB driver. Still not working.

At this point I was out of ideas and just went away for a bit.

Tip: When you hit a brick wall when trying to fix a problem, sometimes it can be helpful just to go away from it for a bit. Work on something else, go for a walk, have a coffee break, whatever. Let your subconscious do the work.

When I came back later, I remembered that I’ve had other intermittent issues with the phone since it was quite old. So I did what I should have done in the first place, the golden rule about fixing tech equipment.

Turn it off, wait, then turn it on again. Working now!

Guess this shows that it is easy sometimes to forget the basics.

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.