Skip to Navigation | Skip to Content



Archive for the 'iPhone' Category

Supporting Custom URLs in PhoneGap-iPhone apps pt 2 of 2 | March 7th, 2011

My previous post explained how to get custom launch params so you can respond to different calling conditions, including a call from another app, or Mobile Safari. There is also a very good chance that your app may already be running, so what then?

Handle Open URL

With multitasking, this actually becomes quite likely, because users no longer kill your app, they simply move away from it. Your app is essentially suspended, so you should probably handle the non-launch option as well.

The ApplicationDelegate class defines a method just for this use, all you have to do is override it and hook it into your webView.

Copy the following to your AppDelegate.m and add the function to your js code:

Also, note that you can name your javascript function whatever you want, as long it is the same name that your AppDelegate passes into the webView. I chose to simply keep things clear and called the function "handleOpenURL(urlStr)", but it could just as easily be "appController.handleUrl(urlStr)". As in the previous post, this url is UrlEncoded, so you may need to decode it, depending on your needs.

One cool thing about the handleOpenURL function is that it is easily testable. You can put a link right inside your html to make the call using your protocol and it will be processed by the OS and passed right back to your app. This may not seem useful, but I can foresee situations where it might make sense, like passing info from a ChildBrowser control back to your main app, or completely decoupling your view from your app-controller. … Any other ideas?

I welcome your comments, questions, and suggestions. buy my single => :)

Posted in iPhone, Objective-C, PhoneGap, XCode | 6 Comments » | Add to Delicious | Digg It

Supporting Custom URLs in PhoneGap-iPhone apps pt 1 of 2 | March 7th, 2011

I recently reworked some of the launchOption / handleOpenURL code in PhoneGap iPhone.
The commit is here.

You can expect these changes to be included in the next official release 0.9.5 later this month, however these are not considered PhoneGap functions, so I thought I would explain how this all works and save anyone having to wait for the next release.

The custom url schemes are an iOS thing, so it did not make sense to me to include them in the core of PhoneGap, but they are definitely useful, so they needed to be included somewhere.

When you create a new PhoneGap project in XCode, the template spits out a new XCode project containing a subclass of PhoneGapAppDelegate where you can choose to implement whatever you want without worrying about breaking the base classes. I chose to modify the template to make it easier for users to use custom urls. You can also add this functionality to an existing project quite simply.

For a very good description of how to set up the custom url, check out this post.

Once you have set up the plist and added your custom url, you can turn your attention to your app delegate files. First we will look at launchOptions.

Launch Options

In your MYPROJECT_AppDelegate.h add a variable to store the invoked url like this.

Now turning your attention to the implementation file, MYPROJECT_AppDelegate.m, you will need to respond to the didFinishLaunchingWithOptions: message. If you were previously handling applicationDidFinishLaunching: you can safely remove this call, and handle things in the withOptions variant. This is the way the baseClass ( PhoneGapDelegate.m/.h ) functions now, but the template was not updated to reflect the change.

Your didFinishLaunchingWithOptions should look like this:

The above stores the launchOptions url as a string for later use.
Next we will pass it into the UIWebView where our JS app loads, we have to wait for the page to load to do this, but we add it before we call super, so the value will be available when the deviceready event fires in our page.

Now moving to the html/js

Awesome, we have received the launchOptions in our Javascript code, and we can continue on and do something relevant with them.

To test this, open Mobile Safari on your device or simulator ( after having installed your app, and making sure it is not running in the background. )

In Mobile Safari’s address bar enter your customUrl scheme and verify that it launches your app and you see an alert with the freaking launchOptions.

Next up : handleOpenURL

Posted in iPhone, PhoneGap, XCode | 4 Comments » | Add to Delicious | Digg It

ekiben | February 1st, 2011

I posted a simple view swapper demo for webkit mobile using XUI + GloveBox.

Want a quick layout for your PhoneGap app? Go and get the code:

