Tuesday, November 26, 2013

RoboSpice Spring

Robospice Spring Android module is a library that you can use when you need to handle restful network communication on your application. Recently, it has been highly advised to use a dependency manager to add this library to your projects. Since the official documentations already contain plenty of guides for that, I will just skip that part. For this tutorial, just make sure that you have the needed jar files. Here are the list of jars:

robospice-cache-x.y.z.jar
robospice-x.y.z.jar
commons-io-x.y.z.jar
commons-lang3-x.y.z.jar
spring-android-core-x.y.z.jar
spring-android-rest-template-x.y.z.jar
robospice-spring-android-x.y.z.jar

These optional libraries are also useful:

jackson-core-asl-x.y.z.jar
jackson-mapper-asl-x.y.z.jar 
jackson-databind-x.y.z.jar
gson-x.y.z.jar
simple-xml-x.y.z.jar

Update the application manifest by adding these permissions:
1:    <uses-permission android:name="android.permission.INTERNET"/>  
2:    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
3:    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  

Also add the JacksonSpringAndroidSpiceService within the application section of the manifest:
1:  <service android:name="com.octo.android.robospice.JacksonSpringAndroidSpiceService" android:exported="false" />  

For the WebService, we will use the OpenWeatherMap forecast api samples. To handle the api response data, we need to prepare the necessary classes but first we need to take a look at the json object from the server.


As you can see, each list item consists of several fields. Some fields consist of strings while others are composed of json objects or json array. For the json objects like the temp property, we prepare an object to handle its data:
1:  @JsonIgnoreProperties(ignoreUnknown = true)  
2:  public class Temp {  
3:       private String day;  
4:       private String min;  
5:       private String max;  
6:       private String night;  
7:       private String eve;  
8:       private String morn;  
9:       public String getDay() {  
10:            return day;  
11:       }  
12:       public void setDay(String day) {  
13:            this.day = day;  
14:       }  
15:       public String getMin() {  
16:            return min;  
17:       }  
18:       public void setMin(String min) {  
19:            this.min = min;  
20:       }  
21:       public String getMax() {  
22:            return max;  
23:       }  
24:       public void setMax(String max) {  
25:            this.max = max;  
26:       }  
27:       public String getNight() {  
28:            return night;  
29:       }  
30:       public void setNight(String night) {  
31:            this.night = night;  
32:       }  
33:       public String getEve() {  
34:            return eve;  
35:       }  
36:       public void setEve(String eve) {  
37:            this.eve = eve;  
38:       }  
39:       public String getMorn() {  
40:            return morn;  
41:       }  
42:       public void setMorn(String morn) {  
43:            this.morn = morn;  
44:       }  
45:  }  

For an array type (just like the weather list) we do declare it like this:
1:       private List<Weather> weather;  

For our request to the webservice, we prepare the following request object:
1:  public class ForecastListRequest extends SpringAndroidSpiceRequest<ForecastList> {  
2:       public ForecastListRequest() {  
3:            super(ForecastList.class);  
4:       }  
5:       @Override  
6:       public ForecastList loadDataFromNetwork() throws Exception {  
7:            Uri.Builder builder = Uri.parse("http://api.openweathermap.org/data/2.5/forecast/daily?lat=35&lon=139&cnt=7&mode=json").buildUpon();  
8:            return getRestTemplate().getForObject(builder.build().toString(), ForecastList.class);  
9:       }  
10:  }  

After preparing the objects, we need to instantiate our spiceManager in our activity to be able to use it:

1:  private SpiceManager spiceManager = new SpiceManager(JacksonSpringAndroidSpiceService.class);  

Also we need to start it on the onStart method of the activity before using it:
1:       @Override  
2:       protected void onStart() {  
3:            super.onStart();  
4:            spiceManager.start(this);  
5:       }  

And stop the spiceManager when the activity stops:
1:       @Override  
2:       protected void onStop() {  
3:            spiceManager.shouldStop();  
4:            super.onStop();  
5:       }  

In our onCreate method, we execute the request like this:
1:  ForecastListRequest request = new ForecastListRequest();  
2:            spiceManager.execute(request, new RequestListener<ForecastList>() {  
3:                 @Override  
4:                 public void onRequestFailure(SpiceException arg0) {  
5:                      Log.i("ForecastListRequest", "failed");  
6:                 }  
7:                 @Override  
8:                 public void onRequestSuccess(ForecastList arg0) {  
9:                      Log.i("ForecastListRequest", "success!");  
10:                      List<Forecast> list = arg0.getList();  
11:                      for (Forecast forecast : list) {  
12:                           Log.i("ForecastListRequest", "dt=" + forecast.getDt());  
13:                      }  
14:                 }  
15:            });  

The full source code for this tutorial can be downloaded here

Monday, November 25, 2013

Using Java Enum As An Alternative to Bit Flags

