.:[Double Click To][Close]:.
Get Paid To Promote, Get Paid To Popup, Get Paid Display Banner




Showing posts with label mobile. Show all posts
Showing posts with label mobile. Show all posts

Friday, October 15, 2010

Jason Grigsby’s DOs and DON’Ts of Mobile Strategy

Last week Jason Grigsby visited Google as part of our Web Exponents speaker series which highlights innovations in web technology. Jason is a tech leader in mobile web development. In addition to spotting trends in the mobile space, Jason is at the front lines building mobile apps at Cloud Four. His humorous and informative talk includes technology recommendations and insightful examples from the world of mobile. Check out the video of the talk below. You can also download the slides.

Jason’s mobile strategy counterexamples include Chanel (they have an iPhone app but their website is unusable on the iPhone) and the difficulties of finding an Apple Store on the iPhone. His DOs and DON’Ts are:

DOs:

  1. Know your customers and what devices they use.
  2. Look beyond native apps to mobile web, SMS & MMS.
  3. Apps for your most loyal customers add value.
  4. Consistent experience across devices and offline.
  5. Understand mobile context.

DON’Ts:

  1. Don’t assume customers have downloaded your app.
  2. Don’t rely on Flash.
  3. Don’t make finding store locations & hours difficult.
  4. Simple to use does not mean dumb.
  5. Don’t forget that the ‘U’ in URL stands for Universal. (He goes on to point out that it really stands for Uniform.)

These all ring true for anyone with experience building for mobile. The hard part is figuring out the right solution for providing the right experience for desktop as well as diverse mobile devices. Jason gives a glimpse into the key features of a solution:

  • integrated image resizing
  • video conversion and resizing
  • separation of content from markup so content can be used in native apps
  • prioritization of content based on context
  • full-featured APIs

The challenge in my opinion is in the steps of breaking out content from markup and determining which content is appropriate for a given device. We need frameworks that better support these ideas, but there’s still a lot of heavy design work on the developer’s shoulders. Jason points to NPR as an example of a large site that has successfully implemented this architecture. Check out Jason’s talk to find out more, and also check out some of the other videos in the Web Exponents playlist.

Wednesday, June 10, 2009

Gmail for Mobile HTML5 Series: Suggestions for Better Performance

On April 7th, Google launched a new version of Gmail for mobile for iPhone and Android-powered devices. We shared the behind-the-scenes story through this blog and decided to share more of our learnings in a brief series of follow-up blog posts. This week, I'll talk about a few small things you can do to improve performance of your HTML5-based applications. Our focus here will be on performance bottlenecks related to the database and AppCache.

Optimizing Database Performance

There are hundreds of books written about optimizing SQL and database performance, so I won't bother to get into these details, but instead focus on things which are of particular interest for mobile HTML5 apps.

Problem: Creating and deleting tables is slow! It can take upwards of 200 ms to create or delete a table. This means a simple database schema with 10 tables can easily take 2-4 seconds (or more!) just to delete and recreate the tables. Since this often needs to be done at startup time, this really hurts your launch time.

Solution: Smart versioning and backwards compatible schema changes (whenever possible). A simple way of doing this is to have a VERSION table with a single row that includes the version number (e.g., 1.0). For backwards-compatible version changes, just update the number after the decimal (e.g., 1.1) and apply any updates to the schema. For changes that aren't backwards compatible, update the number before the decimal (e.g., 2.0) at which point you can drop all the tables and recreate them all. With a reasonable schema design to begin with, it should be very rare that a schema change is not backwards compatible and even if this happens every month or so, users should get to use your application 20, 30 even 100 times before they hit this startup delay again. If your schema changes very infrequently, a simple 1, 2, 3 versioning scheme will probably work fine; just make sure to only recreate the database when the version changes!

Problem: Queries are slow! Queries are faster than creates and updates, but they can still take 100ms-150ms to execute. It's not uncommon for traditional applications to execute dozens or even hundreds of queries at startup – on mobile this is not an option.

Solution: Defer and/or combine queries. Any queries that can be deferred from startup (or at any other significant point in the application) should be deferred until the data is absolutely needed. Adding 2-3 more queries on a user-driven operation can turn an action from appearing instantaneous to feeling unresponsive. Any queries that are performed at startup should be optimized to require as few hits to the database as possible. For example, if you're storing data about books and magazines, you could use the following two queries to get all the authors along with the number of books and magazine articles they've writen:

