Wednesday, May 22, 2013

Sencha Touch Split Window

Wow, almost a year since my last post. It's been a crazy time. I've been on multiple projects with super tight deadlines. As a matter of fact, I don't seem to recall a project with a loose deadline in the recent past. I've been working with Sencha Touch recently. There's a lot to love about the framework, but still enough annoyances. A recent requirement had me scrambling for a splittable view. This is what I finally came up with:

Wednesday, May 16, 2012

Couldn't help but share this great comic from Matt Bors. I saw him in this Boing Boing post and highly recommend that you visit his site and support his creative work!

Thursday, May 10, 2012

RESTful WCF Services with jQuery Mobile (part 2)

In order to get up and running as quickly as possible with jQueryMobile, we're going to copy the Single Page template. Note: In order to simplify this example, I'm adding the single page template HTML directly to the WCF project. I would normally use a multi-page template and separate the UI from the services in a production project and I suggest you do the same.
With that said, create a new html document in your project's root named index.html. Navigate to the Single Page Template, view the source, copy it, and paste it over the contents of the index.html document. Congratulations, you've just integrated jQueryMobile with your project. Now you just need to request and receive data from your service.
The template is broken into a header, content, and a footer section. All of the scripts are loaded from a remote server so you don't need to download anything into your project at this time. Start by removing the paragraph elements within the content section. Add a unordered list element with a data-role of listview. jQueryMobile will handle the styling of this list to make it look like your standard iOS tableview component. We're also going to add a hidden listitem element with an id of categoryTemplate. What we end up with looks like the following. Note that there's also a reference to a category.js file. Create a blank file with that name for now. Finally, we add the javascript to call our WCF service. The function below uses the $(document).ready() function to wait for the content (including jQueryMobile) to load. once it does, the ajax function is called. It shows a page loading message with an animated image when the request starts and hides it when the request has completed. We're specifying that we're sending and receiving json data using a POST method just as defined in the WCF method attributes. Finally, we use the data returned by the service. Recall the structure from the previous post, the object name is GetProductCategoriesResult, so we iterate over the contents of that object, creating a clone of the template node and replacing its text. Finally, we call the listview(refresh) to ensure that jQueryMobile styles the content appropriately.

Friday, May 4, 2012

RESTful WCF Services with jQuery Mobile (part 1)

One of the most essential techniques in mobile application development is getting data to and from a remote server and displaying it in your application's user interface. As such, it's also one of the more common questions asked in the PhoneGap discussion group. In this post, I'm going to cover the basics of configuring a WCF Service to accept requests using a RESTful interface, returning data in JSON format, and utilize the response to populate the user interface in a jQueryMobile user interface. For this example, the UI will be running from the server with the service, but it could just as easily be running within PhoneGap on a mobile device.

These techniques aren't unique to mobile development. The basic pattern can be applied to any web site. Additionally, while this post covers WCF Services in .NET, other server platforms and technologies would work just as well with jQueryMobile.

The first step in developing a dynamic, AJAX driven user interface is exposing your web service endpoints. Visual Studio 2010 and the Windows Communication Foundation really simplifies this task. It's easy to beat up on Microsoft for their missteps, but WCF is a really solid technology and is the Swiss Army Knife of data plumbing.

Visual Studio 2010 has taken much of the configuration pain out of WCF. It makes the simple things simple, and the complex things possible. Let's start by opening Visual Studio 2010 and creating a new WCF Service Application. Name the project MobileService and the solution MobileSolution, saving the project where the rest of your projects are stored (for convenience sake, I like to store projects in c:\projects, but that's just me.
When the project is created, we start with some stubbed out code to load a class named Service1 using interface IService1 through a service named Service1.svc. Since none of this applies to the solution we want to build, we're going to get rid of it all and start from scratch.
  1. Delete the IService1.cs and Service1.svc files
  2. Remove everything from the Web.config file between <system.serviceModel> and </system.serviceModel>
Right-click on the MobileService project and select Add->New Item. Select AJAX-enabled WCF Service, naming it MobileService.svc
This will add missing elements back into your web.config and create the service file. It also takes care of assigning ASPNetCompatibility. The AspNetCompatibilityRequirements attribute is required for RESTful services. Visual Studio has enabled Web Script in the web.config file. This is a Microsoft-specific method of binding javascript to your WCF method. It won't work with REST, so let's remove it by eliminating the <enableWebScript /> line from the web.config file. While you're at it, rename the behavior to MobileService.webHttpBehavior and add a webHttp element. The name is used to describe what the behavior is for an will be referenced later in the config. The webHttp element specifies that the webHttp binding will be used. This relatively simple binding uses the URI + verb dispatcher to be used. This is what you'll end up with when you're done:
With the configuration straightened out, we'll turn our attention to the body of the service. Start out by eliminating the boiler plate method. For our scenario, we're going to accept a POST and return a list of strings in JSON format. The code for this is shown below. What's important to note is the WebInvoke attribute. This is our connection from the request to the function body. If we were using a verb other than post, we would map the Uri elements to function parameters. Because we're using POST and because this method doesn't require parameters, we're omitting this step. Also note that the message style is wrapped. This allows us to send JSON data to and from the server. At this point, we can fire up Fiddler2 and test this service. Run your application with F5 and copy the url. Switch to fiddler and click on the composer tab. Add the url of your service, the port it's running on, the name of the service, and the UriTemplate from the method. You'll also need to specify that you're working with data in json format by adding Content-type: application/json to the request headers. When you're done, you'll have something like this:
Click the execute button and if you put everything together right, you should see a 200 response in the list of http traffic to the left. Opening that response, you should see something like this:
This shows you the structure of the JSON data returned by your service. Next up - creating a jQueryMobile page that consumes that data.

Tuesday, April 10, 2012

