Null Intent passed back On Samsung Galaxy Tab…

So, I’ve had a rough few days, and by rough, I’m talking about the equivilant of a goats knee kinda rough. And if you haven’t guessed it yet, it has to do with the Samsung Galaxy Tab(the 7 inch guy), and null intents when using the camera from inside your app.

Let me set the scene, first, and tell you my story.  I was über excited to recieve my very own “work purchased” Samsung galaxy tablet yesterday, to be used for, among other things, developing some Android applications. I couldn’t contain my excitement, and this was way more fun than filling in my timesheets, so, I cracked the sucker open and began developing a little something that basically made use of the camera functionality. So I initially set off to create a test Activity which had a Gallery control, and a button to activate the camera. All I wanted to do was create a sample app, which would populate the gallery with the photos that I’d take. However, I couldn’t help but be reminded of how similar grappling with the camera functionality on the Samsung Galaxy tab is issuing a command to my ridgeback dog Bruno. Neither of them does what you expect it to! Instead, you’re just left surprised while it does its own crazy thing!  🙂

So in my example, I thought I’d try something simple. Just start the camera activity with the method call to startActivityForResult, and in the method onActivityResult, when the camera returns, I expected to be able to get both the thumbnail and the actual image in the intent’s data. Alas, this is not the case. It appears that if you populate the EXTRA_OUTPUT extra with a URI of where to store the new photo, then the camera will store the photo there for you. Now in my experience, this is true, however, with a little annoying caveat. Not only will the camera store it in the URI location that you supplied, but it also stores it in the default location of its own!

I had another problem. I wanted not only the thumbnail, but also the actual image. For the purpose of this, I didn’t really need the actual image, but more the location of where I could go and get it. Now when using the method I just previously spoke about, by providing the EXTRA_OUTPUT extra on the request intent, the camera on return to the onActivityResult, ends up passing back a NULL intent, which used to have the thumbnail image in the extra key called “data“. Now you have diddley squat!

Yet another problem I faced was that, the URI I was passing in the request intent, to tell the camera where to save this image, always ended up being NULL when the onActivityResult method was called. So now, not only do I have to somehow persist the URI that I had already passed into the request intent (to prevent it from becoming null), I now also didn’t have a thumbnail to speak of – which I used to get from the “data” extra in the return intent.

Plan B…..

It seemed that from all my reading, the best way was to create a temp file, that always had a deterministic name and location, create the file, then create a URI from that, and pass that as part of the request intent, and you could reconstruct the URI when the onActivityResult was called. Thats great, but where’s my thumbnail? Still not there? <sarcasm>Nice!</sarcasm>

Plan C….

So this is what I eventually had to resort to, in order to get both the thumbnail, AND actual image location in order to populate my gallery control with the thumbnails, and retain the actual image location so that I could display it when the user tapped on the thumbnail, and thereby also avoiding any duplicate images being stored :

Call the Camera activity as per normal Don’t do anything fancy, just create the intent with the ACTION_IMAGE_CAPTURE constant. That way, you don’t create duplicate images all over the place.

On the return call of onActivityResult, you need to do a managedQuery on the MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI and MediaStore.Images.Media.EXTERNAL_CONTENT_URI locations, and selecting the last image that was captured. This way, you are able to obtain a handle to both the thumbnail, and the image without having to deal with all the weirdness of before. Once you have these, then you’re good to go! I’ve posted some sample code below to show you what I’m talking about.


private static final int CAMERA_IMAGE_CAPTURE = 0;

public void btnTakePhoto_onClick(View view){
 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 startActivityForResult(intent, CAMERA_IMAGE_CAPTURE);
 }

&nbsp;

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 if(requestCode==CAMERA_IMAGE_CAPTURE && resultCode==Activity.RESULT_OK){

// Describe the columns you'd like to have returned. Selecting from the Thumbnails location gives you both the Thumbnail Image ID, as well as the original image ID
String[] projection = {
 MediaStore.Images.Thumbnails._ID,  // The columns we want
 MediaStore.Images.Thumbnails.IMAGE_ID,
 MediaStore.Images.Thumbnails.KIND,
 MediaStore.Images.Thumbnails.DATA};
 String selection = MediaStore.Images.Thumbnails.KIND + "="  + // Select only mini's
 MediaStore.Images.Thumbnails.MINI_KIND;

 String sort = MediaStore.Images.Thumbnails._ID + " DESC";

//At the moment, this is a bit of a hack, as I'm returning ALL images, and just taking the latest one. There is a better way to narrow this down I think with a WHERE clause which is currently the selection variable
Cursor myCursor = this.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, selection, null, sort);