https://github.com/purplecabbage/ekiben

Posted in iPhone, PhoneGap, XCode | Comments Off | Add to Delicious | Digg It

PhoneGap and the Apple developer license agreement. | April 14th, 2010

Yesterday I made a quick update to a previous blog post. I will go into a little more depth here as some folks mis-understood that this was a new topic because it was part of the older post.

Recent changes to the Apple iPhone SDK developer license agreement have been a hot topic over the last week. There has been much speculation over how far reaching the 3.3.1 clause of the agreement is, not to mention the business strategy behind it. I will not join that conversation, but I will speak of what I have learned with regards to the impact on PhoneGap (iPhone/iPad).

Through email discussions with Apple, I specifically asked what, if any, impact did this have on present/future applications submitted to the App store that were built using PhoneGap. In no uncertain terms, my contacts at Apple have assured me that “PhoneGap is not in violation of the 3.3.1 clause of the license agreement.”

How this affects other tool-chains like Appcelerator, Flash CS5, Corona, MonoTouch, … I have absolutely no idea. All I can say is that PhoneGap is okay.

I will post updated information if I receive it, I have done a few other things to test the waters. Yesterday I submitted my iPhone PhoneGap Tutorial application to the App Store, I will post info here when/if it is approved ( although it may be rejecting for offering insufficient functionality, as it is a tutorial ).



The tutorial source code is available here: http://bit.ly/Jestitute

Posted in iPhone, Objective-C, PhoneGap | 12 Comments » | Add to Delicious | Digg It

iPhoneGap Plugs | April 1st, 2010

Okay, in your phonegap application in XCode, ( Without EVER having to touch the PhoneGapLib )

1) right click the plugins folder and select Add/NewFile/ObjectiveCClass
2) Call your new class : TestPlug
3) Paste the following code into the .m + .h files:

In your header file :


#import <Foundation/Foundation.h>
#import "PhoneGapCommand.h"
@interface TestPlug : PhoneGapCommand {
}
- (void)addThemUp:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
@end

… and in the .m file


#import "TestPlug.h"
@implementation TestPlug
- (void)addThemUp:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
{
NSUInteger argc = [arguments count];
int total = 0;
for(int n = 0; n < argc; n++)
{
total += [[ arguments objectAtIndex:n] intValue];
}
NSString* retStr = [ NSString stringWithFormat:@"alert(\"%d\");",total];
[ webView stringByEvaluatingJavaScriptFromString:retStr ];
}
@end

4) In your JS code, somewhere after deviceready, call your command like this.


PhoneGap.exec("TestPlug.addThemUp",1,2,3,4);

Build and run!

Note the structure of the PhoneGap.exec call
1) a command name : TestPlug
2) a method name : addThemUp
3) a variable length list of arguments

Next time, I'll get into passing objects via the 'options' object.

If you have a compelling plug-in you want to share, you can fork my repo for plugins and send me a pull request :

http://github.com/purplecabbage/PhoneGap-Plugins

If your plugin makes sense on multiple devices, and it is implemented with standards in mind, it may end up in PhoneGapLib.

Posted in iPhone, Objective-C, PhoneGap, XCode | 12 Comments » | Add to Delicious | Digg It

PhoneGApp Store Approval | November 20th, 2009

I just received word from Apple that :

a) Apple has given PhoneGap a technical analysis , and PhoneGap does not violate the Terms & Conditions of the App Store.
b) Apple will review PhoneGap applications based on their own merits and not on their use of PhoneGap.

What this means:

There was still some apprehension within the community as to whether or not using PhoneGap would lead to a possible rejection from the iPhone App Store, we definitely have a green light to PhoneGap. This means we can all get back to doing what we love best, building fast, easy mobile apps with JavaScript+HTML+CSS while still taking advantage of the core features in the iPhone, Android, Symbian-WRT and Blackberry devices.

Happy coding!

[ Update:: April 13, 2010 ]

