|
|
Google's Weather API in Flash These are my notes that I collected as I tried to make google weather API work in Flash. Here is a running version: Flash app using google weather feed Google weather API The base URL http://www.google.com/ig/api? The weather parameter Multiple ways to set the weather parameter (Google's Weather XML API) 1) US postal code (i.e. google.com/ig/api?weather=90120) 2) Canadian postal code (i.e. google.com/ig/api?weather=V9B1A7) 3) City, state (US or canadian) (i.e. google.com/ig/api?weather=toronto,ON) 4) City, country (Sometimes there are multiple cities with the same name in one country, in that case it does not work, i.e. Victoria,BC works but Victoria,Canada does not) The hl parameter (language parameter) The default setting, if not defined, is hl=en You can test it with French, hl=fr (i.e. google.com/ig/api?weather=V9B1A7&hl=fr) The language code will NOT change the XML tags, only the data in those tags The list of legal language codes (ISO 639-1) is in the reference section below Google's weather information is provided by Weather Underground (wunderground.com) Flash actionscript Created a bare bones hard coded flash program to retrieve the file. This works locally. var city:String = "Toronto,ON"; // hard coded the city while testing var xml:XML = new XML(); var urlloader:URLLoader = new URLLoader(); urlloader.load( new URLRequest("http://www.google.com/ig/api?weather="+city) ); urlloader.addEventListener("complete", xmlComplete); function xmlComplete(e:Event):void { xml = XML(e.target.data); trace(xml); var tf:TextField = new TextField(); tf.text = "Temp: "+city+" \n"+xml.weather.current_conditions.temp_c.@data+" Celsius"; addChild(tf); } Policy files The reason this did not work when I posted it up on the website was because of Adobe's Flash Security sandbox. They implemented restrictions in manipulating data retrieved from other sites. You can still load images, swf's or other objects into your flash file as long as you are NOT manipulating them, as soon as you wish to massage the data you would run into security restrictions. What is the security model they use? Policy files, crossdomain.xml Flash tries to retrieve this file using the default name crossdomain.xml and assuming it's located in the root directory of a web site. In this case it's http://google.com/crossdomain.xml <?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <site-control permitted-cross-domain-policies="by-content-type" /> </cross-domain-policy> As we can see we are NOT granted permission to access this content. What we would be looking for was something along the lines of allow-access-from domain="*". (see references below for specification pf crossdomain policy file) Proxy (first run) To get around this you could request specific inclusion of your domain. Or they create access for all (allow-access-from domain="*"). Since the above requests are unlikely to be granted the best option left is to create a simple proxy. All you need to do is read the xml document and display it again. My preference is PHP and Snoopy (see references below for download page for Snoopy) header("Content-type: text/xml"); $weather = $_GET["weather"]; include "Snoopy.class.php"; $snoopy = new Snoopy; if ($snoopy->fetch("http://www.google.com/ig/api?weather=".$weather)) { echo $snoopy->results; } else echo "Snoopy: error while fetching document: ".$snoopy->error."\n"; And you would change your URLRequest in flash to ... new URLRequest("http://weatherdoll.com/xml_proxy.php?weather="+city); Proxy (second run) After reviewing the code (always a good practice), I realize I don't snoopy since all I am doing is loading the file and displaying it through the proxy. The second proxy uses readfile (you could also use fopen, fpassthru, fclose) In addition we tightened up the headers, for example if the server zips up the file before sending it, we set the compression to off to prevent errors on certain browsers. We also set the cache to false, (we should actually set the cache to 1 hour) And we also store a local copy of the XML file that we get, so we don't bombard google with multiple requests of the same data in the span of a few minutes. ini_set("zlib.output_compression", "Off"); header("Content-type: text/xml"); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: no-cache'); $weather = $_GET["weather"]; $url = "http://www.google.com/ig/api?weather=".urlencode($weather); $file = "_weather_".str_replace( array(","," "), "_", $weather).".xml"; ob_clean(); flush(); // check if a local file less than an hour old is already on file if (!file_exists($file) || filemtime($file) < time() - 3600 || filesize($file) == 0) { ob_start(); readfile($url); $google_xml = ob_get_clean(); echo $google_xml; // save local copy of xml $handle = fopen($file,w); fwrite($handle, $google_xml); fclose($handle); } else { // load local copy of xml ob_start(); readfile($file); $google_xml = ob_get_clean(); echo $google_xml; } Concerns still linger on using this API since Google does not publicly endorse it. Summary I put up all my reference material on this page to help others (and myself) whenever I need to update the project. Like all good projects, you get to where you are going through the help of others. Note to self: getting the degree symbol on the mac, shift + option + 8 References: PHP caching using ouput buffering PHP Snoopy download Crossdomain Policy file specification Poking holes in policy files Google Weather API by emerick.org Android Weather API Yahoo Weather API XML / RSS Weather.com sigup for free XML feed List of ISO 639-1 codes |
||
|