Archive for June, 2010

Using mobile-specific HTML, CSS, and JavaScript (Mobile web part 5)

Tuesday, June 29th, 2010

Mobile-specific HTML

Use the viewport tag to properly fit the content to the screen:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

Use the tel scheme for telephone numbers, allowing users to initiate calls by clicking:

<a href="tel:18005555555">Call us at 1-800-555-5555</a>

Or use the sms scheme to initiate an SMS message:

<a href="sms:18005555555">
<a href="sms:18005555555,18005555556">          <!-- multiple recipients -->
<a href="sms:18005555555?body=Text+goes+here">  <!-- predefined message body -->

You also have access to several Apple-specific tags to use in your web application (iPhone and iPod Touch):

// iOS 1.1.3+: this is the icon that's used when the user adds your app to the home screen
<link rel="apple-touch-icon" href="/custom_icon.png"/>

// iOS 3+: full-screen startup splash screen image
<link rel="apple-touch-startup-image" href="/startup.png">

// enable full-screen mode
<meta name="apple-mobile-web-app-capable" content="yes" />

// controls the appearance of the status bar in full-screen mode
<meta name="apple-mobile-web-app-status-bar-style" content="black" />

And also some handy attributes to turn off annoying autocorrect features (works on iPhone, but anything else?):

<input autocorrect="off" autocomplete="off" autocapitalize="off">

Mobile-specific CSS

Media queries enable you to target specific features (screen width, orientation, resolution) within CSS itself. You can use them two ways: 1) inline in a CSS stylesheet or 2) as the “media” attribute in the link tag, which targets an external stylesheet. The following is an example of inline CSS that’s applied only when the device is in portrait mode:

@media all and (orientation: portrait) {
	body { }
	div { }
}

Here’s the same media query using the other method, which points to an external stylesheet (not recommended, as it creates another network request):

<link rel="stylesheet" media="all and (orientation: portrait)" href="portrait.css" />

Here’s a few examples:

// target mobile devices
@media only screen and (max-device-width: 480px) {
	body { max-width: 100%; }
}

// recent Webkit-specific media query to target the iPhone 4's high-resolution Retina display
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
	// CSS goes here
}

// should technically achieve a similar result to the above query,
// targeting based on screen resolution (the iPhone 4 has 326 ppi/dpi)
@media only screen and (min-resolution: 300dpi) {
	// CSS goes here
}

Read more: Media queries (Mozilla Developer Center)

(edit: removed section on body[orient='portrait'], which requires JavaScript and is in error. See Part 6: Dealing with device orientation for more details.)

Mobile-specific JavaScript

window.devicePixelRatio: determine screen resolution (analogue to the media query). (iPhone 4 has the value 2, while Nexus One has the value 1.5).

window.navigator.onLine (boolean): not strictly mobile, but helpful for apps to determine if they’re being run offline

window.navigator.standalone (boolean, iOS 2.1+): determine if it’s running in full-screen mode (Apple only?)

touch events (iOS, Android 2.2+): touchstart, touchmove, touchend, touchcancel

gesture events (Apple only, iOS 2+): gesturestart, gesturechange, gesturend give access to predefined gestures (rotation, scale, position)

window.orientation and orientationchange event: triggered every 90 degrees of rotation (portrait and landscape modes)

MozOrientation (Fennec/Firefox Mobile, Firefox 3.5+): also not strictly mobile. Gives access to the device’s accelerometer (x-y-z orientation data), updated periodically. Works on Android phones (I tested on the Nexus One), Windows Mobile, etc. On the desktop this works with laptops such as Thinkpads and MacBooks.

-near future: camera/microphone access in Android 2.3 (announced at Google I/O 2010) through the Capture API

If you’re developing for a BlackBerry Widget, you have access to proprietary information through the blackberry object (which gives access to useful information such as blackberry.network [returns values such as CDMA and Wi-Fi] and blackberry.system).

You also have the option to use PhoneGap, which augments JavaScript and gives you access to more phone features that native apps would have access to.

Use a mobile-optimized JavaScript library

Because smartphone browsers are standards-based, the aim of a JavaScript library on mobile is less towards API normalization and more towards providing an actual UI framework, usually to emulate the feel of native apps (and to provide easier workarounds to lack of access to position:fixed). We’ve seen a few libraries released that emulate the iPhone UI, and in the future we might see libraries emulating the Android UI, as well as entirely new UIs.

There’s also a bit to be said about simply loading full desktop JavaScript libraries into mobile clients. In my opinion this doesn’t particularly make sense, especially in a world where latency and bandwidth are so much more of a concern. It doesn’t make sense to force the user wait longer and download code that’s ultimately useless to them (hacks for desktop browsers such as IE 6, etc).

Here’s a few of the mobile libraries now available:
-Sencha Touch
-baseJS
-XUI
-jQTouch: jQuery-style mobile library that emulates the look of the iPhone UI
-iUI: the first JavaScript library to be released, emulates the look of the iPhone UI. Originally coded by Joe Hewitt.
-PastryKit: Apple proprietary non-public JavaScript library with no available documentation

