Update the AndroidManifest Version Number automatically

Recently I needed to automate the update of the versionName element in the AndroidManifest.xml file. This needed to be timed stamped and updated with the correct version number when a build was run. We use maven as part of the build, a few plugins come in handy. We want to use POM’s version number so that tools like the maven-release-plugin or maven versions plugin can be used. When these are run the new version number should reflect in the built APKs.

The following magic added to the build portion of the pom handles this.

<plugins>
   <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>build-helper-maven-plugin</artifactId>
      <version>1.8</version>
      <executions>
         <execution>
            <id>parse-version</id>
               <goals>
                  <goal>parse-version</goal>
               </goals>
               <phase>validate</phase>
          </execution>
       </executions>
    </plugin>
    <plugin>
       <groupId>com.google.code.maven-replacer-plugin</groupId>
       <artifactId>maven-replacer-plugin</artifactId>
       <version>1.4.1</version>
       <executions>
         <execution>
            <id>replace-version</id>
            <phase>validate</phase>
            <goals>
               <goal>replace</goal>
            </goals>
         </execution>
       </executions>
       <configuration>
          <file>AndroidManifest.xml</file>
          <replacements>
              <replacement>
                 <token>0.0.0</token>									<value>${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.${maven.build.timestamp}</value>
              </replacement>
          </replacements>
          <quiet>false</quiet>
       </configuration>
   </plugin>
</plugins>

You can add this as part of a profile, and only enable it when you are building say on Jenkins or when you are doing a release. Your AndroidManifest.xml should have the versionName value set to 0.0.0, and when the build runs with the profile enabled it’ll replace this with the pom’s version and also add a time stamp.

Posted in android, maven, release engineering | Leave a comment

Jersey + Jetty = less hair

This is mainly for future me when I run into this problem again. I needed to use Jersey 2.x and had setup an embedded Jetty server for some integration testing. One portion needed to get the parameters from a POST request and needed to pass on the HttpServletRequest. However, injecting the HttpServletRequest always returned empty values for the params. Jersey was consuming them before hand. In order to get around this, I had to implement a subclass of HttpServletRequestWrapper, here is the underlying code:

public class JerseyMultiValueMapWrapper extends HttpServletRequestWrapper {

   MultivaluedMap<String, String> oAuth2Params;
   public JerseyMultiValueMapWrapper(HttpServletRequest request) {
     super(request);
   }
	
   public JerseyMultiValueMapWrapper(MultivaluedMap<String, String> params, HttpServletRequest request) {
     super(request);
     oAuth2Params = params;
   }
	
   @Override
   public String getParameter(String name) {
     return oAuth2Params.getFirst(name);
   }
}

You can then pass this along to the API that expects the HttpServletRequest. I needed this mainly when working with the Apache Oltu api, as it only accepted HttpServletRequests and kept failing validation due to missing parameters.

Hopefully this helps some others.

Posted in java, open source | Leave a comment

Findbugs and Android

Recently I needed to add FindBugs to a android-maven build. This itself is easy enough.

<profile>
   <id>findbugs</id>
   <build>
     <plugins>
       <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>findbugs-maven-plugin</artifactId>
          <version>2.5.2</version>
          <executions>
             <execution>
               <phase>package</phase>
               <goals>
		<goal>findbugs</goal>
               </goals>
               <configuration>
                  <findbugsXmlOutput>true</findbugsXmlOutput>
                  <failOnError>false</failOnError>
                  <excludeFilterFile>${basedir}/findbugs-filter.xml</excludeFilterFile>
               </configuration>
            </execution>
          </executions>
       </plugin>
     </plugins>
   </build>
</profile>

The above will analyse the classes as part of the package proecess. This is fine, however, the generated R.java file typically produces class names that don’t follow the java naming standard. Since there is nothing that can be done about this, we need to exclude this extraneous information from the generated xml analysis. Fortunately findbugs offers a filter mechanism.

The above excludeFilterFile entry refers to a findBugs filter that contains the necessary information to exclude the R.java file. Typically this is generated in your top level package. For example to
exclude the Class naming error from the report you can have your findbugs-filter.xml look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
   <Match>
     <Package name="us.nineworlds.serenity"/>
     <Bug pattern="NM_CLASS_NAMING_CONVENTION" />
   </Match>
</FindBugsFilter>

This will exclude the Class Naming Convention check from the java package specified. More information can be found in filtering section of the findbugs manual.

Posted in android, clean code, craftsmanship, maven | Leave a comment

YouTube GData API and Android

If you want to use the YouTube API v2 to search for content on YouTube with an Android device, the recommended way is the use the gdata-http-client java package. However, this requires that you parse the XML returned yourself, and navigate it. The reason is that out of the box the YouTube API v2 java library doesn’t work on Android. This is due to a requirement on the javax.mail package which isn’t available officially on Android.

However, thanks to the wonders of the internet, you can get a package of javax.mail and activation which have been compiled to work on Android. The javamail-android project contains jars have been compiled to work with Android and it’s DEXer.

For those using Maven, I have added these to my maven repo. Add the following repository to your pom to make it available:

<repository>
  <id>serenity-thirdparty-repo</id>
  <url>http://kingargyle.github.com/repo</url>
  <layout>default</layout>
   <releases>
      <enabled>true</enabled>
      <updatePolicy>always</updatePolicy>
      <checksumPolicy>warn</checksumPolicy>
   </releases>
</repository>

Then for dependencies for the YouTubeAPI you can add the following to your pom for your app.

      <dependency>
         <groupId>com.google.gdata</groupId>
         <artifactId>gdata-youtube</artifactId>
         <version>2.0</version>
      </dependency>
      <dependency>
         <groupId>com.google.gdata</groupId>
         <artifactId>gdata-youtube-meta</artifactId>
         <version>2.0</version>
      </dependency>
      <dependency>
         <groupId>com.google.gdata</groupId>
         <artifactId>gdata-core</artifactId>
         <version>1.0</version>
      </dependency>
      <dependency>
         <groupId>com.google.gdata</groupId>
         <artifactId>gdata-media</artifactId>
         <version>1.0</version>
      </dependency>
      <dependency>
         <groupId>com.google.gdata</groupId>
         <artifactId>gdata-client</artifactId>
         <version>1.0</version>
      </dependency>
      <dependency>
         <groupId>com.google.gdata</groupId>
         <artifactId>gdata-client-meta</artifactId>
         <version>1.0</version>
      </dependency>
      <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
         <version>11.0.2</version>
      </dependency>
      <dependency>
        <groupId>com.google.gdata</groupId>
        <artifactId>mail</artifactId>
        <version>1.0</version>
      </dependency>      
      <dependency>
        <groupId>com.google.gdata</groupId>
        <artifactId>activation</artifactId>
        <version>1.0</version>
      </dependency>

You may want to run ProGuard to help cut down the size of the guava library brought in by the app, as it alone adds about 1.1mb to the size of your application.

With the above added you can use the YouTube GData v2 API to search YouTube for videos and deal with java objects.

Posted in android, build, java, maven, serenity | Leave a comment

Serenity now on the Amazon App Store

serenity-bonsai-logo

Version 1.5.2 is now available in the play store.   It’s been a while since I posted an update here on the blog, but a lot has been added to the App since the last posting.  Some of the features include, a Video Queue for movies and tv shows, ability to toggle between Grid and Detail views, and better integration with supported external players like MX Player Pro.   As always the latest can be found on Google Play

 

Get it on Google Play

In addition, the App is now available on the Amazon App store as well.  So if your device doesn’t support the Google Play store, you can get it through the Amazon App store now as well.   The app does work on Kindle Fire 2nd gen or newer.   It is recommended to use an external video player with the app when using it on the Kindle for the best experience. If you can, side load MX Player for the best integrated experience.

6a0148c71fb71b970c0153901475c3970b-pi

Going forward I will update both stores at the same time. However, due to the extra approval process with the Amazon App Store, the version there will be a couple of days behind the Play store version.

Posted in android, googletv, open source, plex media server, serenity | Leave a comment

Adding Overlay Icons to ImageViews

While working on Serenity for Android, one of the many requests I received was to have a Watched Status indicator appear over the poster. There are a couple of ways to do this on Android.

  • Use a Canvas and draw the overlay icon on to the existing bitmap
  • Use a Layout and overlay the icon as needed.

The first approach works, but leaves the bitmap with the image embedded in it permanetly, meaning if you want to have a toggle you have to redraw the bitmap again and display it without it.

The second approach required a bit more refactoring of some code in Serenity but turned out to be more flexible.  By using a RelativeLayout and emebedding two ImageViews in it, I could easily toggle the visibility of the watched indicator, and also allow for some future overlays if necessary fairly easily.

Here is the layout in question:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/posterIndicatorView"
    android:background="@drawable/gallery_item_background" >
    
    <us.nineworlds.serenity.ui.views.SerenityPosterImageView
        android:id="@+id/posterImageView"
        android:scaleType="fitXY"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        />
    <ImageView android:id="@+id/posterWatchedIndicator"
        android:scaleType="fitXY"
        android:layout_width="33dp"
        android:layout_height="33dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        />
</RelativeLayout>

The RelativeLayout allows for more general positioning of the views, so is ideal for setting the watched status indicator to appear in the lower right corner of the poster. In order to use this view, I needed to use a layout inflator to get the view, and then populate it with the images. The basics are here:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
   View galleryCellView = context.getLayoutInflater().inflate(R.layout.poster_indicator_view, null);
   VideoContentInfo pi = posterList.get(position);
   SerenityPosterImageView mpiv = (SerenityPosterImageView) galleryCellView.findViewById(R.id.posterImageView);
   mpiv.setPosterInfo(pi);
   mpiv.setBackgroundResource(R.drawable.gallery_item_background);
   mpiv.setScaleType(ImageView.ScaleType.FIT_XY);
   int width = 0;
   int height = 0;

   width = ImageUtils.getDPI(130, context);
   height = ImageUtils.getDPI(200, context);
   if (!MovieBrowserActivity.IS_GRID_VIEW) {
      mpiv.setLayoutParams(new RelativeLayout.LayoutParams(width, height));
      galleryCellView.setLayoutParams(new SerenityGallery.LayoutParams(width, height));
   } else {
      width = ImageUtils.getDPI(120, context);
      height = ImageUtils.getDPI(180, context);
      mpiv.setLayoutParams(new RelativeLayout.LayoutParams(width, height));
      galleryCellView.setLayoutParams(new TwoWayAbsListView.LayoutParams(width, height));
   }

   imageLoader.displayImage(pi.getImageURL(), mpiv);
		
   if (pi.getViewCount() > 0) {
      ImageView viewed = (ImageView) galleryCellView.findViewById(R.id.posterWatchedIndicator);
      viewed.setImageResource(R.drawable.overlaywatched);
   }
   return galleryCellView;
}

