Tuesday 29 November 2011

AppEngine Datastore implementation with Objectify - put()

Now I have set up the RequestFactory way of client-server communication, I now need to actually implement some logic to CRUD Gifts.

I am going to use the AppEngine Datastore, see:


Particulary note the comment: "In addition to the standard frameworks and low-level datastore API, the Java SDK supports other frameworks designed to simplify datastore usage for Java developers. A large number of Java developers use these frameworks. The Google App Engine team highly recommends them and encourages you to check them out."

This is because JDO and JPA are massive and have a steep learning curve They suggest Objectify, TWiG and Slim3. With my first Google I found this cool article by Andreas Borglin, and then lots of links to his article.


It seems to me that Objectify is the better option to get going, and this part of the pet-project is not that interesting to me (I AM suppose to be learning Android!). I first had a look at Concepts:


Then I downloaded the Objectify jar and added it to my project (as I'm using AppEngine SDK 1.5.5, I need to use Objectify version 3.1 beta (not the newer 3.1 version) released 13th October 2011)

Now for some implementation.

First I have to manually register the entities with ObjectifyService. The Best Practices guide advised me to use a DAO object with a static initialiser. so I created a new class in package com.yrdomain.yrproject.server;

import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.util.DAOBase;

/**
 * By accessing Objectify through your own DAO class, you can register your
 * entities in a static initializer and also add domain-specific helper methods.
 *
 */
public class DAO extends DAOBase {

    static {
        ObjectifyService.register(Gift.class);
    }

    /* Your DAO can have your own useful methods
    public MyThing getOrCreateMyThing(long id)
    {
        MyThing found = ofy().find(clazz, id);
        if (found == null)
            return new MyThing(id);
        else
            return found;
    }*/
}
 
I then didn't realise what I was doing and tried to get a reference to the Objectify twice with:

Objectify ofy = ObjectifyService.begin();
 
in my YrprojectService.java class. However, by extending DAOBase, it already gets this and is accessible by just typing:

dao.ofy().some_method()
 
If you do it twice it comes up with a NoClassDefFoundError for DAOBase - well it did the first time, when trying to re-create the error to put in the stack-trace for you guys, it worked fine!

This is a first go at the implementation:

public class YrprojectService {

    DAO dao = new DAO();

    @ServiceMethod
    public Gift createGift() {

        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();
        String message;
        if (user == null) {
          message = "No one is logged in!\nSent from App Engine at " + new Date();
        } else {
          message = "Howdie, " + user.getEmail() + 
"!\nSent from createGift on the App Engine at " + 
new Date();
        }

        // Simple create
        Gift porsche = new Gift();
        porsche.setGiftName("sports car");
        porsche.setGiftLocation(message);
        dao.ofy().put(porsche);
        assert porsche.getId() != null;    // id was autogenerated
        return porsche;

    }
    //...other CRUD methods...
}
 
It all works fine, as in there are no errors... but can I get my porche back?

Another Error

Objectify FAQs suggest that we turn off the datanucleus byte-code enhancer in Eclipse (go to the Project Properties -> Builders and disable the Enhancer) If you are using the default AppEngine Connected Android Project that is created when you use the Wizard in Eclipse, it uses JDO in the registration of the device. If you subsequently decide to use Objectify, turning off the datanucleus byte-code enhancer will give you the following error:

Failure: Got exception javax.jdo.JDOUserException: Persistent class "Class com.yrdomain.yrproject.server.DeviceInfo does not seem to have been enhanced. You may want to rerun the enhancer and check for errors in the output." has no table in the database, but the operation requires it. Please check the specification of the MetaData for this class. NestedThrowables: org.datanucleus.store.exceptions.NoTableManagedException: Persistent class "Class comyrdomain.yrproject.server.DeviceInfo does not seem to have been enhanced. You may want to rerun the enhancer and check for errors in the output." has no table in the database, but the operation requires it. Please check the specification of the MetaData for this class.

Just turn on the enhancer again, Clean and re-build, the error will go away. You have to remove all the default behaviour and use the Objectify ways. People like to turn off the enhancer because it can take too much time, its easier to just be a bit more specific in what files you want enhanced, remember it's looking for files that will be persisted. Change these options in:

Project Settings > Google > App Engine > ORM

Change the src/ and shared/ folders

Monday 28 November 2011

Calling your own AppEngine Service methods

To test the operation of this I'm going to take a leaf out of the Task example and implement a Create button on the GWT front-end of the server, to make sure everything is wired up and working.

Add a new button to the web-page com.yrdomain.yrproject.client.YrprojectWidget.ui.xml

 <g:Button ui:field="createButton">Create</g:Button>
 
Open file com.yrdomain.yrproject.client.YrprojectWidget.java

Add the UI element:

@UiField
Button createButton;
 
And in the constructor, fire off a createGift() request.

createButton.addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
            createButton.setEnabled(false);
            MygiftwishlistRequest mygwlRequest = requestFactory.mygiftwishlistRequest();
            mygwlRequest.createGift().fire(new Receiver<GiftProxy>() {
                @Override
                public void onFailure(ServerFailure error) {
                    createButton.setEnabled(true);
                    setStatus(error.getMessage(), true);
                }
                @Override
                public void onSuccess(GiftProxy response) {
                    createButton.setEnabled(true);
                    setStatus(response.getGiftLocation(), false);
                  }
                
            });
        }
    });
 