I have received word from Apple that the above is STILL true! If you were concerned by the recent changes to Apple’s iPhone developer agreement, this has ZERO impact on PhoneGap!

Apps built with PhoneGap will continue to be reviewed based on their own merits and NOT dismissed/rejected because they use PhoneGap.

So enough with the crazy speculative rumour mill. Let’s get back to making apps with HTML+CSS+JavaScript.

PhoneGap ftw!

Posted in iPhone, PhoneGap | 52 Comments » | Add to Delicious | Digg It

PhoneGap for iPhone exposed | November 4th, 2009

Earlier this week I attended the Apple iPhone Developers Tech Talks in Seattle. The event was free and by invite only and you had to have an app in the app store, or be very close to having one to be invited. This meant that the content of the talk could be technical without losing anyone, and we had an informative deep dive into technical things like OpenGLES, Device Audio, and UIKit functionality best practices. I learned a lot over the day about what to avoid, and how to optimize iPhone applications.

As a PhoneGap developer, user and evangelist, I made it my duty to talk to everyone I could about PhoneGap and guage the level of interest from the Apple dev community. After speaking to a couple people at Apple, it became clear that they are very much aware of PhoneGap, but have very little understanding of what it does or how it works. I have decided to dig into these questions to make sure that there are no misconceptions about the project. PhoneGap is entirely opensource, but not everyone has the time read a bunch of code. ( if only …)

PhoneGap Under the Hood

PhoneGap aims to provide a consistent interface to device functionality across multiple platforms to enable rapid application development via well known technologies, namely HTML / JavaScript / CSS.

At it’s core, PhoneGap is nothing more than a spec listing JavaScript accessible calls that an application programmer can use to make applications. Each device ( iPhone, Android, BlackBerry, … ) has it’s own specific implementation, and the tools and processes you use to build, test and deploy/submit your app will vary for each. So again, PhoneGap is a JavaScript accessible API implemented on multiple devices.

All implementations render their user interface using HTML and CSS in a web browser control of some sort. Most modern devices support rich rendering features ( HTML5, CSS3 ) so it is a relatively simple to design, and layout your application with your existing skills, tools, and even existing graphical assets.

The typical PhoneGap application is a packaged version of a webpage/website that runs from the phone. What this means is that all html/css/js files are bundled into the application and run from the file:// protocol. A common misunderstanding is that the application is loaded over the web, which is definitely NOT the way we recommend users write their apps, and (to my knowledge) NOT the way typical PhoneGap based applications are architected. In this case you would be writing a mobile-optimized website and will likely not be approved for app store submission.

In some cases PhoneGap applications have a server component that delivers data via an HTTP API, usually json or xml using XMLHttpRequest. PhoneGap itself does not provide any server communication functionality, so app developers must roll their own server access layer.

So How Does PhoneGap Work?

Every device implementation has it’s own specific means of accessing device functionality, so I will be focusing on the iPhone implementation. The iPhone implementation is probably the most misunderstood, and most used, plus it is where I have spent the most time.

How does JavaScript call Objective-C code?

In order for a developer’s application code (js) to access device functionality they will include the file phonegap.js in their (html) application. The file phonegap.js defines the entire API and contains the key functionality for device communication. All device functionality that PhoneGap exposes is done via the navigator object in JavaScript.
For example, to access Accelerometer functionality, you would call JavaScript methods on the navigator.accelerometer object.

In order for phonegap.js to send a request to the device it simply sets the location of the page based on the following protocol:

gap://CommandHandler.method?arg1Name=arg1Value&arg2Name=arg2Value

gap://
This is a phonegap request and not a request to load a new page.
CommandHandler
This is a subset of device functionality that contains methods. An example would be Accelerometer or Notification
method
Each CommandHandler defines it’s own methods
arguments
a URL encoded list of arguments that are passed to the method ( varies based on the method ) Note that phonegap.js will URLEncode the parameters for you.