SELECT Author, COUNT(*) as NumArticles
FROM Magazines
GROUP BY Author
ORDER BY NumArticles;

SELECT Author, COUNT(*) as NumBooks
FROM Books
GROUP BY Author
ORDER BY NumBooks;


This will work fine, but the additional query will generally cost you about 100-200 ms over a different (albeit less pretty) query like:

SELECT Author, NumPublications, PubType
FROM (
SELECT Author, COUNT(*) as NumPublications, 'Magazine' as PubType, 0 as SortIndex
FROM Magazines
GROUP BY Author
UNION
SELECT Author, COUNT(*) as NumPublications, 'Book' as PubType, 1 as SortIndex
FROM Books
GROUP BY Author
)
ORDER BY SortIndex, NumPublications;

This will return all the entries we want, with the magazine entries first in increasing order of number of articles, followed by the book entries, in increasing order of the number of books. This is a toy example and there are clearly other ways of improving this, such as merging the Magazines and Books tables, but this type of scenario shows up all the time. There's always a trade-off between simplicity and speed when dealing with databases, but in the case of HTML5 on mobile, this trade-off is even more important.

Problem: Multiple updates is slow!

Solution: Use Triggers whenever possible. When the result of a database update requires updating other rows in the database, try to do it via SQL triggers. For example, let's say you have a table called Books listing all the books you own and another called Authors storing the names of all the authors of books you own. If you give a book away, you'll want to remove it from the Books table. However, if this was the only book you owned by that author, you would also want to remove the author from the Authors table. This can be done with two UPDATE statements, but a "better" way is to write a trigger that automatically deletes the author from the Authors table when the last book by this author is removed. This will execute faster and because triggers happen asynchronously in the background, it will have less of an impact on the UI than executing two statements. Here's an example of a simple trigger for this case:

CREATE TRIGGER IF NOT EXISTS RemoveAuthor
AFTER DELETE ON Books
BEGIN
DELETE FROM Authors
WHERE Author NOT IN
(SELECT Author
FROM Books);
END;
We'll get into more detail on triggers and how to use them in another performance post to come.

Optimizing AppCache Performance

Problem: Logging in is slow!

Solution: Avoid redirects to the login page. App-Cache is great because it can launch the application without needing to hit the network, which makes it much faster and allows you to launch offline. One problem you might encounter though, is that the application will launch and then you'll need to hit the network to get some data for the current user. At this point you'll have to check that the user is authenticated and it might turn out that they're not (e.g., their cookies might have expired or have been deleted). One option is to redirect the user to a login page somewhere, allow him to authenticate and then redirect him back to the application. Regardless of whether or not the login page is listed in the manifest, when it redirects back to your application, the entire application will reload. A nicer approach is for the application itself to display an authentication interface which sends the credentials and does the authentication seamlessly in the background. This will avoid any additional reloads of the application and makes everything feel faster and better integrated.

Problem: AppCache reloading causes my app to be slow!

Solution: List as few URLs in the manifest as possible. In a series of posts on code.google.com, we talked about the HTML5 AppCache manifest file. An important aspect of the manifest file is that when the version gets updated, all the URLs listed in the file are fetched again. This happens in the background while the user is using the application, but opening all these network connections and transferring all that data can cause the application to slow down considerably during this process. Try to setup your application so that all the resources can be fetched from as few URLs as possible to speed up the manifest download and minimize this effect. Of course you could also just never update your manifest version, but what's the point of having rapid development if you never make any changes?


That's a brief intro to some performance considerations when developing HTML5 applications. These are all issues that we ran into ourselves and have either fixed or are in the process of fixing in our application. I hope this helps you to avoid some of the issues we ran into and makes your application blazing fast!

We plan to write several more performance related posts in the future, but for now stay tuned for next post where we'll discuss the cache pattern for building offline capable web applications.



Previous posts from Gmail for Mobile HTML5 Series
HTML5 and Webkit pave the way for mobile web applications
Using AppCache to launch offline - Part 1
Using AppCache to launch offline - Part 2
Using AppCache to launch offline - Part 3
A Common API for Web Storage

Thursday, June 4, 2009

Android: Now beaming I/O videos and presentations to the world

Google I/O was one of Android's biggest events of the year, with a Mobile track that focused primarily on all things Android, and 22 developers showcasing some of their great Android applications at the Google I/O developer sandbox.