Take advantage of new stuff!

While not specific to mobile, there’s a lot of new stuff in general that you can use. If you limit yourself to the top smartphones (iPhone, Android, and maybe webOS), compared to the desktop you immediately have access to an even wider array of new stuff, especially many Webkit proprietary features, since most of these top smartphones have browsers based on Webkit.

-HTML: new tags (HTML5 (I’m sure you’ve heard of it by now…))
-CSS: 2d transforms, 3d transforms, animation, border radius, custom fonts with @font-face, etc.
-JavaScript: strict mode, constants, block scope, Date.now(), etc.

Related posts

This post is part of a series on the mobile web. You can read the other parts of the series here:
Part 1: The viewport metatag
Part 2: The mobile developer’s toolkit
Part 3: Designing buttons that don’t suck
Part 4: On designing a mobile webpage

iPhone 4 SunSpider test results (22% faster than iPhone 3GS)

Friday, June 25th, 2010
============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                 10669.4ms +/- 1.0%
--------------------------------------------

  3d:                   1471.5ms +/- 2.1%
    cube:                428.7ms +/- 2.6%
    morph:               584.3ms +/- 4.7%
    raytrace:            458.5ms +/- 0.6%

  access:               1476.7ms +/- 1.3%
    binary-trees:        151.6ms +/- 1.3%
    fannkuch:            664.0ms +/- 0.1%
    nbody:               397.9ms +/- 2.1%
    nsieve:              263.2ms +/- 6.3%

  bitops:                947.2ms +/- 2.1%
    3bit-bits-in-byte:   195.7ms +/- 2.0%
    bits-in-byte:        206.1ms +/- 1.0%
    bitwise-and:         179.7ms +/- 1.1%
    nsieve-bits:         365.7ms +/- 3.9%

  controlflow:           169.5ms +/- 8.0%
    recursive:           169.5ms +/- 8.0%

  crypto:                668.7ms +/- 1.0%
    aes:                 307.0ms +/- 1.4%
    md5:                 181.1ms +/- 3.1%
    sha1:                180.6ms +/- 1.0%

  date:                  838.4ms +/- 4.6%
    format-tofte:        420.9ms +/- 7.4%
    format-xparb:        417.5ms +/- 2.8%

  math:                 1161.9ms +/- 1.0%
    cordic:              424.9ms +/- 0.5%
    partial-sums:        385.1ms +/- 0.3%
    spectral-norm:       351.9ms +/- 2.9%

  regexp:               1479.3ms +/- 0.1%
    dna:                1479.3ms +/- 0.1%

  string:               2456.2ms +/- 0.9%
    base64:              347.6ms +/- 3.1%
    fasta:               408.1ms +/- 6.7%
    tagcloud:            447.7ms +/- 0.6%
    unpack-code:         797.8ms +/- 0.4%
    validate-input:      455.0ms +/- 0.4%

Summary

Thanks to my coworker for lending me his phone for a few minutes (he waited in line for 9 hours yesterday when it first went on sale!).

This is quite an improvement over the iPhone 3GS running iOS4, which ran the SunSpider test in 13787ms. The iPhone 4 ran the same test in 10669ms, which makes it ~22% faster head-to-head.

Processors

The iPhone 3GS has a Samsung S5PC100 ARM Cortex-A8[5] 833 MHz (underclocked to 600 MHz), while the iPhone 4 has an Apple A4 1GHz (likely underclocked to an unknown speed).

JavaScript SunSpider: HTC Evo versus HTC Incredible versus Nexus One

Thursday, June 10th, 2010

Result table

Test Evo (2.1) Incredible (2.1) Nexus One (2.2)
Total 16167ms 15237ms 5452ms
3D 2014ms 1835ms 946ms
Access 2126ms 1892ms 463ms
Bitops 1519ms 1591ms 360ms
Controlflow 243ms 206ms 20ms
Crypto 1033ms 1003ms 344ms
Date 1849ms 1896ms 639ms
Math 1684ms 1419ms 602ms
Regexp 1779ms 1673ms 155ms
String 3920ms 3722ms 1923ms

Thoughts

The Incredible is just slightly faster than the Evo, to the point where it’s probably negligible or within a margin of error. Both of these phones run on Android 2.1 with HTC’s Sense UI modifications, and represent the latest and greatest in Android phones available on the market today. Both run on the same 1GHz Snapdragon processor (QSD8650). The Nexus One is a bit older, and runs with an older version of the Snapdragon processor (QSD8250), however it still runs at 1GHz just like the other two phones.

As you can see the Nexus One blows away all the competition because it’s running Android 2.2 Froyo. These results were quite a shock to me and are quite impressive. These results even blow away Apple’s new iOS 4 running on my iPhone 3GS, which clocked in at a total time of 13787ms compared to the Nexus One’s startling 5452ms.