The RPC wizard automatically took the Gift.java Entity and created a GiftProxy, which it used in YrprojectRequest.java and added an entry for it in the MyRequestFactory.java (both in the shared folder).
Update the createGift() method to make it return something interesting - ok, just a variation on the HelloWorldService:

@ServiceMethod
    public Gift createGift() {
        
        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();
        String message;
        if (user == null) {
          message = "No one is logged in!\nSent from App Engine at " + new Date();
        } else {
          message = "Howdie, " + user.getEmail() + 
"!\nSent from createGift on the App Engine at " + 
new Date();
        }
       
        Gift porsche = new Gift();
        porsche.setGiftName("sports car");
        porsche.setGiftLocation(message);
        
        return porsche;
    }
 
When we run the project, we see that when we press the Create button on the web-page, it calls the createGift() function on YrprojectService.java as expected.

Now we need to properly create Gifts and store them against the name of the user in the database.

RequestFactory implementation

This is a record of my implementation of the information contained in the following tutorial:

http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html

I started with the default implementation of a new AppEngine Connected Android Project and I have been following the tutorial on the Google website:

http://www.youtube.com/watch?v=M7SxNNC429U&feature=player_embedded#!

Sometimes I cut and paste text from the Google website, or change it around slightly, so credit to and acknowledgement to Google where I have done this. It just makes it easier as their terminology is correct.
I wanted to add some gifts (as its Christmas!) to my default AppEngine Connected Android Project. They chose Tasks, I thought Gifts would be more fun :)

First I created my Gift.java class - a simple class with three variables: giftName, giftLocation, giftPrice (all Strings for now) and the getters and setters.

Now the thing that makes this POJO interesting is that I added the annotation @Entity. This describes my class being able to be 'persisted to a data store such as a relational database or the Google App Engine Datastore'.

Gift.java

package com.yrdomain.yrproject.server;

import javax.persistence.*;
import javax.validation.constraints.*;

@Entity
public class Gift {

      private String giftName;
      private String giftLocation;
      private String giftPrice;

      @Id
      @Column(name = "id")
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;

      @Version
      @Column(name = "version")
      private Integer version;

    public String getGiftName() {
        return giftName;
    }
    public void setGiftName(String giftName) {
        this.giftName = giftName;
    }

    public String getGiftLocation() {
        return giftLocation;
    }
    public void setGiftLocation(String giftLocation) {
        this.giftLocation = giftLocation;
    }

