Categories
iPhone Development jQuery Mobile Phonegap

Update on Drupal iOS Plugin for PhoneGap

I’ve made progress with the Drupal iOS plugin for PhoneGap, and I’m really happy with the results. I’m holding off on writing more posts in the Building a jQuery Mobile App with PhoneGap for Drupal series until I get all the functionality I need into the plugin – I’ve just got to add the file methods to upload a picture.

I’m also working on another Drupal demo app with jQuery Mobile and PhoneGap and the plugin – here’s a screenshot:

 

 

Link to the repo for the plugin : https://github.com/jefflinwood/Drupal-Plugin-for-PhoneGap-for-iOS

 

Categories
Drupal Planet iPhone Development Phonegap

Announcing: PhoneGap iOS Plugin for Drupal v0.1

PhoneGap iOS Plugin for Drupal v0.1 – Proof of Concept – https://github.com/jefflinwood/Drupal-Plugin-for-PhoneGap-for-iOS

While working on the Building an app with jQuery Mobile, Phonegap, and Drupal 7 series of blog posts, I found myself writing JavaScript to access the Drupal Services API, using jQuery’s $.post and $.get.

This quickly became unwieldy, so I felt like I either had to create a JavaScript library for interacting with Drupal that I could leverage in the future, or to follow the lead of the PhoneGap team and create a Drupal plugin in Objective-C that exposed Drupal Services with an easy-to-use JavaScript API. Because Kyle Browning’s Drupal iOS SDK already has code for interacting with the Drupal Services API, I decided to create a PhoneGap plugin.

Creating a PhoneGap plugin for iOS was a little trickier than I thought, mostly because the plugin documentation isn’t up to date, and PhoneGap is changing quick! I extended the PGPlugin class and used PluginResult to return NSDictionary objects from the Drupal iOS SDK to JavaScript.

Also, getting a PhoneGap project running with the Drupal Plugin will be a pain with version 0.1! This is mostly because PhoneGap bundles libraries into its framework that the Drupal iOS SDK needs. I’d like to make this as painless as possible to use, so that it’s easy to get started.

I’m also only exposing four methods in the 0.1 version of the plugin – node.get, user.login, user.logout, and system.connect. I’m planning on adding all of the methods that the Drupal iOS SDK exposes.

Here’s some sample code for PhoneGap that interfaces with the Drupal plugin API:

window.plugins.drupal.login(username, password, 
  successCallback,failureCallback)        
window.plugins.drupal.nodeGet(1,successCallback,failureCallback);

I’d like to get some feedback on this project from anyone who’s using PhoneGap now with Drupal to see if this solves a lot of the problems with writing a lot of JavaScript to interface with Drupal. There are also some memory management issues with camera uploads in particular that I’d like to make sure aren’t as big a problem with the Drupal plugin.

Next Steps for this project:
=================
* Finish the node methods from the Drupal iOS SDK
* Add the file methods from the Drupal iOS SDK
* Add the view methods from the Drupal iOS SDK
* Reduce the number of steps needed to add the Drupal Plugin to a PhoneGap application
* Figure out a testing strategy
* Document the JavaScript API
* Create a sample application
* Build an Android version
* Update/test plugin with PhoneGap 1.0

Categories
Talks Uncategorized

Building Mobile Applications with Drupal – Dallas Drupal Camp

Slides from my presentation at Dallas Drupal Camp 2011

Categories
Drupal Planet jQuery Mobile Phonegap

Building a jQuery Mobile HTML5 App with PhoneGap for Drupal 7, Part 2

In this post, we’re going to add functionality to take a picture to our jQuery Mobile app using the PhoneGap Media Capture API. We’ll add a button with jQuery Mobile that brings up the mobile phone’s camera.

With jQuery Mobile, to make buttons, we can use the <a href> tag with a data-role=”button” attribute. If you’re submitting a form, use the <button> tag instead – jQuery Mobile will format both of those the same way.  We’ll go ahead and add a button that doesn’t do anything yet – replace the contents of the <div data-role=”content”> tag with this:

<div data-role="content">             
  Welcome to the jQuery Mobile Demo App for Drupal!             
  <p/>             
  <a id="takePhotoButton" data-role="button">Take Photo</a>         
</div>

Run it in the iPhone Simulator, and it looks pretty good for us not having to do too much!

We’ll take advantage of jQuery’s bind method and PhoneGap’s deviceready event for our button functionality.

One gotcha you will probably run into is that you’re used to binding to the click event with jQuery on desktop browsers. With jQuery Mobile, we need to bind to the tap event for our button instead.

We’re using the PhoneGap Media Capture API with the camera – only one line of Javascript needed to bring up the camera on the phone.

navigator.device.capture.captureImage(captureSuccess, captureError, {limit: 1});