Recently, I needed to use bit flags as parameter to a method to determine its output. I noticed while doing a bit of research online that most people suggest using EnumSet instead of bit flags as a parameter. Normally,  I use the bit flag like this:

1:  public class SampleUtil {  
2:       public static final int FLAG_1 = 1 << 0;  
3:       public static final int FLAG_2 = 1 << 1;  
4:       public static final int FLAG_3 = 1 << 2;  
5:       private static String processString1(String input) {  
6:            return input + "process1";  
7:       }  
8:       private static String processString2(String input) {  
9:            return input + "process2";  
10:      }  
11:      private static String processString3(String input) {  
12:           return input + "process3";  
13:      }  
14:      public static List<String> processInput(String input, int flags){  
15:            List<String> output = new ArrayList<String>();  
16:            if ((flags & FLAG_1) == FLAG_1) {  
17:                 output.add(processString1(input));  
18:            }  
19:            if ((flags & FLAG_2) == FLAG_2) {  
20:                 output.add(processString2(input));  
21:            }  
22:            if ((flags & FLAG_3) == FLAG_3) {  
23:                 output.add(processString3(input));  
24:            }  
25:            return output;  
26:       }  
27:  }  

For every flag set, I perform a method on an input and add it to the results. Works well but maybe things could be better.. so I decided to take a look at using enums. Taking another look at the docs, I remembered that enums are much more powerful and versatile than bit flags.

Since enum is also a class, I decided to exploit this property. One thing I noticed with the methods used for processing the string is that they all have the same input and output type. Another thing is that each one is tied to a certain flag exclusively. Because of this, I made an interface that represents all these methods.
1:  public interface IStringProcessor {  
2:       String processString(String input);  
3:  }  

Then, I modified the constructor to add a parameter for the enum:
1:       private IStringProcessor processor;  
2:       ProcessFlag(IStringProcessor processor) {  
3:            this.processor = processor;  
4:       }  

I also added a method to my enum class so I can use the processor passed on the constructor of the enum.
1:       public String applyMethod(String input) {  
2:            return processor.processString(input);  
3:       }  

Then I initialized the enums:
1:       FLAG_1(new IStringProcessor(){  
2:            @Override  
3:            public String processString(String input) {  
4:                 return input + "process1";  
5:            }  
6:       }),  
7:       FLAG_2(new IStringProcessor(){  
8:            @Override  
9:            public String processString(String input) {  
10:                 return input + "process2";  
11:            }  
12:       }),  
13:       FLAG_3(new IStringProcessor(){  
14:            @Override  
15:            public String processString(String input) {  
16:                 return input + "process3";  
17:            }  
18:       });  

To use enumset as a parameter, I modified my "processInput" method and used the enum type for processing my input string:
1:       public static List<String> processInput(String input, EnumSet<ProcessFlag> flags){  
2:            List<String> output = new ArrayList<String>();  
3:            Iterator<ProcessFlag> iterator = flags.iterator();  
4:            while (iterator.hasNext()) {  
5:                 ProcessFlag pFlag = iterator.next();  
6:                 output.add(pFlag.applyMethod(input));  
7:            }  
8:            return output;  
9:       }  

Here is a short code to demonstrate how to use the "processInput" method:
1:       public static void main(String[] args) {  
2:            EnumSet<ProcessFlag> flags = EnumSet.of(ProcessFlag.FLAG_1, ProcessFlag.FLAG_2);  
3:            List<String> strings = SampleUtil.processInput("Hello", flags);  
4:            for (String s : strings) {  
5:                 System.out.println(s);  
6:            }  
7:       }  

A complete source for this demo can be downloaded from here

Monday, July 29, 2013

Starting With ActionBarSherlock

ActionBarSherlock is a library that extends the android support library to enable applications to use the action bar on devices with lower versions of the android os.

To follow this guide, you must download the ActionBarSherlock library from here.

After you have extracted the contents of the source file archive (the name of the file I downloaded is JakeWharton-ActionBarSherlock-4.4.0-0-g4a79d53.zip which, I assume, is the latest version), you must import the source file to create an android library project.

Select Import->Existing Android Code Into Workspace and navigate to the folder where you extracted the source archive. Select the folder named actionbarsherlock.


Check if the project is set as a library by viewing the project Properties->Select Android and check on the right part of properties window if the following is checked:

Create a new android project that you will use for testing the actionbarsherlock library. After the project is created, you need to reference the action bar library by viewing the Properties -> Android window again. Click add, and select the actionbarsherlock project that you imported earlier.

Please note that in my screenshot, I renamed the actionbarsherlock folder into abs.

To be able to use the action bar, your activity must extend the SherlockActivity class:

1:  package org.kaithe.android;  
2:  import com.actionbarsherlock.app.SherlockActivity;  
3:  import android.os.Bundle;  
4:  public class MainActivity extends SherlockActivity {  
5:       @Override  
6:       protected void onCreate(Bundle savedInstanceState) {  
7:            super.onCreate(savedInstanceState);  
8:            setContentView(R.layout.activity_main);  
9:       }  
10:  }  

From this point, you can already run your application. However, it will just look plain since we still haven't done any customisations on the action bar.


To test the action bar, we will add some items in it. Override the onCreateOptionsMenu method from the SherlockActivity class.
1:       @Override  
2:       public boolean onCreateOptionsMenu(Menu menu) {  
3:      menu.add("Save")  
4:        .setIcon(R.drawable.ic_compose)  
5:        .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);  
6:      menu.add("Search")  
7:        .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);  
8:      menu.add("Refresh")  
9:        .setIcon(R.drawable.ic_refresh)  
10:        .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);  
11:      return true;  
12:       }  

In here, we created 3 menu on the action bar. Running the application, this is what our action bar will look like:


The action bar sherlock library source that I used can be found in here
The full action bar sample application source can be obtained here

Thursday, June 13, 2013

Camera Overlays for Titanium Mobile Android

To add overlays to the Titanium Mobile camera screen, you need to set the overlay property of your CameraOptionsType:

1:  Titanium.Media.showCamera({  
2:   success : function(e) {},  
3:   error : function(e) {},  
4:   cancel : function(e) {},  
5:   overlay : Ti.UI.createView({  
6:    backgroundImage : '/crosshair.png',  
7:    width : '200dp',  
8:    height : '200dp'  
9:   })  
10:  })  

While that step looks simple enough, you might still encounter some unexpected errors like this: (Unable to find explicit activity class... TiCameraActivity)


From the error, we can see that the activity class for TiCameraActivity was not defined in the Android manifest. Normally, that entry is supposed to be added automatically to the generated manifest file but what happened here is that its missing. This happened because I am using a custom manifest file. I created the custom manifest before I added the camera code which is why the camera activity definition is missing from the manifest. To fix this, simply add the code to your custom manifest file in between the <application></application> tags:

1:  <activity   
2:            android:name="ti.modules.titanium.media.TiCameraActivity"  
3:            android:configChanges="keyboardHidden|orientation"  
4:            android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />  

Also note that while this fixes the crash problem, you will also face another weird problem with the overlay on android:
You can see that the overlay's orientation is converted to landscape, even though the image I used is in portrait mode. But since that problem is simple enough to solve, I'll just leave it as is..

You can get the source code for this application in here

Displaying Images Taken from Titanium Mobile showCamera Method

While the api documentation for the Ti.Media.showCamera method does a pretty good job in demonstrating how to call the camera application, it does not show how the use or display the image that was captured by the camera. So after spending some time with it, I was able to come up with this solution to display my image.

First, I created a wrapper that will contain my picture:

1:  var imageWrapper = Ti.UI.createView({  
2:       backgroundColor : 'red',  
3:       width : '300dp',  
4:       height : '385dp',  
5:       top : '65dp'  
6:  });  
7:  win.add(imageWrapper);  

Then, on the success callback of the CameraOptionsType, I created an image view that will contain the image data from the native camera application:

1:  var image = event.media;   
2:  tempImage = Ti.UI.createImageView({  
3:   image : image,  
4:   width : '385dp',  
5:   height : '300dp'  
6:  });  

From what I have observed, the images taken on the android device are not properly oriented (maybe its the same on ios), so I rotate the images before adding them on the wrapper I prepared earlier:

1:  var rotation = Ti.UI.create2DMatrix({ rotate : -270 });  
2:  tempImage.transform = rotation;  
3:  imageWrapper.add(tempImage);  

To test the whole application, get the full source code here

Android MapsV2 Module Sample Code in Titanium Mobile Alloy

With the introduction of SDK 3.0, a new framework called Alloy had been integrated with Titanium. This framework uses model-view-controller architecture to break down your application code. While it is fairly simple to learn the new framework, I encountered a bit of slowdown when trying to use the new Google Maps Android v2 module in it. To help save a lot of time, I'll demonstrate how I used the  map module on the new framework.

First, you need to download the map module from here. After you have downloaded the zip file, you need to put the extracted contents on the root folder of your application.


You can also put the module in the Titanium SDK Home Directory (but for me, I prefer to use the application folder).

After placing the module on the proper folder, you need to edit the tiapp.xml file on your project root. Find the <modules/> tag and update it like below:
1:    <modules>  
2:         <module platform="android" version="2.1.0">ti.map</module>  
3:    </modules>  