    public String getGiftPrice() {
        return giftPrice;
    }
    public void setGiftPrice(String giftPrice) {
        this.giftPrice = giftPrice;
    }

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
}
 
I was then able to use File > New > Google > RPC Service to generate me the necessary classes for the RPC service. Its an easy way to create the client-side code that does the basic CRUD operations. The wizard looks for all classes with persistence annotations (and finds Gift.java defined above) and uses this to create the following files in the same package:
  • GiftLocator.java
  • YrprojectService.java
  • YrprojectServiceLocator.java
and the proxy in the shared package:
  • GiftProxy.java
  • YrprojectRequest.java
and a new annotations package:
  • ServiceMethod.java
Lets have a look at some of these...

GiftProxy.java

The GiftProxy is the client-side representation (EntityProxy) of the server-side Gift (Entity). We associate it with the entity in the @ProxyFor annotation and link the persistence implementation with the GiftLocator class.
package com.yrdomain.yrproject.shared;

import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyForName;

@ProxyForName(value   = "com.yrdomain.yrproject.server.Gift",
              locator = "com.yrdomain.yrproject.server.GiftLocator")
public interface GiftProxy extends EntityProxy {

    String getGiftName();
    void setGiftName(String giftName);

    String getGiftLocation();
    void setGiftLocation(String giftLocation);
    String getGiftPrice();
    void setGiftPrice(String giftPrice);

    Long getId();

    Integer getVersion();
    void setVersion(Integer version);
}
 
GiftLocator.java

The generated file is for when you don't want to implement persistence code in an entity itself. However there are two small problems with the generated file, maybe because the API is so new?
Change Void id to Long id (Eclipse will suggest that you implement all unimplemented methods, which will in effect re-define this method)
@Override
    public Gift find(Class<? extends Gift> clazz, Long id) {
        // TODO Auto-generated method stub
        return null;
    }
Add the missing semi-colon :)
@Override
    public Long getId(Gift domainObject) {
    return domainObject.getId();
    }
 
YrprojectRequest.java

This is found with the GiftProxy.java class in the shared package. This is a RequestFactory service stub, and it must extend RequestContext and uses the @Service or @ServiceName annotations to name the associated service implementation class on the server. The methods in a service stub do not return entities directly, but rather return subclasses of com.google.web.bindery.requestfactory.shared.Request.
This allows the methods on the interface to be invoked asynchronously with Request.fire()from the client.
package com.yrdomain.yrproject.shared;

import java.util.List;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.ServiceName;

@ServiceName(value = "com.yrdomain.yrproject.server.YrprojectService", locator = "com.yrdomain.yrproject.server.YrprojectServiceLocator")
public interface YrprojectRequest extends RequestContext {

    Request<GiftProxy> createGift();
    Request<GiftProxy> readGift(Long id);
    Request<GiftProxy> updateGift(GiftProxy gift);
    Request<Void> deleteGift(GiftProxy gift);
    Request<List<GiftProxy>> queryGifts();
}
 
YrprojectService.java

package com.yrdomain.yrproject.server;

import java.util.List;
import com.yrdomain.yrproject.annotation.ServiceMethod;

public class YrprojectService {

    @ServiceMethod
    public Gift createGift() {
        // TODO Auto-generated method stub
        return null;
    }
    @ServiceMethod
    public Gift readGift(Long id) {
        // TODO Auto-generated method stub
        return null;
    }
    @ServiceMethod
    public Gift updateGift(Gift gift) {
        // TODO Auto-generated method stub
        return null;
    }
    @ServiceMethod
    public void deleteGift(Gift gift) {
        // TODO Auto-generated method stub
    }
    @ServiceMethod
    public List<Gift> queryGifts() {
        // TODO Auto-generated method stub
        return null;
    }
}
 
You'll notice that the Service class above imports a generated annotation class too:


package com.yrdomain.yrproject.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation on method specifying that the method is a service method
 * and needs to have the corresponding request factory code
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface ServiceMethod {
}
 
YrprojectServiceLocator.java

package com.yrdomain.yrproject.server;

import com.google.web.bindery.requestfactory.shared.ServiceLocator;

public class YrprojectServiceLocator implements ServiceLocator {

    @Override
    public Object getInstance(Class<?> clazz) {
        try {
            return clazz.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
 
That's enough for one post... next, making it do stuff!

Thursday 24 November 2011

FATAL EXCEPTION: IntentService due to NullPointerException on PendingIntent.getActivity()

When sending a message to your Android device you use the default GWT template provided:

C2DM web service

You must have used a registered email address (see previous post) otherwise you'll get a Failure. If all is fine you'll get a Success: message sent message.
However, just because all things are rosy this side, doesn't mean that your phone has picked up the message:

11-24 17:37:35.586: E/AndroidRuntime(1339): FATAL EXCEPTION: IntentService[role@yrdomain.com]
11-24 17:37:35.586: E/AndroidRuntime(1339): java.lang.NullPointerException
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at android.app.PendingIntent.getActivity(PendingIntent.java:195)
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at com.example.yourname.Util.generateNotification(Util.java:120)
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at com.example.yourname.MessageDisplay.displayMessage(MessageDisplay.java:44)
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at com.example.yourname.C2DMReceiver.onMessage(C2DMReceiver.java:82)
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at com.google.android.c2dm.C2DMBaseReceiver.onHandleIntent(C2DMBaseReceiver.java:112)
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at android.os.Handler.dispatchMessage(Handler.java:99)
11-24 17:37:35.586: E/AndroidRuntime(1339):     at android.os.Looper.loop(Looper.java:137)
11-24 17:37:35.586: E/AndroidRuntime(1339):   
at android.os.HandlerThread.run(HandlerThread.java:60)

This is due to the default code that comes with the standard New install of the Android Cloud to Device Messaging (C2DM):

    /**
     * Display a notification containing the given string.
     */
    public static void generateNotification(Context context, String message) {
        int icon = R.drawable.status_icon;
        long when = System.currentTimeMillis();

        Notification notification = new Notification(icon, message, when);
        notification.setLatestEventInfo(context, "C2DM Example", message,
                PendingIntent.getActivity(context, 0, null, PendingIntent.FLAG_CANCEL_CURRENT));
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        SharedPreferences settings = Util.getSharedPreferences(context);
        int notificatonID = settings.getInt("notificationID", 0);

        NotificationManager nm = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        nm.notify(notificatonID, notification);

        SharedPreferences.Editor editor = settings.edit();
        editor.putInt("notificationID", ++notificatonID % 32);
        editor.commit();    

    }
 
Besides the fact that they really should be using the new Notification.Builder (introduced in Honeycomb API 11), this piece of code gives a NullPointerException because of the null value given where an Intent is expected.

PendingIntent.getActivity(context, 0, null, PendingIntent.FLAG_CANCEL_CURRENT));
 
All you have to do is add an Intent:

PendingIntent.getActivity(context, 0, new Intent(Util.DUMMY_PENDING_INTENT)
PendingIntent.FLAG_CANCEL_CURRENT));

You could use an existing one declared in Util.java, or you can create a new one like I did here called DUMMY_PENDING_INTENT. It doesn't matter because we are not going to use the Intent to start an activity, it's just an example to display a message on the notification bar. In a real program you would launch your app, just as an email notification launches your email app, etc.

Wednesday 23 November 2011

Your First Connect to the Cloud Error: PHONE_REGISTRATION_ERROR

When you set up your new project you added in your role email address as in this image. This is the same role email address that you used to sign up for Android Cloud to Device Messaging. If you haven't done this yet then go to http://code.google.com/android/c2dm/signup.html and fill in the form and wait for the confirmation email before proceeding.

Configure C2DM

You build the projects and launch in Debug for the first time. All Android devices have the concept of a Google email address and password that is usually set up on the first day you have the phone. Thereafter you don't have to supply your email address and password every time you connect to a Google service. However, if you try to connect to the cloud using the role email address that you used to register with C2DM then you'll get the following error:

C2DM Connect to the Cloud Screen

11-23 15:39:11.444: E/C2DM(629): Registration error PHONE_REGISTRATION_ERROR
11-23 15:39:31.584: I/dalvikvm(629): threadid=3: reacting to signal 3
11-23 15:39:31.623: D/dalvikvm(629): threadid=1: still suspended after undo (sc=1 dc=1)
11-23 15:39:31.623: I/dalvikvm(629): Wrote stack traces to '/data/anr/traces.txt'
11-23 15:39:41.677: D/AndroidRuntime(629): Shutting down VM
11-23 15:39:41.677: W/dalvikvm(629): threadid=1: thread exiting with uncaught exception (group=0x409951f8)
11-23 15:39:41.854: E/AndroidRuntime(629): FATAL EXCEPTION: main
11-23 15:39:41.854: E/AndroidRuntime(629): java.lang.RuntimeException: Error receiving broadcast Intent { act=comexample.yourname.UPDATE_UI flg=0x10 } in com.example.yournameActivity$1@41058dd8
11-23 15:39:41.854: E/AndroidRuntime(629):     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:737)
11-23 15:39:41.854: E/AndroidRuntime(629):     at android.os.Handler.handleCallback(Handler.java:605)
11-23 15:39:41.854: E/AndroidRuntime(629):     at android.os.Handler.dispatchMessage(Handler.java:92)
11-23 15:39:41.854: E/AndroidRuntime(629):     at android.os.Looper.loop(Looper.java:137)
11-23 15:39:41.854: E/AndroidRuntime(629):     at android.app.ActivityThread.main(ActivityThread.java:4340)
11-23 15:39:41.854: E/AndroidRuntime(629):     at java.lang.reflect.Method.invokeNative(Native Method)
11-23 15:39:41.854: E/AndroidRuntime(629):     at java.lang.reflect.Method.invoke(Method.java:511)
11-23 15:39:41.854: E/AndroidRuntime(629):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
11-23 15:39:41.854: E/AndroidRuntime(629):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
11-23 15:39:41.854: E/AndroidRuntime(629):     at dalvik.system.NativeStart.main(Native Method)
11-23 15:39:41.854: E/AndroidRuntime(629): Caused by: java.lang.NullPointerException
11-23 15:39:41.854: E/AndroidRuntime(629):     at android.app.PendingIntent.getActivity(PendingIntent.java:195)
11-23 15:39:41.854: E/AndroidRuntime(629):     at com.example.yourname.Util.generateNotification(Util.java:120)
11-23 15:39:41.854: E/AndroidRuntime(629):     at com.example.yournameActivity$1.onReceive(yournameActivity.java:81)
11-23 15:39:41.854: E/AndroidRuntime(629):     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:728)
11-23 15:39:41.854: E/AndroidRuntime(629):     ... 9 more

