Android swipe to reveal

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513 Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

More and more Android apps seem to use a swipe-to-reveal or swipe-for-action UX pattern with ListViews. This is a nice way to give (power) users fast access to certain actions. One of the downsides is that these swipe gestures are often hard to discover.

If you want to use this technique, have a look at 47 degree’s android-swipelistview library.

I ran into a small issue when trying it out. When I was building my project, I got the following error:

  1. error: Attribute "***" has already been defined

In my case this was caused by ActionBarSherlock using the same library as the android-swipelistview project. Adding an exclusion to my Gradle build script solved this.

  1. compile ('com.fortysevendeg.swipelistview:swipelistview:1.0-SNAPSHOT@aar') {
  2.  
  3.     transitive = true
  4.     exclude group: "com.android.support", module: "appcompat-v7"
  5. }

Usage in combination with SwipeRefreshLayout

If you want this swipe library in combination with the new SwipeRefreshLayout class, there is a little more work you need to do. To facilitate this, I have forked the original project and added the functionality as suggested by Keith Thompson in the issue he opened on the project site.

I ran into another issue where both the swipe-to-reveal as the pull-to-refresh actions were performed. This would happen when the ListView was at the top, the user would swipe horizontally and then pulled down. This has been fixed in my fork too.

An example of how to hook up this functionality can be found in Keith’s fork of the android-swipelistview project. The key classes to look at are “CustomSwipeRefreshLayout” in the sample project and “RefreshSwipeListView” in the library.

Other issues

The original android-swipelistview project has some other issues too:

The fixes for these issues have been committed to my fork of android-swipelistview too.

Coveralls with Cobertura

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513 Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

If you want to keep track of your test coverage and/or give others insight of the test coverage you can use Coveralls.io. Assuming you have already set up Cobertura, it is quite easy to get Coveralls integrated. There is an existing Gradle plugin to convert and send Cobertura reports to Coveralls. Have a look at “Robolectric and Cobertura with Gradle“, if you want to know how to set up Robolectric and Cobertura.

Gradle setup
First add a dependency to “org.kt3k.gradle.plugin:coveralls-gradle-plugin:0.3.0”.
Apply the “coveralls” plugin.
After that make sure that the cobertura plugin generates an XML report as well. In the Cobertura configuration, add the following:

  1. coverageFormats = ["html", "xml"]

If you’re not running on Travis (pro) you may need to add a service name by specifying “service” in the coveralls plugin configuration.

Environment setup
Add a “COVERALLS_REPO_TOKEN” environment variable containing your coveralls token.

Now that everything is set up, all you need to do is run the below to send a coverage report to Coveralls.

  1. gradle coveralls

If you want to look into the Gradle Coveralls plugin in more detail, have a look at the coveralls-gradle-plugin project page.

Robolectric and Cobertura with Gradle

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513 Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

Update 2 (July 29 2015): Even better! Just use unit testing support of the Android Gradle plugin. As of Robolectric 3.0 you also no longer need any Robolectric Gradle plugin.

Update (Apr 03 2015): You can now just use the Robolectric Gradle plugin. It works like a charm and avoids a lot of manual setup.

DEPRECATED

Recently I have been working to set up code coverage reports for an Android project using Cobertura. I had already set up Robolectric manually and there is a working Cobertura Gradle plugin available. This left me with figuring out how to hook up the two. In general the following steps are needed to use Cobertura with any testing framework:

  • Make sure you fork the JVM.
  • Point the “net.sourceforge.cobertura.datafile” system property to your “cobertura.ser” file location.
  • Add the instrumented classes to the front of the class path.
  • Add cobertura classes to the class path.

You can read more about Cobertura setup in the “Ant Task Reference” on the Cobertura Wiki.

My first problem was that the Cobertura plugin automatically adds the Java plugin. The Android plugin doesn’t play nice with the Java plugin, so that had to be solved. The solution was to put all Coberture related configuration in its own Gradle build file without the Android Gradle plugin applied. All the Cobertura plugin needs to do after all is inspect compiled (and instrumented) code.

After this it was a matter of configuring the Cobertura and Robolectric plugins correctly and running tasks in the right order.

Cobertura Gradle configuration
To be able to instrument all classes, I pointed the “coverageDirs” property to a list of build folders from my project and subprojects.
NOTE: You may need to set up the “auxiliaryClasspath” if you get some “ClassNotFoundException” errors.