long imageId = 0l;
long thumbnailImageId = 0l;
String thumbnailPath = "";

try{
 myCursor.moveToFirst();
imageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
thumbnailImageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
thumbnailPath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
}
finally{myCursor.close();}

 //Create new Cursor to obtain the file Path for the large image

 String[] largeFileProjection = {
 MediaStore.Images.ImageColumns._ID,
 MediaStore.Images.ImageColumns.DATA
 };

 String largeFileSort = MediaStore.Images.ImageColumns._ID + " DESC";
 myCursor = this.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, largeFileProjection, null, null, largeFileSort);
String largeImagePath = "";

try{
 myCursor.moveToFirst();

//This will actually give yo uthe file path location of the image.
largeImagePath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
}
finally{myCursor.close();}
 // These are the two URI's you'll be interested in. They give you a handle to the actual images
 Uri uriLargeImage = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(imageId));
 Uri uriThumbnailImage = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, String.valueOf(thumbnailImageId));

// I've left out the remaining code, as all I do is assign the URI's to my own objects anyways...

}
}

I hope this helps someone else out there, cause this had me baffeled for a while. I don’t know what this just can’t be easier. Surely there’s no need to have to jump through hoops like this. Anyhoo, I’m working on getting the better managed query working, and I’ll just use this when I need it. It seems to work for the most part anyway.

Different Responses with Spring REST

So lately I’ve been delving into Spring REST, and playing around with a few things, and something dawned on me which hadn’t occurred to me until I was actually messing around with a side project I have going on at home. Spring provides you the capability to return content in 2 different fashions:

  1. Either as a representation of the Model Object OR
  2. Either as the actual formatted content in the response body in whatever format(xml, json etc)

It’s important to draw the distinction between information being returned to you directly via the response body, and the model object. An example is probably in order.

Let’s say we have our standard Spring MVC project set up, and we have the controller class HomeController

@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value="/home", method=RequestMethod.GET)
public String home(ModelMap model) {
logger.info("Welcome home!");
model.addAttribute("attribute", "home-gerome");
return "home";
}
}

and the relevant xml for the spring configuration looks like this:

<bean id="xStreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="autodetectAnnotations" value="true"/>
<!--<span class="hiddenSpellError" pre=""-->bean>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1"/>
<property name="mediaTypes">
<map>
json" value="#{T(org.springframework.web.servlet.view.json.MappingJacksonJsonView).DEFAULT_CONTENT_TYPE}"/>
<entry key="xml" value="#{T(org.springframework.web.servlet.view.xml.MarshallingView).DEFAULT_CONTENT_TYPE}"/>
</map>

</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg name="marshaller" ref="xStreamMarshaller"/>
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true"/>
</bean>

There’s nothing special about this configuration, its pretty standard, and I managed to gleam most of it off of the Spring documentation, and the API docs on the ContentNegotiatingViewResolver

Notice how there’s only a @RequestMapping annotation on the method, nothing else, and the ModelMap parameter being passed in. If you build your HTTP GET request ( I use an add-on called REST Client for Firefox), for the home.json resource, you’ll notice that the response body actually returns like this:

{"attribute":"home-gerome"}

No surprises here that is looks just like the content of the Model, with the key-value pair.

I’d just like to mention that if I made a request for home.html, instead of home.json, I’d actually get the HTML content of the home.jsp page in the response body, and there will be no trace of the ModelMap data here. This is purely down to the ViewResolver chaining where the ContentNegotiatingViewResolver wouldn’t be able to satisfy my request for my .html request, and would then move onto the 2nd ViewResolver I had configured which can. Seeing as though I made the request for home.json, the ContentNegotiatingViewReolver finds a class that can resolve a view for the request, and it uses the MappingJacksonJsonView to resolve the request and format a response, which looks at the ModelMap, to return data back to the calling client. Requests ending in .json, or .xml etc are preferred over the Accept Headers in the request, although this is also configurable in the ContentNegotiatingViewResolver.