This is because you are trying to connect without a proper gmail address. If you have connected up your live device, choose another email address such as your personal one to test. If you are using the simulator, you need to go into the Settings and add another google account - again add your personal one. You'll then have success :)

C2DM Contacting server

C2DM Successful response from App Engine

New App Engine Connected Android Project Won't Build

It's really irritating when watching a really cool video showing how easy it is to create a new project and right out of the box (so to speak) it doesn't compile :(

This happened to me whilst checking out the cool new App Engine Connected Android Project tutorial from Google IO 2011.

You have to download the Google plug-in for eclipse first of course, but then select New > Other > App Engine Connected Android Project.

It doesn't build - lots of errors - specifically can't find:

com.example.yourname.client.MyRequestFactory;
import com.example.yourname.client.MyRequestFactory.RegistrationInfoRequest;
import com.example.yourname.shared.RegistrationInfoProxy;

All we need to do is to build the two projects properly:
  1. Right-click on yourname-Android >Build Path > Configure Build Path... and go to the Projects Tab.
  2. Add the yourname-AppEngine project to the Android project by pressing the Add button and choosing it.
  3. Right-click on yourname-Android > Debug As >Local App Engine Connected Android Application.
No more red :)

If you do get errors then first try Clean and then Build. Other than that it's the standard turn it off and then on again, sometimes delete project (not files!!!!!) from workspace and re-import them (hence do NOT delete contents of project on disk!!!) otherwise Google it - maybe there's a problem release?