You’ll need to provide functions to handle success and errors, along with PhoneGap’s CaptureImageOptions. In our case, we’re limiting the number of photos the user can take to one at a time.

Here’s the JavaScript we need to add to our index.html

<script> 
        function captureSuccess(mediaFiles) {
            navigator.notification.alert('Success taking picture:');
        }        
        function captureError(mediaFiles) {
            navigator.notification.alert('Error taking picture: ' + error.code);
        }
        $(document).bind("deviceready",function () {
            $("#takePhotoButton").bind("tap", function() {
                navigator.device.capture.captureImage(captureSuccess, captureError, {limit: 1});
            });
        });
</script>

You won’t be able to see this run in the iPhone Simulator, because the iPhone Simulator doesn’t have a camera – instead, you’ll need to run it on an actual iPhone (or iPod Touch or iPad with a camera).

In my next post, we’ll cover how to upload images to Drupal 7 using Services 3.

Categories
Drupal Planet jQuery Mobile Phonegap

Building a jQuery Mobile HTML5 App with PhoneGap for Drupal 7, Part 1

In this series of posts, I’m going to discuss how to build a jQuery Mobile HTML5 App that talks to Drupal 7 using AJAX, REST and JSON. I’m going to use the PhoneGap project to create an iPhone application out of the jQuery Mobile app that you can install onto your iPhone. Using PhoneGap, you can also create apps for Android, WebOS, Android, Blackberry, and Symbian.

This first post in the series will get you up and running with jQuery Mobile and PhoneGap on iOS with XCode 4. We’ll get to Drupal a little bit further down the road, so if you just want to do some apps that don’t connect to a server, this post should be useful.

I’m going to use Drupal 7 as the server for the app. Drupal 7 has a lot of functionality built in, but not web services, so you will need to install the Services 3 module.

To build the client application, first download and install the latest version of PhoneGap, following the directions for getting started here:

http://www.phonegap.com/start#ios-x4

For this post, I’m using XCode 4 as the IDE for iOS, so I linked to the specific directions for that platform. I’m also going to target iOS 4.x and above, using the PhoneGap Media Capture API to access the camera.

After running the PhoneGap installer, open XCode 4 and start a new project. You should see the PhoneGap template as one of your options:

Click Next on the Choose your template dialog

I’m going to use DrupalApp as my Product Name, and com.jefflinwood as my company identifier.

Click Next.

Now put your new project into a folder of your choice (for instance, under your home directory’s Documents), and let XCode 4 create a local git repository if it offers to.

Click Create

XCode 4 will do some processing, and then you should see your new DrupalApp project in Xcode.

Hit the Play button in the upper left hand corner of XCode to run your project in the iPhone Simulator. PhoneGap will load, but it won’t have any content to display. The first time you run your project, PhoneGap will actually create a www folder you can drag into XCode to get started. Here’s what the iPhone Simulator will look like:

Now that we have our XCode project set up, and we’ve run our project, we need to add the www folder to our project. With the current version of PhoneGap, this needs to be done manually – the template isn’t set up to import the www folder into the XCode project. Luckily, this is pretty easy.

Open up the DrupalApp project folder in Finder. It should look like this:

Drag the www folder onto your XCode DrupalApp Project, right between DrupalApp and PhoneGap.framework. This is so XCode will bundle the contents of the www folder with your app when it packages the app to run on the iPhone Simulator or on an iPhone, iPod Touch, or iPad.

Xcode will prompt you to create folder references for any added folders – choose this option if the Create groups option is selected.

Click Finish.

Now run the project again, (stopping the currently running DrupalApp if it is still running) and PhoneGap should let you know it’s working:

The next step is to download and add jQuery Mobile (from http://jquerymobile.com/download/) to your XCode project. We will bundle the CSS, Javascript, and images into our app to minimize download times.

In the finder, create a new folder under the www folder named css, and copy the jquery.mobile-1.0b1.min.css file into the css folder. Create another folder under the www folder named javascripts, and copy the jquery.mobile-1.0b1.min.js file into the javascripts folder. You’ll also need to download jQuery 1.6.2 from http://code.jquery.com/jquery-1.6.2.min.js into your javascripts folder.

Now open the index.html in your www folder so we can add the CSS file and the two Javascript files.

In the index.html element, add

<link rel="stylesheet" href="css/jquery.mobile-1.0b1.min.css"/>

and

<script type="text/javascript" charset="utf-8" src="javascripts/jquery-1.6.2.min.js"></script>

<script type="text/javascript" charset="utf-8" src="javascripts/jquery.mobile-1.0b1.min.js"></script>

Now that we have jQuery Mobile added to our project, go ahead and run the project – you shouldn’t see any difference in the output from the iPhone Simulator. This is because jQuery Mobile expects your content to be in <div> tags that correspond to individual pages in your mobile application. This is a little different from what you might be used to, where each page in a web application is a separate HTML file. To minimize download time, and to enable transition effects between pages, it’s best to set up as many of your pages in one HTML file as possible. You can link to other HTML files, of course, but you may lose your transitions between the two – and mobile users strart to expect to see those transitions.

I mentioned that jQuery Mobile wants its content structured into <div> tags instead of individual HTML pages. With those <div> tags, you’ll need to tell jQuery Mobile how your content is structured with the new HTML5 data-* attributes. For instance, <div data-role=”page”>…</div> wraps a mobile page, while <div data-role=”header”>…</div> is the header and <div data-role=”content”>…</div> is the content of the page.

We’re going to replace the contents of the <body> tag of our index.html with some content structured for jQuery Mobile:

<body>  	  
  <div data-role="page" id="home">         
    <div data-role="header">             
      <h1>Home</h1>                       
    </div>         
    <div data-role="content">
      Welcome to the jQuery Mobile Demo App for Drupal!         
    </div>     
  </div> 
</body>

Run the app in the iPhone Simulator:

In the next post, I’m going to show you how to use PhoneGap’s cross-platform features to take photos with your smartphone’s camera.

Categories
Drupal Planet iPhone Development

Building a simple iPad Application with Drupal 7, Part 1

At DrupalCamp Colorado 2011, I created a birds-of-a-feather session on “Going Mobile with Drupal”. There were quite a few of us there, with all kinds of experience – we talked about using jQuery Mobile with Drupal and about connecting iPhone apps to Drupal using the Services module, REST, and either JSON or plist XML. Lots of interest in building RESTful web services with Drupal to support mobile apps.

Drupal 7 makes an ideal back-end for mobile apps, because it already has everything you need for content authoring and permissions built-in. There isn’t any reason to write a lot of server-side code to add a forum or groups or blogs to your mobile app. Another advantage is the large Drupal ecosystem of consultancies, developers, books, training, and conferences that you can turn to for help.

Tablet Puppy Ipad App

The night before the birds-of-a-feather, I built an iPad app to show the Drupal IOS SDK in use with an almost out-of-the-box Drupal 7 site. Here’s the github repo for my iPad demo app for Drupal – I’m not going to submit it to the App Store 🙂

Configuring Drupal to be the back end for Mobile

Right out of the box, Drupal 7 isn’t going to work as a back-end for mobile apps. You will need to install Services 3 to make it possible for Drupal to act as a REST server for its content. You’ll also need to set up an endpoint URL for your REST service, and tell Drupal which resources to expose at that endpoint. This is all much easier in Drupal 7/Services 3 than it was in Drupal 6/Services 2 – if you are using Drupal 6, see my article on Using Drupal 6 with the REST Server.

Drupal Services Modules for REST Server

The first step is to install the modules you’ll need for Services 3:

Services 7.x-3.0-rc3 – requires the ctools 7.x module

To make Services work with the Drupal iOS SDK for iPhone app development, you’ll also need:

Rest Server PLIST 7.x-1.0 – enable rest_server and rest_server_plist

If you’re also planning to retrieve views from your mobile app (and that’s most of the power here) you’ll need to install the Views module and the Services_views module. Services_views exposes Views as a resource to Services

Views 7.x-3.0-beta3 – enable Views and Views UI

Services_views 7.x-1.x-dev – enable Services_views

To keep this focused, I’m not including directions on how to install modules here – read the Drupal.org handbook on installing modules.

In the next post, I’ll cover how to configure Services so you can use Drupal as the server side of a mobile solution!

Categories
Touchpad

Updates to EveryMarathon for WebOS – TouchPad

[NOTE: 7/5/2011 – changed enyo.hitch() in source code to enyo.bind(), which is documented. They’re the same function in Enyo 0.1]

Now that I actually have a device to run the app on, I’ve found a few things I’d needed to fix with version 1.0.0 of EveryMarathon:

1) The scrollers for individual states weren’t moving back into place when I refreshed their contents – you have to do that manually with the $.scroller.scrollIntoView() method

2) In Portrait mode, the app looked terrible – what I thought would fix that would be to set a minimum width on the details pane, but that doesn’t seem to work. I need to go back to this, but for now, I hard-coded the app to only work in “right” landscape orientation – what’s annoying about this is that if you are holding it upside down but in landscape, the app will launch upside down….this is on the must fix list.

3) The month displayed in the details view was off by one – totally my bug, nothing to do with WebOS – easy fix.

