Thursday 15 December 2011

Setting up a project in XCode 4.2 with Git and Bitbucket

Xcode now includes a powerful source control client which supports (in fact by default uses) the Git DVCS.

Bitbucket have recently started offering unlimited private repositories (for free!) and now support both Git and Mercurial repositories.

If you're starting a new closed source iOS project and want to store your app source safely offsite but at the same time can't initally afford to pay a fee for the privilege then this is great news.

An hour or so ago, I discovered this great news myself and decided to give it a try. I've had some dealing with various source control systems over the years but up until today I've not had the pleasure of using Git. I've previously been a CVS and Subversion user.

I did a quick google to see if many people were using Bitbucket with Xcode and discovered quite a few threads where people had found issues getting the two to play nicely together, so I decided to have a go myself.

Its quite an easy process in Xcode 4.2, here are the steps:

Step 1: Register with Bitbucket

Step 2: Start a new Xcode project, select the option for Xcode to put your source under version control. It will create a Git repository for your project. You can find the repositories Xcode is managing in the Organizer on the Repositories page.

Step 3: Create a new repository on Bitbucket.  Select Git as the repo type.

Step 4: Bitbucket will show you a command to type to clone your repository locally. We won't use this command but copy the url from the command eg:

https://jumpsource@bitbucket.org/jumpsource/hellobucket.git

Step 5: In Xcode open up the Organizer and switch to Repositories, find your new project's repository. Under your repository name you'll see 3 folders: Branches, Remotes & YourProjectFolder, select Remotes.

Step 6: At the bottom of the screen you'll see the Add Remote option - select it and enter a name for your remote repository and in the URL paste the one you copied from bitbucket in step 4.

Step 7: Click Create, enter your username and password when prompted.

Step 8: You should now have an empty folder in the Remotes view with the name of your remote repository.

Step 9: You now need to Push your local changes to your empty remote repository. To do this, from the menu in Xcode choose: File -> Source Control -> Push. Select the remote repository to push to - if your reading this article there will probably just be one remote - the one you just configured in step 6 & 7. Press Push, Xcode will chug for a bit, then report (hopefully!) that the push was successful.

Step 10: Refresh your page at Bitbucket and you will see your updates.

Wednesday 14 December 2011

Not able to Debug As... Local App Engine Connected Android Application for CloudTasks


I've downloaded the source code for the tutorial above and followed along the Brad Adams Blog but couldn't get the Debug As... option to come up. With some Googling I found this blog by Bill Lahti
which just changed the <nature> contents.

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
    <name>CloudTasks-Android</name>
    <comment></comment>
    <projects>
    </projects>
    <buildSpec>
        <buildCommand>
            <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>org.eclipse.jdt.core.javabuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>com.android.ide.eclipse.adt.ApkBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
    </buildSpec>
    <natures>
        <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
        <nature>org.eclipse.jdt.core.javanature</nature>
        <nature>com.google.gdt.eclipse.appengine.rpc.appengineConnectedNature
        </nature>
    </natures>


    <linkedResources>
        <link>
            <name>shared</name>
            <type>2</type>
            <locationURI>WORKSPACE_LOC/CloudTasks-
                AppEngine/shared</locationURI>
        </link>
    </linkedResources>
</projectDescription>

Friday 2 December 2011

Error: The RequestFactory ValidationTool must be run for GWT 2.4

When loading up the CloudTasks tutorial as downloaded from the Google website, I encountered the following Runtime error:

SEVERE: Unexpected error
java.lang.RuntimeException: The RequestFactory ValidationTool must be run for the com.cloudtasks.shared.CloudTasksRequestFactory RequestFactory type

I found this article:

http://code.google.com/p/google-web-toolkit/wiki/RequestFactoryInterfaceValidation

Here's an excerpt:
The RequestFactory annotation processor will validate the RequestFactory interface declarations and ensure that the mapping of proxy properties and context methods to their domain types is valid. The manner in which the errors are reported depends on the method by which the annotation processor is invoked.
In addition to validating the interfaces, the annotation processor also generates additional Java types which embed pre-computed metadata that is required by the RequestFactory server components. Users of RequestFactorySource must also run the annotation processor in order to provide the client code with obfuscated type token mappings. In the client-only case, the server domain types are not required.
If the validation process is not completed, a runtime error message will be generated:
The RequestFactory ValidationTool must be run for the com.example.shared.MyRequestFactory RequestFactory type
In GWT 2.4, RequestFactory interfaces must be validated before they can be used by the RequestFactory server code or JVM-based clients. I followed the instructions for Eclipse as follows:
  • Right-click on Project and select Properties > Java Compiler > Annotation Processing
  • Tick "Enable project specific settings"
  • Then make sure that both "Enable annotation processing" and "Enable processing in editor" are ticked.
  • Go to Factory Path underneath Annotation Processing in the left-hand menu
  • Click the button "Add External Jar"
  • Add the requestfactory-apt.jar file from your Eclipse distribution
  • Press Apply and the project will re-build.
The images on the above link ask you to add this file from GWT_TOOLS, but the text says to use your distribution. I found my file under:

C:\dev\eclipse-3.5.2\plugins\com.google.gwt.eclipse.sdkbundle_2.4.0.relr35v201110112027\gwt-2.4.0

Thursday 1 December 2011

Eclipse Android Library Error: Unable to get system library for the project

I downloaded some code via subclipse from the SVN server of Google to follow a tutorial. However, eclipse didn't know that it was an Android project and wouldn't let me build it as one no matter how many different ways I tried to add the android jar file. I found this great discussion on StackOverflow but this is what was wrong for me:
  • Right click on project > Properties > Android
  • Set Project build target (mine was ICS Android 4
  • Press Apply (I had to press apply 3 times for it to listen to me!)
  • Then go to Build Configuration and set the "Unable to get system library for the project" libraries Native folder to your Android jar (something like  C:/dev/AndroidSDK/platforms/android-14)
  • Right click on project > Android Tools > Fix Project Properties
  • Clean & Build
  • If nothing, try opening and closing the project
  • Also try pressing Apply on the build target some more
Sounds silly, but eclipse can be silly sometimes too!
Obviously check to make sure that you've set the Android SDK location in Window > Preferences > Android. My SDK location is C:\dev\AndroidSDK (not sure why eclipse holds the backslashes here and forward slashes above)

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.