Monday 14 November 2011

Google Map View Tutorial

Trying out the Google Map View tutorial at http://developer.android.com/resources/tutorials/views/hello-mapview.html I found a few sticking points.

My first problem was when faithfully copying the code was in overriding the the boolean com.google.android.maps.ItemizedOverlay.onTap(int index) method to give a fatal exception.

FATAL EXCEPTION: main
java.lang.NullPointerException
 at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:136)
 at android.app.AlertDialog$Builder.<init>(AlertDialog.java:353)
 at com.example.HelloItemizedOverlay.onTap(HelloItemizedOverlay.java:87)
 
Weird... what's going on here then. The first part of the tutorial tells me to delete the theme information so I thought that maybe I'd deleted a bit too much stuff or made another error... but no.

Of course the first thing I should have done is put in some breakpoints and step through to the offending line to look at my NullPointerException. This clearly told me that the mContext was null in HelloItemizedOverlay.onTap():

AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
 
Well of course it was, I hadn't set it! Also, looking closely at the code I could see that the setting of the mContext variable was in the constructor that I didn't use because I hadn't changed this on the HelloGoogleMapsActivity class.

So I could see that the tutorial required more than just cutting and pasting so had a think about it and made the following changes:

1. HelloGoogleMapsActivity.onCreate() I changed the call to the overlay class HelloItemizedOverlay:

HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable, this);

Remember that Activity is an indirect subclass of Context so this is fine.

Activity extends android.view.ContextThemeWrapper which extends android.content.ContextWrapper which extends android.content.Context

Try using getApplicationContext() and you'll run into android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application errors.

2. HelloItemizedOverlay constructor chain to the other constructor instead of a call to super. The other constructor then calls super.

public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
 this(defaultMarker);
 mContext = context;
 }
public HelloItemizedOverlay(Drawable defaultMarker) {
 super(boundCenterBottom(defaultMarker));
 }
 
That's it, done! The dialogue appears when the android is clicked:

HelloGoogleMaps dialogue after tap on android

Couldn't get connection factory client

Sometimes when setting up your Android development environment for the first time you'll get an error like: Couldn't get connection factory client

For example: Trying out the HelloGoogleMaps tutorial from http://developer.android.com/resources/tutorials/views/hello-mapview.html

Sometimes it may be due to an invalid Maps API key so check that you have done this correctly.

If you have followed all the instructions and haven't cut corners then the next thing to try is your DDMS settings.

In Eclipse go to Window > Preferences > Android > DDMS and set your ADB connection time out (ms) from the default 5000 to 10000.

This gives the notoriously slow AVD a chance to get going with the request before it times out.

Friday 11 November 2011

Welcome to Jump Source

We are going to use this site to blog about our day to day coding activities which include development on both iOS and Android platforms and web development using HTML/CSS and the Joomla! CMS. We will also cover various allied topics on game design, game physics, marketing apps, and on tools like source Control, IDEs etc

Over the years we have had a great deal of support from various blogs and forums and we now feel it's time to contribute ourselves.

We are software developers just like you, who are dealing with various problems day to day. When we find solutions which we feel with benefit others we will share them with you here.