and here’s a concrete example:

gap://Notification.alert?message=Hello&title=My%20App%Name&buttonLabel=OK

This will call the Notification objects alert method, passing it a message,title, and the text to display on the button.

So, upon receiving the command, Objective-C code will take over and perfom the requested command.

So How Does Objective-C call my JS code?

Some calls from JS require a callback mechanism to let the JS code know when the command has completed, if it succeeded and so on. The majority of this is handled for the developer in phonegap.js. Objective-C code will call stringByEvaluatingJavascriptFromString() to pass data back into the js code. The mechanism for each command is defined in phonegap.js, so the developer will simply pass a function callback that phonegap.js will call once the command has returned data.

Here is a concrete example:

In my application, I want to access the accelerometer, so I define a callback function :


function onAccelData(accelObj)
{
// accelObj has properties x,y,z that you can use to see the
// current state of the accelerometer so presumably you
// would do something with that data here.
}
function onAccelFail()
{
// accelermeter functionality is not available,
// do something else ...
}

In order recieve the data, I need to make a call to the js Accelerometer object :

navigator.accelerometer.watchAcceleration(onAccelData, onAccelFail);

Now, your callback is going to be called repeatedly with updated accelerometer data, that your application can use as you see fit. Since this is not intended to be a blog post about how to use the accelerometer, I will stop there. You should know also that the accelerometer supports stopping as well, and you can also specify how often you want to be updated.

So that, in a nutshell, is the entire iPhone implementation of PhoneGap. Note, there is no voodoo or magic sauce, just 2 data transfer mechanisms and a protocol between them.
Hopefully this will give better perspective and help anyone who has to answer the question: What is PhoneGap?

Remember that PhoneGap is completely opensource so if you want a deeper look under the hood, you are completely free to do so.

If you want to use PhoneGap, you can git it here :http://github.com/phonegap/phonegap
To read more, have a look at www.phonegap.com

I invite your questions, comments, criticism, accolades, beers!

Posted in iPhone, Objective-C, PhoneGap | 10 Comments » | Add to Delicious | Digg It

Running jQTouch in PhoneGap | October 28th, 2009

Update: the content of this post is no longer relevant. The gap has been filled.

Last week there were some discussions about the poor performance of jQTouch in PhoneGap apps, so I dug into it.

First I had to verify that this was something we were doing in PhoneGap and not a difference between Mobile-Safari and the UIWebView control which we use in PhoneGap.

I created a PhoneGap project and dropped the jQTouch sample code into the www folder, and immediately noticed the sluggish performance.

I then created a bare bones iPhone Windowed application with a UIWebView in it, and dropped the same www folder contents into the project root.

NSURL *appURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"www"]];
NSURLRequest *appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
[webView loadRequest:appReq];

After running both builds on the device it was obvious that the PhoneGap version was in fact sluggish compared to the bare-bones version. Verified!

So, thinking about what could be causing this, I looked into the PhoneGapDelegate code, and immediately saw the Accelerometer handling code the a potential culprit. The PhoneGapDelegate class asks the sharedAccelerometer for updates 40x per second. According to the Applei Phone dev docs, this interval is “Suitable for games and other applications that use the accelerometers for real-time user input.” Which is cool, but probably way more than this application needs considering it isn’t even being used. Every time that the sharedAccelerometer calls back with an update, the javascript is written into the webView’s DOM. Commenting out the accelerometer code that sets up the interval indeed fixes the majority of the sluggishness. Verified! Pretty smooth, eh?

Okay, so commenting it out isn’t really a solution, so here is the plan:
I am working to re-implement the Accelerometer portion as a command, that can be used more elegantly. Javascript code inside the www folder should have the ability to set how frequently it wants be updated, and have the ability to start + stop monitoring the accelerometer, which should also remove the overhead.

Note:
If your application does not use the accelerometer, instead of commenting out the code like I did, you can simply set “EnableAcceleration” to false in PhoneGap.plist.