If you want the source code to show up correctly in your reports, make sure to configure the “coverageSourceDirs” property.

Cobertura will inspect all classes you point to in the “coverageDirs” property. To exclude any classes generated by the Android framework, add the following to the “coverageExcludes” property:

  • “.*\\.package-info.*” for package-info files,
  • “.*\\.R.*” for generated R classes and
  • “.*BuildConfig.*” for any BuildConfig classes.

Robolectric Gradle configuration
Add the following to you Gradle build file so the instrumented classes are able to write their reports:

  1. systemProperties["net.sourceforge.cobertura.datafile"] = "your_cobertura_ser"

In the Robolectric test compile dependencies, make sure you add the path to the instrumented classes in front of everything else.

Don’t forget to add “net.sourceforge.cobertura:cobertura:2.0.3” to your test compile dependencies as well.

Putting it all together
Now all plugin configuration is done, you can run tests and have the coverage reports generated by executing the following commands. Note that this depends on a previous “gradle assembleDebug” run.

  1. gradle clean cobertura -x generateCoberturaReport
  2. gradle robolectricTest
  3. gradle cobertura -x instrument -x copyCoberturaDatafile

The first Cobertura run will instrument all the classes, but not generate any reports. After that all Robolectric tests are run. Finally, the second Cobertura run will generate the coverage report.

I hope this helps you setting up Cobertura for your Android projects.

Privileged Aspects

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513 Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

When you are using Aspect-Oriented Programming with AspectJ and you want to get around Java restrictions in your Aspect, you can declare the Aspect “privileged“.

Say you perform some logging from your Aspect, but the member you want to access has no (public) accessor method. You could create a public getter method and use that. Better would be to make the Aspect privileged so it can access the member even though it is declared private. This scenario is demonstrated in the snippets below.

Given the following class “Foo”.

  1. ppublic class Foo {
  2.     private String bar;
  3.  
  4.     private void doSomething() {
  5.         bar = "bar";
  6.     }
  7. }

The Aspect would look something like this.

  1. public privileged aspect FooLogging {
  2.     protected pointcut myClass(): within(Foo);
  3.     private pointcut doSomethingMethod(): myClass()
  4.             && execution(doSomething());
  5.  
  6.     after(): doSomethingMethod() {
  7.         String value = ((Foo) (thisJoinPoint.getThis())).bar;
  8.         // Logging goes here.
  9.     }
  10. }

There is one limitation to privileged Aspects though:

Privileged aspects are not supported by the annotation style.

See “Aspect Declarations” in “Chapter 9. An Annotation Based Development Style” of the “The AspectJ 5 Dev Kit Developer’s Notebook“.

Loading Contact photos with Picasso

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

