Tuesday, August 02, 2011

Using Google Protobufs in Android and Maven

In this post, we are going to build upon my previous post on using Maven as a build manager for Android projects.
Google Protobufs have recently found traction in serialization of structured data. It automatically produces code in C++, Java and Python from .proto file for use in user programs. A proto file consists of messages that are compiled using the protocol buffer compiler to produce code with getters, setters, builders etc.. The user is directed to the Java Protobuf tutorial for more details.
The first task is to add Protobufs as a dependency to your Android project pom.xml:

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.2.0</version>
<scope>compile</scope>
</dependency>

Next, to automatically compile the .proto to the equivant .java, add the following build task to your project pom.xml:

<build>
<finalName>${project.artifactId}</finalName>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<exec executable="protoc">
<arg value="--java_out=src" />
<arg value="path_to_proto" />
</exec>
</tasks>
<sourceRoot>src</sourceRoot>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Replace path_to_proto with the path your .proto.
Having taken care of dependencies and automatically build, now, let's focus on the .proto itself.
The .proto should have the following two lines at the very start:

package org.x.x;
option java_outer_classname = "Filename";

where org.x.x is the Java package to which the resultant "Filename.java" should be added.

Let's take the example of a .proto which consists of just one message, Test:

message Test {
required int32 integerField = 1;
optional string stringField = 2;
repeated int64 doubleField = 3;
}

int32 is compiled to a Java int while int64 is compiled to a Java double.

To build the Test message in Java after compilation:

Test test = Test.newBuilder()
.setIntegerField(10)
.setStringField("Hello")
.addDoubleField(1.0)
.addDoubleField(2.0)
.build();

Note that optional fields can be skipped during a message build while more than one repeated field objects can be added as they constitute a Java List.

To write the message to an OutputStream:

test.writeTo(outputStream);

To get a ByteArray equivalent:

byte[] byteArray = test.toByteArray();

To generate a Test message from a ByteArray:

Test test = Test.parseFrom(byteArray);

In addition to these methods, standard get, set, has and is methods are also provided.

No comments:

Post a Comment