Testing methodology

Test: SunSpider 0.9.1

Devices: HTC Evo (Android 2.1), HTC Incredible (Android 2.1), HTC Nexus One (Android 2.2)

The SunSpider test was run five times on each phone. The phone was completely turned off and on before each test. The most extreme values of the five tests were thrown out, and the resulting four tests were averaged (sometimes from three tests when the values were very close together).

Raw results:

SunSpider HTC Evo results (5 tests)

SunSpider HTC Incredible results (5 tests)

SunSpider HTC Nexus One results (5 tests)

Related links

JavaScript SunSpider test: iOS 3.1.3 versus iOS 4 GM

JavaScript SunSpider test: iOS 3.1.3 versus iOS 4 GM

Thursday, June 10th, 2010

Result table

Test iOS 3.1.3 (3GS) iOS 4 GM (3GS) % change
Total 15396ms 13787ms -10.5%
3D 2411ms 1917ms -20.5%
Access 1884ms 1893ms +0.5%
Bitops 1044ms 1239ms +18.7%
Controlflow 143ms 221ms +54.5%
Crypto 982ms 850ms -13.4%
Date 1355ms 1065ms -21.4%
Math 2053ms 1511ms -26.4%
Regexp 1616ms 1916ms +18.6%
String 3908ms 3175ms -18.8%

Thoughts

After running these SunSpider tests, it looks like overall there’s significant speed gains between iOS 3.1.3 and iOS 4 GM. However, it’s concerning from these tests there were some things that actually ran slower on iOS 4. This either represents a real speed loss between the versions, a margin of error, or some flaw or inconsistency while testing. Or maybe I possibly have some wrong setting on my phone? Any input would be appreciated.

Testing methodology

Test: SunSpider 0.9.1

Device: iPhone 3GS

The test was run five separate times on the same phone for each version of the OS. The phone was completely turned off and on before each test.

The most extreme values of the five tests were thrown out, and the resulting four tests were averaged (sometimes from three tests when the values were very close together). I’m no statistics expert, so if you’d like to work it out for yourself, here are my raw test results:

SunSpider iOS 3.1.3 results (5 tests)

SunSpider iOS 4 results (5 tests)

Related links

Speed Test: iPhone 3GS Even Faster than Apple Claims

How to install obsolete Android Virtual Devices (AVDs)

Wednesday, June 9th, 2010

Apparently it’s no longer possible to easily download Android versions 2.0 and 2.0.1 from the AVD Manager. I noticed this problem when I got a new machine and had to install everything from scratch. In the future I suspect even more AVDs will be made obsolete, so this solution also applies to them.

Why would you want to install obsolete AVDs? In my case it’s a matter of research: I simply want to see the progress of features being added to its browser, and track those changes over time.

Step 1: Manually download and inspect repository.xml

When updating from “Available Packages” there’s a little one-line error saying “Some packages were found but are not compatible updates.”

Ok, so let’s check out the XML for ourselves to see if we can find anything. So point your browser to https://dl-ssl.google.com/android/repository/repository.xml (to see the XML, right click to view the page source if you’re using a Webkit-based browser).

Search for the AVD version you want. In this case we want 2.0 and 2.0.1, so a simple search find the relevant blocks of code. And we also find the XML tag that’s the cause of our troubles, which prevents us from easily getting the AVDs:

<sdk:obsolete />

Step 2: Get the AVDs!

At this point you could do two things, either save repository.xml to your computer and remove these “obsolete” tags (then add the XML to your AVD Manager by clicking “Add Add-on Site…”), or simply find the path to the AVD and download it manually.

The second option is to simply manually download the paths, which are easy to find in the XML and are listed here for your convenience:
Android 2.0 AVD (Linux)
Android 2.0 AVD (Mac OSX)
Android 2.0 AVD (Windows)

Android 2.0.1 AVD (Linux)
Android 2.0.1 AVD (Mac OSX)
Android 2.0.1 AVD (Windows)

Step 3: Install!

Create directories under your Android SDK installation’s “platforms” folder. In this case we have 2.0 (API level 5) and 2.0.1 (API level 6), so I created these folders: android-5 and android-6. Now just unzip the contents into these folders.

Start up the AVD Manager and click on “Installed Packages”. If you don’t see your new (obsolete) packages you just installed, hit the Refresh button and you should see them.

Now you can create new AVDs with these obsolete packages!

Mobile First: Luke Wroblewski on mobile design

Saturday, June 5th, 2010

Click to play Luke Wroblewski: Mobile First

In episode 6 of The Big Web Show, Luke Wroblewski gives his “Mobile First” talk, explaining his philosophy for designing for mobile, the challenges, and a look at the road ahead. Luke explains that because of the limitations on mobile, developers are forced to really optimize the user experience for mobile. Often times this mobile experience turns out much better than on the desktop, where the “gluttony of resources” results in distracting and excessive webpages.