The Picasso image downloading library has an interesting feature that I just stumbled upon. It can load Contact photos based on a passed in Contact Uri containing the ContactsContract.Contacts.LOOKUP_KEY. It is as simple as:

  1. Uri uri = Uri.withAppendedPath(
  2.     ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
  3. Picasso.load(uri).into(myImageView);

It doesn’t seem to be mentioned on the Picasso website, but it is a very useful feature.

If you want to know exactly how Picasso loads the Contact photo, have a look at the ContactsPhotoBitmapHunter class.

Android RenderScript support library

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513 Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

A while back I wrote about RenderScript and the lack of a support library. Now Google has released the support library for RenderScript, making it a lot more accessible for a lot of developers.
Usage is really simple, just import the correct classes:

  1. import android.support.v8.renderscript.*;

And target Android API 18 when building:

  1. renderscript.target=18
  2. renderscript.support.mode=true
  3. sdk.buildtools=18.1.0

There are unfortunately some limitations, but nothing that’s a real show-stopper.

“Allocation.USAGE_IO_INPUT and Allocation.USAGE_IO_OUTPUT are not currently available in the RenderScript Support Library.”

“Devices running Android 4.2 and earlier will always run their RenderScript applications on the CPU, while devices running Android 4.3 or later will run their RenderScript applications on whatever processors are available on that particular device.”

“Support Library versions have to be precompiled to support all possible platforms, there is a performance hit when running the precompiled scripts compared to runtime compilation on Android 4.3.”

Read the full details in Google’s blog post.

Android fragmentation 2013

At last  year’s DroidCon in London, Robin Puthli’s talked about Device Fragmentation among Android devices. Open Signal has just posted a new visualization of device fragmentation for 2013.

Fragmentation is both a strength and weakness of the Android ecosystem. When comparisons are made between Android and iOS the issue of different API levels, and the vastly different devices running them, is often emphasised. In this report we examine the extent of Android fragmentation and analyse its impact on both users and developers.

Read the full article on opensignal.com.

SQLite on Android

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513 Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513 Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

In the past week I started working with SQLite databases on Android.

It can be quite cumbersome to explore the data stored in the DB on an actual device. What has helped me a lot is grabbing the DB from the device and loading the SQLite DB in a third party SQLite browser / manager. This will give you a lot more flexibility on exploring the data that is stored and will also be a great help for testing your queries.
You can retrieve your database from the device using ADB:

  1. adb pull /data/data/[app_package]/databases/[db_file] .

I’ve been using SQLiteBrowser to explore the DB and test my queries.

One thing I noticed is that inserting around a hundred rows took quite some time, about 350ms. I was inserting one row at a time and after some Googling on how to insert multiple rows in one query, I found an answer on StackOverflow. The suggestion was to do something like the following:

  1. INSERT INTO 'tablename'
  2.     SELECT 'data1' AS 'column1', 'data2' AS 'column2'
  3.     UNION SELECT 'data3', 'data4'
  4.     UNION SELECT 'data5', 'data6'
  5.     UNION SELECT 'data7', 'data8'

After trying this approach it cut the insertion time in half near the 170ms mark, still quite slow.
Some more searching brought me to an article about “Speeding up SQLite insert operations“. What this article advises is to use transactions, an example:

  1. database.beginTransaction();
  2. for (...) {
  3.     database.insert(...);
  4. }
  5. database.setTransactionSuccessful();
  6. database.endTransaction();

Using this technique the insertion was sped up to roughly 25ms, much better!

As an alternative to using a database, you could just store the data on disk. This works fine especially when you just use a database to store data and don’t need to sort it or do more complex queries. Even if you needed sorting, you could use the SortedMap class.

IntelliJ keyboard shortcuts

Recently I switched from Eclipe to IntelliJ and that meant getting to know IntelliJ’s keyboard shortcuts. Below is a list of the shortcuts I use most.

Generic
crtl + n = Open resource.
ctrl + f4 = Close window.
alt + [left/right arrow] = Move to the window on the left/right.
ctrl + shift + f = Find in path, i.e search in whole project.

Text operations
ctrl + d = Duplicate line.
ctrl + y = Remove line.
ctrl + shift + [up/down arrow] = Move line up / down.
ctrl + g = Navigate to line.
ctrl + shift + u = Toggle case.

Code
ctrl + q = Quick docs (floating documentation window when having selected a class, method, member).
ctrl + f12 = Show members.
alt + f7 = Find usage.
shift + f6 = Refactor > rename.
ctrl + alt + l = Format.
ctrl + alt + [left/right arrow] = Back / Forward.
alt + insert = Generate code, i.e. constructor, getters/setters.

Global Exception handling in Android

Warning: Illegal string offset 'language' in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 510 Warning: ksort() expects parameter 1 to be array, string given in /var/www/vhosts/ansuz.nl/subdomains/blog/httpdocs/wp-content/plugins/igsyntax-hiliter/classes/frontend.php on line 513

To be able to catch any exception you may encounter that isn’t part of a try-catch-clause, you can use the Thread.setDefaultUncaughtExceptionHandler( Thread. UncaughtExceptionHandler ) method.

In the handler you can then perform whatever action you want. Don’t forget to call “System.exit()” though, because otherwise this won’t work!

A simple example:

  1. public class SomeActivity extends Activity {
  2.  
  3.     private static final String LOG_TAG = "SomeActivity";
  4.  
  5.     @Override
  6.     protected void onCreate(Bundle savedInstanceState) {
  7.         super.onCreate(savedInstanceState);
  8.         Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
  9.             @Override
  10.             public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
  11.                 Log.e(LOG_TAG, "OMG! Uncaught Exception!");
  12.                 // Without calling System.exit() this will not work.
  13.                 System.exit(2);
  14.             }
  15.         });
  16.     }
  17. }

For some more details have a look at “Using Global Exception Handling on android” on StackOverflow.com.