Also, you’ll see I’ve added the property ignoreAcceptHeader=true, and I did that because of another “problem” I faced while working with HTTP requests and how Spring uses them to make certain choices, and subsequently learnt that HTTP Headers can be evil… but more on that in another post. So for now, I’ve actually set this property in my project to ignore Accept Headers for now, and just use the extensions on the request to determine how content should be delivered.

Now, having spring deliver content via the @ResponseBody opens up another can of worms. In fact, I was going to try and give you an example here, but after I finished I felt that this post actually ended up being way too massive so I’ll possibly address @ResponseBody use and configuration in an upcoming post. Suffice to say though, that although it is nice to have your objects returned directly via the response body when using the @ResponseBody annotation, doing so doesn’t come without its fair share of additional configuration and hacking about.

In chatting to some others who have used Spring REST, and all the goodness it offers, I’ve come to the conclusion that many are left with the question of when to use @ResponseBody as opposed to just the traditional way before @ResponseBody came onto the scene. From what I’ve seen so far, I’d make the decision based on the following

You have an existing Spring MVC website in place, and you want to make it deliver content in json and xml format.

Well, if this is the case, I’d avoid using @ResponseBody, and I’d just populate the ModelMap object with the content I want to send back to the client. The reason for this being that, I can still then make use of the view resolving that happens for me when I return a string to lookup the .jsp page and render that content back. However if I stick a @ResponseBody tag on my method, I’m effectively responsible for doing all of that myself, i.e. returning the actual content to the response, and I lose all that spring automagic that happened before. So for situations where you want to run your website and your REST requests/responses off of the same MVC controller, then I’d stay away from @ResponseBody.

Another good reason for avoiding the @ResponseBody, is that for GET requests, Spring doesn’t seem to be able to work out (yet) which formatter to correctly pick other than looking at the accept headers. When you use @ResponseBody, as part of the configuration, you’ll setup HTTPConverters responsible for formatting the content, and you’ll configure them to only listen for certain accept headers by populating the supportedMediaTypes property. As I’ve mentioned just previously, I’ve just recently learnt that when relying on browsers coming to your website, accept headers can be evil.. so stay away! 🙂

You don’t have to service browser requests, and will only be serving content to clients to have control the accept header.

If all you need is something that interacts with a representations of your domain objects, then I’d say go for the @ResponseBody annotation. Purely because clients are more than likely in control of setting things like HTTP headers, and when using @ResponseBody with GET requests especially, you have to add the headers property of the @ResponseBody annotation to tell spring which method to effectively call for which type or representation. So your controller would look something like this:

These are my experiences so fat while using @ResponseBody. I’ve only just started realising its benefits, but I think it needs to be said that if you;rethinking about using the @ResponseBody feature, think carefully about where, and how you want to use it, because it can give you more headaches than its worth.

Mobile Workforce on Android

So, just recently my company, G3 Global, tasked me with investigating mobile application development, with the intention to integrate into SAP. So as a proof of concept, I managed to put together a prototype mobile application that simply mimics the role of your mobile engineering workforce out in the field.

The idea simply demonstrates a job listing for an engineer, allowing them to review the job details, and contains the ability to take before and after photos of the job, as well as geo tagging the images with their current GPS location, to pin point where the images were taken. I believe Drew has already beaten me to the post (no pun intended) but if you haven’t seen it there yet, then check out the cool video we put together:

You can also find the original post on my company blog here: ‘Mobile Workforce On Android

The beginnings of my new journey

So, after a very very long time, I’ve decided to pick up blogging again. Hopefully this time I’ll be able to find the time I seemed to have lost previously, to blog my software development musings as well as some other cool interests I have including my motorcycle and photography!

So without taking up too much time on the first post, I just wanted to say, “I’m back!”

Expect great things on this here blog over time, as I plan to plot my journey ,traversing the world of .NET and Microsoft and into the unknown world of Java and all of its open source goodness!

Until next time….