I will post an update here when I have checked in anything of significance.

Posted in iPhone, Objective-C, PhoneGap, Uncategorized, XCode | 10 Comments » | Add to Delicious | Digg It

PhoneGap Static lib for iPhone-XCode | October 27th, 2009

I recently spent some time evaluating the iPhone branch of PhoneGap and have made some changes that I think will make things easier to develop.

One of the key issues that I wanted to address was that PhoneGap existed as a repository and anyone that made an application with it would invariably have to mix their code in. In a very few cases it is possible to make a complete application using PhoneGap out of the box, but what if you need to add, remove or change something? As soon as you start messing with the core PhoneGap code, you are looking at huge merge issues when updates are pushed to the PhoneGap repo. Most likely you will just ignore any new commits, and your code will be stuck in time from the moment you changed it, or you will have to pick through the updates, and decide what is worth re-implementing in your own codebase.

My changes work as follows: You do not create a PhoneGap app anymore! You create an app that inherits from PhoneGap. This means your PhoneGap code can be in a git repo somewhere (github) while your application code can be in it’s own repo. If there are updates to the PhoneGap codebase then ( as long as the API has not changed ) you simply update PhoneGap and build your app.

In order to make these changes, I had to simplify some of the PhoneGap code. I removed the dependency on XIB files so the UIWebView is now created through code instead of automagically by XCode boilerplate code behind the scenes. The PhoneGap core code is now a static library that you link to and inherit from so there are some things you will have to do to create a new phonegap application. Also keep in mind that this is all subject to change as we are currently looking at ways of making this dead-simple.

You can git the code here: http://github.com/phonegap/phonegap/tree/plugins/iphone/

The new PhoneGap 12 step program

  1. In XCode create a new WindowBased iPhone Application.
  2. Select the project and add a reference to the PhoneGapLib project. ( The one you downloaded from git )
  3. Add a reference to all headers in the PhoneGapLib project ( these are needed so the compiler can know what you will be linking against, and what the base PhoneGapDelegate protocol looks like )
  4. Delete the MainWindow.XIB interface builder file that XCode created.
  5. In main.h add your app delegate class name to the UIApplicationMain call.
    ex.
    int retVal = UIApplicationMain(argc, argv, nil,@"MyAppDelegate");
  6. Change the interface of your application delegate to inherit from PhoneGapDelegate.
    ex.
    @interface MyAppDelegate : PhoneGapDelegate { }
  7. Select the build target in your project and add a dependency for PhoneGapLib.
  8. Add libPhoneGapLib.a to the ‘Link Binary with Library’ build step.
  9. Add the www folder to the ‘Copy Bundle Resources’ build step.
  10. Place phonegap.js in your www folder along with all your html/css/js application code.
    ( note: this is a little bit hack-y, and we are looking at ways of improving this step especially )
  11. Add project references to the following frameworks
    • AddressBook.framework
    • AddressBookUI.framework
    • AudioToolbox.framework
    • AVFoundation.framework
    • CFNetwork.framework
    • CoreGraphics.framework
    • CoreLocation.framework
    • Foundation.framework
    • MediaPlayer.framework
    • QuartzCode.framework
    • SystemConfiguration.framework
    • UIKit.framework
  12. Build and Go.

So What’s Next?

Recent PhoneGap discussions have led us to the conclusion that we need a plug-in architecture. It will be much easier to get people to contribute if they can focus on a key piece of functionality and not have to implement things throughout the codebase + it also gives a clearer separation of contributions and would allow for unit testing. This latest addition/change is a step towards a more plug-able architecture. Thanks also to Shazron for his help, support and suggestions along the way.

So get reviewin’ !!

Posted in iPhone, Objective-C, PhoneGap, XCode | 17 Comments » | Add to Delicious | Digg It


Search Posts

You are currently browsing the archives for the iPhone category.

Categories

Archives