For those of you who missed I/O or could not make all the Android sessions, we're excited to release session videos and presentations from the Mobile track online and free to developers worldwide.

At this year's I/O, we wanted to help developers further optimize their applications for the Android platform by creating better user experiences. Romain Guy explored techniques for making Android apps faster and more responsive using the UI toolkit. Chris Nesladek discussed the use of interaction design patterns in the Android system framework to create an optimal user experience. Since mobile application development is inextricably tied to battery performance, Jeff Sharkey provided an insightful look at the impact of different application features and functionalities on battery life. Taking the mobile experience further, T.V. Raman and Charles Chen discussed building applications that are optimized for eyes-busy environments, taking advantage of the Text-to-Speech library, as well as new UI innovations that allow a user to interface with the device without needing to actually look at the screen.

We also offered a few sessions on building compelling and fun apps that take advantage of the Android media framework and 2D and 3D graphic libraries. Chris Pruett discussed the gaming engine that he built and used as a case study to explain best practices and common pitfalls in building graphics-intensive applications. David Sparks lifted the hood on the infrastructure by diving into Android's multimedia capabilities and expanding on how to use them to write secure and battery-efficient media code.

We also had several sessions that meditate on challenges, best practices, and philosophies for writing apps for Android. Dan Morrill demonstrated multiple techniques for developing apps for Android in different scenarios, to help developers make the right decisions on the right techniques for writing their apps. Joe Onorato talked to developers about leveraging Android's ability to support multiple hardware configurations to make their applications run on a wide variety of devices without the overhead of building a custom version for each. Justin Mattson talked about advanced usage of Android debugging tools in his session and presented real-world examples in which these tools were used at Google.

Lastly, Robert Kroeger returns from the frontlines of launching Gmail Mobile Web for iPhone and Android's offline capabilities and shares the team's experiences in using a portable write-through caching layer running on either HTML 5 or Gears databases to build offline-capable web applications.

We hope these session videos and presentations are helpful to all Android developers out there. Don't forget to check out our newly announced Android Developer Challenge 2 - we look forward to seeing your passion, creativity, and coding prowess come together in the great apps you submit in this next challenge!

Thursday, May 21, 2009

Gmail for Mobile HTML5 Series: A Common API for Web Storage

On April 7th, Google launched a new version of Gmail for mobile for iPhone and Android-powered devices. We shared the behind-the-scenes story through this blog and decided to share more of our learnings in a brief series of follow up blog posts. Over the last few weeks we've talked about how to use the AppCache functionality of HTML5 to launch an application offline. We discussed the impact that AppCache can have on your mobile web applications, as you enable users to launch your app faster in the face of flaky or slow internet connections. This week, I'll talk about how we're using both HTML5 Structured Storage and the Google Gears Database to make devices tolerate flaky network connections.



Although these technologies allow web applications to cache user data on the mobile device and perform data modifications locally, HTML5 Structured Storage uses an asynchronous model, where the Google Gears Database uses a synchronous model. This difference makes it difficult to develop an application on top of both platforms. We dealt with this problem by creating the Web Storage Portability Layer (WSPL) for Gmail. Coming soon under a liberal open source license to code.google.com/p/webstorageportabilitylayer, WSPL provides a common API that supports an identical asynchronous programming model for both platforms by using a worker thread in Gears. Let's take a look!

The WSPL consists of a collection of classes that provide asynchronous transactional access to both Gears and HTML5 databases. It can be used to execute nested statements within callbacks, create statement templates, and optionally control the synchronous/asynchronous modes of the Gears Database Wrapper. There are five basic classes.

google.wspl.Statement - A parametrizable SQL statement class
google.wspl.Transaction - Used to execute one or more Statements with ACID properties
google.wspl.ResultSet - Arrays of JavaScript hash objects, where the hash key is the table column name
google.wspl.Database - A connection to the backing database, also provides transaction support
google.wspl.DatabaseFactory - Creates the appropriate HTML5 or Gears database implementation

Let's take a look at how we can use this API to perform a simple query, starting with the creation of a Database. Note that you'll need to provide a URL to the worker file hosted from your domain.

var database = google.wspl.DatabaseFactory.createDatabase('db name', 'http://yourdomain/dbworker.js');