4) I got my map working, with clickable infoboxes! This was way more trouble than I thought it would be, because I was overthinking things. Microsoft supplies the Bing Maps V7 AJAX map control with a Pushpin object and an Infobox object, but the two aren’t connected. I took advantage of the fact that everything is a Javascript object, so I can just define new properties on my Pushpin objects and Infobox objects to maintain the state I need to. Obviously I’d prefer it if Microsoft provided the solution, or if HP had a nice wrapper for this for Enyo, but until then, I’ll use my custom Enyo MapView kind. Here’s the source code:

enyo.kind({
  name: "EveryMarathon.MapView",
  kind: "VFlexBox",
  events: {
      onBack: "",
      onPinOnclick: "",
      onInfoboxOnclick: "",
      onSelectItem: ""

  },
  published: {
      url: "",
      visibleInfobox: "",
      selectedItemIndex: ""
  },
  components: [
      {kind: "Map", name:"mapContainer", zoom: 6, flex:1, credentials: BING_API_CREDENTIALS},
	  {kind: "Toolbar", components: [
		{kind: enyo.GrabButton},
		{flex: 1},				  
			{caption: "Done with Map", onclick: "dismiss"},
			{flex: 1},				  

	  ]}	      
  ],
  showRacesOnMap: function(races) {
	
	this.$.mapContainer.clearAll();
	
  	var inOptions = null;
  	var locations = [];
  	for (var i = 0; i< races.length; i++)
  	{
  		var latitude = races[i].latitude;
  		var longitude = races[i].longitude;
		var location = new Microsoft.Maps.Location(latitude, longitude);
		locations.push(location)
		var pushpin = new Microsoft.Maps.Pushpin(location, inOptions);
		var infobox = new Microsoft.Maps.Infobox(location, {htmlContent: "
" + races[i].title + "
",visible:false, offset:new Microsoft.Maps.Point(0,35)}); infobox.raceIndex = i; pushpin.infobox = infobox; this.$.mapContainer.map.entities.push(infobox); this.$.mapContainer.map.entities.push(pushpin); Microsoft.Maps.Events.addHandler(pushpin, 'click', enyo.bind(this, "doPinOnclick")); Microsoft.Maps.Events.addHandler(infobox, 'click', enyo.bind(this, "doInfoboxOnclick")); } var bestview = Microsoft.Maps.LocationRect.fromLocations(locations); this.$.mapContainer.map.setView({bounds:bestview }); this.$.mapContainer.setZoom(6); }, dismiss: function() { this.doBack(); }, doPinOnclick: function(inSender) { var pin = inSender.target; if (pin) { var infobox = pin.infobox; if (infobox) { if (this.getVisibleInfobox() != "") { this.getVisibleInfobox().setOptions({visible:false}); } this.setVisibleInfobox(infobox); infobox.setOptions({visible:true}); } } }, doInfoboxOnclick: function(insSender) { this.setSelectedItemIndex(insSender.target.raceIndex); this.doSelectItem(this); } });
Categories
Touchpad

EveryMarathon for TouchPad out today!

I got a WebOS version of my EveryMarathon iPhone app out the door for the HP Touchpad launch today – I’m releasing it as a free app for the Touchpad because I don’t have a tablet yet to test it on, so if it’s got a few quirks, I don’t want any disappointed customers 🙂

One of the things I wasn’t sure about with EveryMarathon would be what the UI patterns would be for the TouchPad – for instance, how are most people going to integrate web views into their app? This isn’t necessarily a technical problem – HP does have a nice Design Guidelines document as part of the WebOS 3.0 SDK, but just like iOS, I’d expect certain patterns to emerge as standards.

One of the fun things about the new HP Touchpad tablet is that it’s got the best web development framework I’ve ever worked with – Enyo!

I’d love to build all my web apps with Enyo on the front-end and a thin back-end like Sinatra for Ruby after working with Enyo for just a little while.

If you’ve been doing any kind of Javascript development for the web, remember when you first saw jQuery, Prototype, Dojo, or any similar framework and saw how easy that made some things with JavaScript? Enyo makes building the whole front-end that easy – no more HTML or CSS box model. Instead you get to use layout managers to write your app – similar to Android or Swing, but not exactly the same. There may be other Javascript frameworks that let you program in a similar way, but I haven’t used them – let me know if there are any!

I found that WebOS 3 is missing a lot of community support compared to iOS development – with iOS, usually if I have the problem, other people have had the problem too, so it’s easy to start tracking down a solution through GitHub, StackOverflow, or just plain Google. With WebOS, the number of developers is a lot smaller, and the only place to discuss programming for the Touchpad has been a private forum on the Palm Developer web site.

On the positive side for WebOS development – getting JSON from a web service is unbelievably easy, the UI library seems to be well thought-out, and there are no weird code-signing/certificate issues like iOS – that was a breath of fresh air! Testing an app on the emulator is as easy as running palm-package on the directory with your app in it, and then running palm-install <name-of-app>, and boom, app is running.