I built this nifty little weather/clock app as a way of learning to work with API's and incorporates both the yahoo weather api and the flickr api. Now that it is in functioning order, I decided I would port it over to a playbook app via a Flash Builder 4.4 ActionScript Mobile project. I was able to get it installed on the playbook simulator just fine however when the app launched it showed a blank stage. After several hours of research I determined it was a runtime error.
After several more hours of research I found it was a security error when making a call out to the flickr api. The debugger reports the following error:
SecurityError: Error #3207: Application-sandbox content cannot access this feature. at flash.system::Security$/allowDomain() at global$init()[C:\Users\poorpaddy\Adobe Flash Builder 4.5\Scripts\flickrGrabber.as:43] at Weather/addGrabberEvents()[C:\Users\poorpaddy\Adobe Flash Builder 4.5\Weather\src\Weather.as:36] at Weather()[C:\Users\poorpaddy\Adobe Flash Builder 4.5\Weather\src\Weather.as:22]
I have tried several examples of
Security.allowDomain(FLICKR_URL);
Security.loadPolicyFile(CROSSDOMAIN_URL);
Without any luck. Here is my flickrGrabber class.
package {
import flash.display.Bitmap;
import flash.events.ErrorEvent;
import flash.events.EventDispatcher;
import flash.display.Loader;
import flash.events.Event;
import flash.events.ErrorEvent;
import flash.events.IOErrorEvent;
import com.adobe.webapis.flickr.events.FlickrResultEvent;
import com.adobe.webapis.flickr.*;
import flash.net.URLRequest;
import flash.system.Security;
import flash.system.LoaderContext;
//
public class flickrGrabber extends EventDispatcher {
private const FLICKR_URL:String = "flickr.com";
private const CROSSDOMAIN_URL:String = "http://api.flickr.com/crossdomain.xml";
private var imageLoader:Loader
//
private var fs:FlickrService;
private var activeUser:User;
private var photoList:PagedPhotoList
private var constrainWidth:Number;
private var constainHeight:Number;
private var photoPosition:Number = 0;
private var flickrSource:String;
private var searchType:String;
private var doUserSearch:Boolean;
private var userData:User;
private var activePhoto:Photo;
private var otherDataRecieved:Boolean;
public function flickrGrabber(parentWidth:Number, parentHeight:Number, api:String, secret:String, flickrSearchTerm:String, searchByUser:Boolean = false) {
constrainWidth = parentWidth;
constainHeight = parentHeight;
flickrSource = flickrSearchTerm
doUserSearch = searchByUser;
//
imageLoader = new Loader();
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageReady);
imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onImageError);
//
Security.allowDomain(FLICKR_URL);
Security.loadPolicyFile(CROSSDOMAIN_URL);
//
fs = new FlickrService(api);
//
fs.addEventListener(FlickrResultEvent.AUTH_GET_FROB, hGetFrob);
fs.addEventListener(FlickrResultEvent.PHOTOS_GET_SIZES, recievePhotoSize);
fs.addEventListener(FlickrResultEvent.PEOPLE_GET_INFO, recieveUserInfo);
fs.addEventListener(FlickrResultEvent.PEOPLE_FIND_BY_USERNAME, userSearchResults);
fs.addEventListener(FlickrResultEvent.PEOPLE_GET_PUBLIC_PHOTOS, recievePhotoList);
fs.addEventListener(FlickrResultEvent.PHOTOS_SEARCH , recievePhotoList);
//
fs.secret = secret;
//
fs.auth.getFrob();
}
private function hGetFrob(evt:FlickrResultEvent):void {
if (evt.success) {
if (doUserSearch){
fs.people.findByUsername(flickrSource);
}else {
fs.photos.search("", flickrSource, "any", "", null, null, null, null, -1, "", 100, 1, "interestingness-desc");
}
} else {
reportError("Error obtaining Frob from flickr");
}
}
private function userSearchResults(evt:FlickrResultEvent):void {
if (evt.success) {
activeUser = evt.data.user;
fs.people.getPublicPhotos(activeUser.nsid);
} else {
reportError("Count not find specified user name");
}
}
private function recievePhotoList(evt:FlickrResultEvent):void {
photoList = evt.data.photos as PagedPhotoList;
if (photoList.total > 0){
dispatchEvent(new Event("flickrConnectionReady", false));
} else {
reportError("No results recieved for user/search");
}
}
public function loadNextImage():void {
activePhoto = photoList.photos[photoPosition];
otherDataRecieved = false;
fs.people.getInfo(activePhoto.ownerId);
fs.photos.getSizes(activePhoto.id);
//
if (photoPosition+1 > photoList.photos.length-1) {
photoPosition = 0;
} else {
photoPosition ++
}
}
private function recieveUserInfo(evt:FlickrResultEvent):void {
userData = evt.data.user as User;
checkReadyStatus();
}
private function recievePhotoSize(evt:FlickrResultEvent):void {
if (evt.success){
var sizeArr:Array = evt.data.photoSizes;
var sizeObject:PhotoSize = sizeArr[i];
//Pull the photo that is closes开发者_Go百科t to the target size.
for (var i:int = 0; i < sizeArr.length; i++) {
sizeObject = sizeArr[i];
if (sizeObject.width > constrainWidth || sizeObject.height > constainHeight) {
break;
}
}
imageLoader.load(new URLRequest(sizeObject.source), new LoaderContext(true));
} else {
reportError("Photo sizes were not recieved");
}
}
private function checkReadyStatus():void {
if (otherDataRecieved) {
dispatchEvent(new Event("imageReady"));
} else {
otherDataRecieved = true;
}
}
//
private function onImageReady(evt:Event):void {
try {
var imageAlias:Bitmap = imageLoader.content as Bitmap;
} catch (e:Error) {
reportError("Returned image was not a proper bitmap: " + imageLoader.loaderInfo.url);
}
checkReadyStatus();
}
private function onImageError(evt:IOErrorEvent):void {
reportError("Error loading image: " + imageLoader.loaderInfo.url);
}
public function get image():Bitmap {
return imageLoader.content as Bitmap;
}
public function get imageTitle():String {
return activePhoto.title;
}
public function get imageAuthor():String {
return userData.fullname;
}
private function reportError(errorString:String):void {
dispatchEvent(new ErrorEvent("flickrGrabberError", false, false, errorString));
}
}
}
And here is my DocumentClass / Weather.as that references the flickerGRabber class.
package
{
import flash.display.MovieClip;
import flickrGrabber;
import flash.events.*;
public class Weather extends MovieClip
{
private var apiKey:String = "###removed for this posting###";
private var apiSecret:String = "###removed for this posting###";
public var flickrLocationName:String = "San Diego";
private var grabber:flickrGrabber;
private var la:LoadAnimation = new LoadAnimation;
public var backgroundClip:MovieClip;
private var clock:ClockObject = new ClockObject;
public var foreCast:WeatherObject = new WeatherObject;
private var settingsPanel:KeyboardObject = new KeyboardObject;
public function Weather()
{
addGrabberEvents();
clock.x = 492;
clock.y = 375;
addChild(clock);
foreCast.x = 27;
foreCast.y = 12;
addChild(foreCast);
settingsPanel.x = 38;
settingsPanel.y = 28;
addChild(settingsPanel);
}
public function addGrabberEvents():void
{
grabber = new flickrGrabber(1024,600,apiKey,apiSecret,flickrLocationName,false);
grabber.addEventListener("imageReady", onLoadedImage);
grabber.addEventListener("flickrGrabberError", onErrorImage);
grabber.addEventListener("flickrConnectionReady", onFlickrReady);
}
public function onFlickrReady(evt:Event):void
{
la.x = stage.stageWidth - (la.width + 20);
la.y = 20;
addChild(la);
grabber.loadNextImage();
}
public function onLoadedImage(evt:Event):void
{
backgroundClip = new MovieClip();
addChildAt(backgroundClip,0);
backgroundClip.addChild(grabber.image);
removeChild(la);
}
public function removeMe(e:MouseEvent):void
{
removeChild(backgroundClip);
addGrabberEvents();
settingsPanel.closeKeyboard(null);
settingsPanel.keyBoardPanel.statusMessage.msg_txt.text = ""
settingsPanel.keyBoardPanel.zipCodeEntry.zipCodeTxt.text = ""
}
public function onErrorImage(evt:ErrorEvent):void
{
trace("Report error: " + evt.text);
}
}
}
Your assistance would be very much appreciated I've been stuck for a couple days.
Argh. I spent many hours trying to refactor the code or look for something I was missing. It turns out all I have to do was remove the two lines.
Security.allowDomain(FLICKR_URL);
Security.loadPolicyFile(CROSSDOMAIN_URL);
精彩评论