You can then execute SQL statements without worrying about the specifics of HTML5 and Gears. Refer to the recent blog posts about AppCache to find steps you can follow to see your database contents using sqlite3.
var statement = google.wspl.Statement('SELECT col from test_table;');
database.createTransaction(function(tx) {
tx.executeAll([statement], {onSuccess: function(tx, resultSet) {
// Statement succeeded.

for(; resultSet.isValidRow(); resultSet.next()) {
window.console.info(resultSet.getRow()['col']);
}
}, onFailure: function(error) {
// Statement failed.
}});
}, {onSuccess: function() {
// After transaction commits, before any other starts.
}, onFailure: function(error) {
// After transaction fails, before any other starts.
}});
I've found that using the Gears database asynchronously will nicely split up the JavaScript execution, allowing event handlers and other code to execute between the callbacks. This can improve the responsiveness of your application if you're using long transactions. You can also use SQL triggers to avoid the read-modify-write pattern that causes "ping ponging" between threads -- either the main thread and Gears worker or the main thread and the HTML5 SQL thread.

That's all I'll show you for now, but you can look for more details about the Web Storage Portability Layer at Google I/O, May 27-28 in San Francisco where we'll be presenting a session on the architecture of a generic application using HTML5. We'll also be available at the Developer Sandbox and are looking forward to meeting you in person. Stay tuned for the next post where we'll talk about improving the performance of HTML5-based web applications.

Using the Google Static Maps API and HTTP Geocoder to power Lonely Planet's mobile travel guide

This post is part of the Who's @ Google I/O, a series of blog posts that give a closer look at developers who'll be speaking or demoing at Google I/O. Today's post is a guest post written by Ken Hoetmer of Lonely Planet.

Lonely Planet has been using Google Geo APIs since 2006 - you can currently find them in use on destination profiles at lonelyplanet.com , in our trip planner application , in our hotel and hostel booking engine , on lonelyplanet.tv , and in our mobile site, m.lonelyplanet.com . I could talk for hours about any of these sites, but in preparation for Google I/O and my talk at the Maps APIs and Mobile session, I'll spend this post discussing our use of the Google Static Maps API and the HTTP geocoding service on m.lonelyplanet.com.

Our mobile site's primary feature is highlighting points of interest (POIs) around you, as selected by Lonely Planet. The site is browser based and targeted at a baseline of devices. This accessibility is great for on the road, but because of this choice, we can't obtain precise user locations via a location API. Instead, we've asked our users to self-select their location by entering it into a free form text field when they first arrive at the site. This location is then posted to our server, geocoded on the back end by forwarding the text to the Google HTTP geocoding API, and then used to either set the user's location or return a list of options for disambiguation.

Knowing the user's position, we then forward the position and a radius in kilometers to our Content API's POI proximity method, returning a list of points within range, in order of proximity. Once we have the POIs, we need to present them on a map, relative to the user's location. This is where the Google Static Maps API comes in. We can't rely on the availability of Flash, JavaScript, and Ajax, but the Static Maps API enables us to serve a JPEG map by simply providing our list of POI geocodes, a few bits about labeling markers, and a height / width (which we calculate per device by querying screen sizes from WURFL) as query parameters to a URL. Below the map we put a few links for switching the map between (road)map, satellite, hybrid, and terrain base maps.

That gives us a basic map, but what if the user wants to look a little farther to the north or east? To enable this, we augmented the map with a lightweight navigation bar (north, south, east, west, zoom in, zoom out), with links to new static maps that represent a pan or zoom action. Here's how we generated the links:

Let's say our page has a static map of width w pixels, height h pixels, centered at (lat,lng) and zoom level z.
$map_link = "http://maps.google.com/staticmap?key={$key}&size={$w}x{$h}&center={$lat},{$lng}&zoom={$z}";
Then, we can generate north, south, east, and west links as follows (this example assumes the existence of a mercator projection class with standard xToLng, yToLat, latToY, lngToX routines):
// a mercator object
$mercator = new mercator();

// we'll pan 1/2 the map height / width in each go

// y pixel coordinate of center lat
$y = $mercator->latToY($lat);

// subtract (north) or add (south) half the height, then turn
back into a latitude
$north = $mercator->yToLat($y - $h/2, $z);
$south = $mercator->yToLat($y + $h/2, $z);


// x pixel coordinate of center lng
$x = $mercator->lngToX($lng);