Find the <android xmlns:android="http://schemas.android.com/apk/res/android"/> tag and update it as well:
1:  <android xmlns:android="http://schemas.android.com/apk/res/android">  
2:      <manifest>  
3:        <!-- Allows the API to download data from Google Map servers -->  
4:        <uses-permission android:name="android.permission.INTERNET"/>  
5:        <!-- Allows the API to cache data -->  
6:        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
7:        <!-- Use GPS for device location -->  
8:        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>  
9:        <!-- Use Wi-Fi or mobile connection for device location -->  
10:        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
11:        <!-- Allows the API to access Google web-based services -->  
12:        <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>  
13:        <!-- Specify OpenGL ES 2.0 as a requirement -->  
14:        <uses-feature android:glEsVersion="0x00020000" android:required="true"/>  
15:        <!-- Replace com.domain.appid with your application ID -->  
16:        <uses-permission android:name="<com.domain.appid>.permission.MAPS_RECEIVE"/>  
17:        <permission android:name="<com.domain.appid>.permission.MAPS_RECEIVE"  
18:          android:protectionLevel="signature"/>  
19:        <application>  
20:          <!-- Replace "PASTE YOUR GOOGLE MAPS API KEY HERE" with the Google API key you obtained -->  
21:          <meta-data android:name="com.google.android.maps.v2.API_KEY"  
22:            android:value="PASTE YOUR GOOGLE MAPS API KEY HERE"/>  
23:        </application>  
24:      </manifest>  
25:    </android>  

Remember to set your api key on the android:value property of the meta-data tag on the manifest section of your tiapp.xml file. Also, change the <com.domain.appid> strings on that same section with your application id found between the <id></id> tags in the tiapp.xml file.

An alloy application framework code is divided into four parts. Each part can be located in its corresponding folder under the app directory. For my sample application, I have no need for a model so you can see that it's folder is empty.


Since all alloy application start with the index, you can see the controllers, views, and styles had been created. I don't need customise the view so I just removed the sample code from it:

1:  <Alloy>  
2:       <Window class="container">  
3:       </Window>  
4:  </Alloy>  


To instantiate the module, just use the require method. In my sample application, I placed it in the index controller. The file can be found inside the app/controllers/ directory. The code for my index.js file is as follows:

1:  var MapModule = require('ti.map');  
2:  var mapview = MapModule.createView({  
3:       mapType : MapModule.NORMAL_TYPE,  
4:       region: {  
5:            latitude:33.74511,   
6:            longitude:-84.38993,  
7:      latitudeDelta:0.01,   
8:      longitudeDelta:0.01  
9:    },  
10:    top : 0,  
11:    left : 0,  
12:    right : 0,  
13:    bottom : 0,  
14:    animate:true,  
15:    regionFit:true  
16:  });  
17:  $.index.add(mapview);  
18:  $.index.open();  

Just adding the code above on the index controller will already add the MapView on the application window.  If you need more info on the MapView, just consult the API docs.

To see the full source of my sample application go here

MapView Transparency Bug on Titanium Android

While using the new MapView module for android, I noticed that the view becomes blank when it is animated. Even when I tried to refresh the view, the map would remain to be invisible (or seems to be located at the background).

At first, I thought it was the drawer menu widget that I was using. However, as I looked further, I was able to confirm that any animation that moves the MapView on the screen causes it to become invisible (like my sample below):

View code:
1:  <Alloy>  
2:       <Window class="container">  
3:            <View id="mainwindow" top="0" left="0" right="0" bottom="0" backgroundColor="white" onClick="doClick">  
4:            </View>  
5:       </Window>  
6:  </Alloy>  

Controller code:
1:  var MapModule = require('ti.map');  
2:  var mapview = MapModule.createView({  
3:       mapType : MapModule.NORMAL_TYPE,  
4:       region: {  
5:            latitude:33.74511,   
6:            longitude:-84.38993,  
7:      latitudeDelta:0.01,   
8:      longitudeDelta:0.01  
9:    },  
10:    top : '50dp',  
11:    left : 0,  
12:    right : 0,  
13:    bottom : 0,  
14:    animate:true,  
15:    regionFit:true  
16:  });  
17:  $.mainwindow.add(mapview);  
18:  function doClick(e) {   
19:    $.mainwindow.animate({  
20:         left : '300dp',  
21:         top : 0,  
22:         right : 0,  
23:         bottom : 0  
24:    });  
25:  }  
26:  $.index.open();  

To check if the problem is rooted at the native android sdk, I created a similar scenario on a native android application. When I was not able to encounter the same problem,  I then tried to find a workaround for this bug.

After a lot of searching, I finally found out that using hardware acceleration on the application would help in bringing back the MapView. So, going to the Android manifest, you need to find the application tag and add the property to enable hardware acceleration on your application:

1:  <application android:icon="@drawable/appicon"  
2:            android:label="sample" android:name="SampleApplication"  
3:            android:debuggable="false"  
4:            android:hardwareAccelerated="true">  

Please note that using this solution, the MapView may still disappear a bit while the view is animating, but it comes back again after the animation finishes.