The above is in the Adapter used to render the views. It uses a Gallery adapter, but also works in a TwoWayGridView as well. It will fetch the poster to be used, and setup the Layout Parameters for the image view, it will also make sure the RelativeLayout itself is set to the same size as the ImagePoster that it encapsulates (using wrap content doesn’t seem to work as expected with a RelativeLayout). It then checks to see if the view count on the video is greater than 0 if so, it sets the overlay bitmap to be used on the poster. Finally it returns the newly populate gallery view to the Gallery to be displayed.

The nice thing here is that using the XML layout one can easily add other overlays if necessary by adding the necessary markup and enabling them when necessary. I’m sure there are other ways to do this as well, but this seems to work fairly well and is pretty flexible for future expand-ability.

Posted in android | Leave a comment

Detecting Television Feature on Android

I wrote up a post on google plus, that may be interested to a wider audience.  If you are an android app developer and want your app to work well on a Television or set top box, you need know if you need to handle focus specially or not for these devices.  Here is one way to know when you are running on such devices.

Android has the following system feature that can be checked.

android.hardware.type.television

If the device has this feature you can know that that the device supports the following:

This feature defines “television” to be a typical living room television experience: displayed on a big screen, where the user is sitting far away and the dominant form of input is something like a d-pad, and generally not through touch or a mouse/pointer-device.

Why is this important. Because for D-PAD devices, like the OUYA and Google TV, one needs to be more aware of what items can have Focus and which item currently has focus. Not all Android views play well with Focus, as for a touch screen device it isn’t as important to know what currently has focus. It is critical though when designing an app that can be used effectively on a tv.

For those that need a bit of code, here is some from Serenity for Android 1.4.2 to help you out.

public static boolean isAndroidTV(Context context) {
     final PackageManager pm = context.getPackageManager();
     return pm.hasSystemFeature("android.hardware.type.television");
}

The above will check if the device reports that it supports the Television feature or not.

Not paying attention to what items have focus is probably the biggest useability issue your app will run into when trying to run on a non touchscreen device.

Posted in android, googletv | 1 Comment