// subtract (west) or add (east) half the width, then turn back into a longitude
$east = $mercator->xToLng($x + $w/2, $z);
$west = $mercator->xToLng($x - $w/2, $z);
So that our north, south, east, west links are:
$north = "http://maps.google.com/staticmap?key={$key}&size={$w}x{$h}&center={$north},{$lng}&zoom={$z}";
$south = "http://maps.google.com/staticmap?key={$key}&size={$w}x{$h}&center={$south},{$lng}&zoom={$z}";
$east = "http://maps.google.com/staticmap?key={$key}&size={$w}x{$h}&center={$lat},{$east}&zoom={$z}";
$west = "http://maps.google.com/staticmap?key={$key}&size={$w}x{$h}&center={$lat},{$west}&zoom={$z}";
Of course if you're serving a page knowing only a list of points and their geocodes, then you don't have a zoom level value for calculating the map links. Thankfully, mercator projection implementations often offer a 'getBoundsZoomLevel(bounds)' function, which serves this purpose (create your bounds by finding the minimum and maximum latitudes and longitudes of your list of geocodes). If your implementation doesn't provide this function, it's not complicated to write, but I'll leave that to the reader (hint: find difference in x and y values at various zoom levels and compare these to your map width and height).

As mentioned earlier, I'll be joining Susannah Raub and Aaron Jacobs to delve deeper into maps and mobile devices at Google I/O. In addition, Matthew Cashmore (Lonely Planet Ecosystems Manager) and I will be meeting developers and demoing our apps in the Developer Sandbox on Thursday, May 28. We'd love to meet you and we'll be easy to find - simply follow the noise to the jovial Welshman.

Thursday, April 30, 2009

PPK: The Open Web Goes Mobile

Last week I was privileged to host PPK (Peter-Paul Koch) for a Google tech talk entitled "The Open Web Goes Mobile". Most developers building web apps have benefited from PPK's browser compatibility research hosted on his well known site quirksmode.org. Now, fortunately, PPK is turning his attention to the world of mobile web devices. To no one's surprise, browser compatibility on mobile devices is even worse than it is on the desktop. Or as PPK puts it on his opening slide "Hell is other browsers". Check out his slides or watch the video here.



PPK starts by identifying the four main problems with getting web sites to work well on mobile clients: small memory, small display, flaky browsers, and flaky connections. Memory is an area for more research, especially benchmarking. PPK offers some suggestions for dealing with a small display, including using media queries in CSS (@media all and (max-width: 300px) {}) and offsetWidth in JavaScript.

Mobile browsers themselves are flaky when it comes to advanced CSS and JavaScript. But PPK finds that even basic stuff, such as font-style: italic, has to be verified. As a result of his testing, PPK categorizes mobile browsers into three levels of compatibility:
  • top level: Android WebKit, Safari, Opera Mobile
  • mid level: S60 WebKit, Blackberry, Opera Mini
  • bottom level: NetFront, IE Mobile
Obviously, this is not an exhaustive list of mobile clients. PPK also mentions OpenWeb, Nokia S40, Palm Blazer, Iris, Bolt, Skyfire, Obigo, Fennec, and Teashark. This is the challenge in developing for the mobile web - there are a large number of clients and they exhibit diverse compatibility behavior.

When it comes to flaky connections, PPK points out that your connection speed is affected by the activity of the people around you. It's unlikely that this is going to change any time soon, so it's important to reduce the size of your downloads as much as possible. The problem is that caching on mobile devices isn't always reliable.

The impact of flaky connections can be mitigated by saving your core files on the mobile device. W3C Widgets offers a solution for achieving this. They're local applications written in HTML, CSS, and JavaScript that run inside the mobile browser. Ajax is used to download what's required: data. An advantage of using W3C Widgets is that, if the specification gets wide adoption, widgets will run across multiple mobile devices, and companies won't have to build a custom application for each target device. Right now, W3C Widgets work in Vodafone and Nokia S60 phones and Opera/T-Mobile phones for Windows Mobile, so evangelism to other mobile devices is needed. But the possibility of sharing applications across phones is compelling, for both the user experience as well as reduced development costs for mobile app developers.

Thursday, July 10, 2008

QR Codes now available on the Google Chart API



You can easily render 2D bar codes, known as QR Codes, with the Google Chart API, along with pie charts and bar graphs. If you haven't seen a QR Code before, you are looking at one on the right hand side (To see more, do an image search for "QR Code".)