Changes to SMS Plugin for PhoneGap 1.5

The PhoneGap transition to Cordova introduced some changes to the plugin Architecture. I've been focusing a little on Sencha / Titanium (just broadening my horizons not abandoning the platform), so I haven't really had an opportunity to look at the full scope of the changes. Since at least one person is having adapting the SMSPlugin to 1.5, here's a short list of changes. I'll get these changes into the git repository when I have a chance. It appears that the only changes required in the plugin are: Remove the import "com.phonegap.api.PluginResult.Status" and replace it with "org.apache.cordova.api.PluginResult.Status", and change the first parameter of the pendingIntent.getActivity call from "this.ctx" to "this.ctx.getContext()"

UPDATE: These changes have been merged with the phonegap-plugins repository on GitHub

/*
Copyright (C) 2011 by Daniel Shookowsky

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package net.practicaldeveloper.phonegap.plugins;
import org.json.JSONArray;
import org.json.JSONException;

import android.app.PendingIntent;
import android.content.Intent;
import android.telephony.SmsManager;

import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import org.apache.cordova.api.PluginResult.Status;

public class DemoPlugin extends Plugin {
 public final String ACTION_SEND_SMS = "SendSMS";
 
 @Override
 public PluginResult execute(String action, JSONArray arg1, String callbackId) {
  PluginResult result = new PluginResult(Status.INVALID_ACTION);
  
  if (action.equals(ACTION_SEND_SMS)) {
   try {
    String phoneNumber = arg1.getString(0);
    String message = arg1.getString(1);
    sendSMS(phoneNumber, message);
    result = new PluginResult(Status.OK);
   }
   catch (JSONException ex) {
    result = new PluginResult(Status.ERROR, ex.getMessage());
   }   
  }
  
  return result;
 }

 private void sendSMS(String phoneNumber, String message) {
    SmsManager manager = SmsManager.getDefault();
  
    PendingIntent sentIntent = PendingIntent.getActivity(this.ctx.getContext(), 0, new Intent(), 0);
  
    manager.sendTextMessage(phoneNumber, null, message, sentIntent, null);
 }

}

Tuesday, December 6, 2011

Debugging Phonegap/Cordova Applications

When developing a mobile application with PhoneGap, there inevitably comes a point when things don't work as expected.

When this happens, I triage the application in the following order:

  1. Sanity Checks on the HTML and JavaScript
  2. Verify event binding
  3. Inspect variable values
  4. Wire protocol analysis

Sanity Checks

JavaScript is a Misunderstood Dynamic Language. Unfortunately, that rules out many compile-time sanity checks. The good news is that it doesn't rule them all out. JSLint is an excellent tool to add to your Eclipse environment to quickly look at your code for syntax errors. Personally, I turn off the options for whitespace checking and add a list of known, created classes and configure JSLint to inspect all javascript files in my project. This simplifies the checking of my own flaky code. The only downside is that other included libraries have to be cleared to remove "problems" in the output. JSLint can be very strict in what it considers acceptable JavaScript (=== versus == as an example). The easiest solution is to right click any 3rd party files such as the phonegap-1.2.0.js file and the jquerymobile/jquery javascript files and tell rockstarapps to clear javascript errors. This allows any errors in your own JavaScript files to show through in the Eclipse problems window.

Verify Event Binding

When verifying event binding, the easiest solution is a simple alert message. In many cases this is all that's needed. If you'd like to instrument your code further, you can use the console.log statement. This is visible in the IDE debugging window in many environments. console.log allows you to write out debugging messages that don't interfere with the flow of your application in the same way alert messages would. There are some notable exceptions where the device will not report the message. Most commonly, when running on a physical device (e.g. HTC Evo) console.log messages aren't logged in Eclipse. In these cases, you can turn to weinre (pronounced "winery"). This tool works by running a local server and communicating with this server from your PhoneGap Application. This is a fantastic bit of technology, but the setup can be a bit daunting. Fear not, the PhoneGap devs have provided a wonderful service at http://debug.phonegap.com/. This service allows you to enter a globally unique ID (I simply use my name). By inserting a javascript link with this guid, your mobile device can automatically route console.log information to the phonegap server where you can view the output. Communication is two-way, allowing you to highlight html elements and see the regions highlighted on the device. The latter feature is invaluable for identifying bits of dynamic content that didn't work out as planned.

Inspecting Variable Values

While developing applications, I tend to go through a large number of iterations simply in chrome. After developing the UI, I view it in chrome and use the inspect element feature to view details about the output. Using CTRL+SHIFT+I, I can bring up an environment that allows me to inspect CSS styles, step through javascript, and view the resulting HTML in the browser. The key to working well with this is isolating your user interface code from the device. As an example, I like to create javascript classes that have canned data in addition to the live server data. This allows me to eliminate data/network issues from the user interface. In the same way, I insulate the user interface from the physical device. This allows me to test my interface in a desktop browser without the overhead of an emulator (more iterations == faster development), and it allows me to rule out issues between PhoneGap and my own code (hint: it's always my code that's wrong).

Wire Protocol Analysis

If your user interface looks right with the data you're expecting, but you're not getting what you're expecting, it's time to rule out issues between the client and the server. In these cases, I like to use WireShark to capture the communication between the client and the server (again isolating the physical device as much as possible from the equation). Before selecting the network interface to capture on, I navigate in my application as far as possible before the issue in question. This reduces the junk I have to look through while debugging. You can definitely do this with filters in WireShark, but for the novice, it's easier to limit the incoming data.

Last Recourse

When none of these techniques solve my problems, I tend to post to the phonegap google group. I encourage all of you to do the same and please don't be shy if you have a possible solution to someone else's problem. Even if it isn't the perfect answer, it can set someone on the road to success.