QR Codes are a popular type of two-dimensional barcode. You can encode URLs, contact information, etc. into a black-and-white image like the one on the right. A QR-Code-enabled device can later scan the image and read back the original text. Learn more about QR Codes from Google Print Ads. If you don't have a reader Google also offers a QR Code decoder library: Zebra Crossing (ZXing).

This is how you can creating these with the Google Chart API:

Simply, there is a new chart type, qr, with attributes to tell the service what to produce:
cht=qr
chl=<text>
choe=<output>
<text> is text for the QR code. This must be url-encoded in UTF8. Note the space between hello and world is written as %20 in the following example.
<output> optionally specifies how the text is encoded into bytes in the QR Code. If this is not specified the default of UTF-8 is used. Available options are: Shift_JIS, UTF-8, or ISO-8859-1.

For the details, please read the full documentation.

Wednesday, April 2, 2008

Google Developer Podcast: Picasa Web and Google Gears for Mobile





I had the pleasure of taking a trip back to my home land of England to meet up with the team behind the Google Gears for Mobile product.

As someone who loves Web development, it is an exciting proposition to be able to use the Web platform to be able to develop applications on the mobile.

This release enables you to use the Gears 0.3 APIs on Windows Mobile devices. With this new version, not only do you have access to the Database, LocalServer, and WorkerPool APIs, but you can also create desktop shortcuts. Considering the disconnected nature and latency issues inherent to the mobile networks, these APIs allow you to deliver more responsive applications that can hide some of the problems.

Today, we saw the release of a new mobile version of Picasa Web Albums that uses these features. I got to sit down with Joe Walnes, tech lead of the mobile Picasa team. Joe and his team built both the Gears-enabled version of Picasa for the phone as well as the iPhone version that allows you to sit on the Tube and still flip through your family photos.

Joe tells us about his experience building the Gears application.



I have also put together an audio podcast consisting of interviews with not only Joe, but other members of the Gears team.

First, I talk to Charles Wiles, the Product Manager of the Google Gears for Mobile team. He gives us a high level view of the project in general, and this launch in particular. We also discuss the native abilities of Gears on the mobile, widget platforms, and future Gears developments.

Second, we hear from two engineers on the project, Dave Burke and Andrei Popescu. They go into detail on the platform, how you architect mobile Web applications, how you develop and debug applications, new APIs such as the Location API, and how Android fits in to the picture.

Finally, we hear again from Joe Walnes.

I am really excited about the prospect of building rich mobile applications using Web based technology.

You can download the episode directly, or subscribe to the show (click here for iTunes one-click subscribe).

Monday, March 3, 2008

Power up your mobile web applications



It's a mobile zoo out there. If you've ever tried coding up a mobile client application, you've probably noticed that the huge variety of mobile operating systems makes it tough to build rich applications that work on every device. We face the same challenges. But what if developers could deploy applications directly to mobile browsers rather than develop native applications? That would simplify the development process, as developers could use the same coding skills to create mobile applications. Even better, if these mobile web applications could work offline, users would be able to use them when they are disconnected from the network.

Developers, look no further. Today we're announcing the launch of Google Gears for mobile, a mobile browser extension for creating rich web applications for mobile devices. The first version is now available for Internet Explorer Mobile on Windows Mobile 5 and 6. It's a fully functional port of Google Gears v0.2 that can be used to develop offline capability into your mobile web applications. You can also create slick and responsive applications by hiding latency issues through controlled caching of data and storage of information between sessions. We're also working to bring Google Gears for mobile to Android and other mobile platforms with capable web browsers.

There are already a handful of Windows Mobile web apps that use Google Gears for mobile, such as the personal finance service Buxfer and online applications provider Zoho.  Read more about these applications and how they use Google Gears for mobile on the Google mobile blog.

For more on the vision for Google Gears for mobile and its origins, watch this video.

Friday, August 17, 2007

Dreamweaver Tools for Google



We keep making more services available to mobile users; in addition to Google Mobile Search, you will find that Google News, Google Maps, and more have had a mobile presence for a while. So, we want to make it easy for developers to link to and use these services in mobile web sites. I'm therefore pleased to note that we've collaborated with WebAssist to add new mobile tools to their Dreamweaver Tools for Google plugin. The newly-released version 2.0 of this free tool includes, among other things, one-click access to embedding Google Maps, News, Mobile Search, and Send-to-phone in a page.