Geolocation StatusEvent Never Fires - actionscript-3

I am developing an AIR for iOS app and I have just this one issue left on my list of bugs to fix. Basically, when a certain window is opened, the user is able to use their current position to search. I am using the Geolocation class for this and it works fine, except for the fact that StatusEvent.STATUS is not firing. The user is prompted to give permission to use their current location, as it should, but when they choose, my StatusEvent handler is never called.
if ( Geolocation.isSupported ) {
var geo:Geolocation = new Geolocation();
geo.addEventListener( StatusEvent.STATUS, this.geolocationStatusHandler );
this.geolocationStatusHandler();
}
protected function geolocationStatusHandler( e:StatusEvent = null ):void{
var geo:Geolocation = new Geolocation();
this.gpsButton.enabled = !geo.muted;
}
The only thing I can think of is that the alert window (which freezes app execution) is opened with new Geolocation(), before I add the event listener. But if that were the case, calling the handler manually wouldn't occur until after the user closed the Alert (it happens at the same time, roughly. A breakpoint there stops the app while the alert is open)
Is there a solution for this? I could always move the prompt to the very beginning of the app, but I personally prefer not being prompted until it is needed.
Details:
ActionScript Mobile project built with AIR 3.6 SDK
Tested on iPad 2, 3, and Mini, all running iOS 6.1.3
Tested in both release and debug modes

Listen for the GeolocationEvent.UPDATE event.
Also, it appears you're manually calling the handler immediately after the listener; then your handler is instantiating a new Geolocation instead of getting GeolocationEvent latitude and longitude.
Example implementation using Google Geocoding API from XpenseIt tutorial:
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.GeolocationEvent;
import flash.sensors.Geolocation;
import mx.rpc.AsyncResponder;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="locationUpdate", type="flash.events.Event")]
public class GeolocationUtil extends EventDispatcher
{
protected var geo:Geolocation;
public var updateCount:int;
protected var service:HTTPService = new HTTPService();
public var location:String;
public var longitude:Number;
public var latitude:Number;
public function GeolocationUtil()
{
service.url = "https://maps.googleapis.com/maps/api/geocode/xml";
}
public function geoCodeAddress(address: String):AsyncToken
{
return service.send({address: address, sensor: Geolocation.isSupported});
}
public function getLocation():void
{
if (Geolocation.isSupported)
{
geo = new Geolocation();
geo.setRequestedUpdateInterval(500);
updateCount = 0;
geo.addEventListener(GeolocationEvent.UPDATE, locationUpdateHandler);
}
}
protected function locationUpdateHandler(event:GeolocationEvent):void
{
// Throw away the first location event because it's almost always the last known location, not current location
updateCount++;
if (updateCount == 1) return;
if (event.horizontalAccuracy <= 150)
{
trace("lat:" + event.latitude + " long:" + event.longitude + " horizontalAccuracy:" + event.horizontalAccuracy);
geo.removeEventListener(GeolocationEvent.UPDATE, locationUpdateHandler);
geo = null;
}
longitude = event.longitude;
latitude = event.latitude;
var token:AsyncToken = service.send({latlng: latitude+","+longitude, sensor: Geolocation.isSupported});
token.addResponder(new AsyncResponder(
function(event:ResultEvent, token:AsyncToken):void
{
// Map the location to city and state from the response address component
location = event.result.GeocodeResponse.result[0].address_component[3].long_name + ', '+ event.result.GeocodeResponse.result[0].address_component[5].long_name;
dispatchEvent(new Event("locationUpdate"));
},
function (event:FaultEvent, token:AsyncToken):void
{
// fail silently
trace("Reverse geocoding error: " + event.fault.faultString);
}));
}
}
}

Related

How keep track of a walk in a google map in kotlin

I' m trying to keep track of a walk using google maps API in kotlin.
For now I get only the last known current location ( which actually is not the real current one)
This is mine MapsActivity code:
import android.content.pm.PackageManager
import android.location.Location
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.example.macc_project.R
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
class MapsActivity : AppCompatActivity(), OnMapReadyCallback, GoogleMap.OnMarkerClickListener {
override fun onMarkerClick(p0: Marker?): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
companion object {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
}
private lateinit var map: GoogleMap
private lateinit var lastLocation: Location
private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps_google)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
map.uiSettings.isZoomControlsEnabled = true
map.setOnMarkerClickListener(this)
setUpMap()
}
private fun setUpMap() {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
return
}
// 1
map.isMyLocationEnabled = true
// 2
fusedLocationClient.lastLocation.addOnSuccessListener(this) { location ->
// Got last known location. In some rare situations this can be null.
// 3
if (location != null) {
lastLocation = location
val currentLatLng = LatLng(location.latitude, location.longitude)
map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f))
}
}
}
}
How can I keep track of the entire walk that I do? For example painting a blue line that follows my walk, from an initial state to a final one

Flash kiosk touch app - if nothing happens go to homepage

I'm making a simple touchscreen app with flash. When users doesn't use it for 1 or 2 minutes I would like that the movie will automatically go back to the homepage link. How to reach that?
Is there any actionscript that if a mouse doesn't move for 2 minutes the movie will go to a link or it will rewind?
Thank you!
SOLVED:
AS2.0
// main timeline code
timeout = 5000;
this.onMouseMove = function(){
clearInterval(ID);
ID = setInterval(action, timeout);
trace("interaction");
};
function action(){
clearInterval(ID);
trace("no interaction for 5 seconds");
// go to end frame
};
Here is static class I wrote for a kiosk application I made many years ago. You just pass in a reference to the main stage, a function to reset the program, and a dialog box function (you could easily take out that part of the code if you don't want the dialog).
TimeoutManager.init(stage, myResetFunction, myDialogBoxFunction);
You could enable or disable it anytime with: TimeoutManager.kioskTimeoutEnabled = false;
Let me know if you have any questions about it, it's fairly well commented.
package
{
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.clearTimeout;
import flash.utils.setTimeout;
import flash.utils.Timer;
/**
* Manages the Kiosk session timeout functionality
* #LDMS
*/
public class TimeoutManager
{
//KioskTimeout Vars
private static var kioskTimeoutEnabled_ :Boolean = false;
private static var kioskTimeoutTimer :Timer = new Timer(3000, 1);
private static var kioskTimeout :uint;
private static var timeoutCountdownTimer:Timer = new Timer(1000);
private static var stage :Stage;
public static var defaultTime :int = 120000; //2 minutes - amount of inactivity before the "are you still there" message comes up.
public static var dialogTime :int = 30000; //30 seconds - amount of time to wait for the user to click the "are you still there" message before reseting the applicaiton
public static var resetFunction :Function; //the function to call to reset the application
public static var dialogFunction:Function; //the function to call to show a dialog box - passes tittle & text as two parameters to the method.
public static function init(mainStage:Stage, resetFunction_:Function, dialogFunction_:Function):void {
stage = mainStage;
resetFunction = resetFunction_;
dialogFunction = dialogFunction_;
kioskTimeoutTimer.addEventListener(TimerEvent.TIMER, timeoutKiosk, false, 0, true);
kioskTimeoutEnabled = true;
timeoutCountdownTimer.addEventListener(TimerEvent.TIMER, countdownTick, false, 0, true);
}
/**
* Enable or Disable the Kiosk reset timeout feature
*/
public static function set kioskTimeoutEnabled(val:Boolean):void
{
kioskTimeoutEnabled_ = val;
if (val) {
setKioskTimeout();
try { stage.addEventListener(MouseEvent.MOUSE_DOWN, kioskTimeoutReset, false, 0, true); } catch (e:Error) { trace(e.toString()); };
} else {
cancelKioskTimeout();
try { stage.removeEventListener(MouseEvent.MOUSE_DOWN, kioskTimeoutReset, false); } catch (e:Error) { trace(e.toString()); };
};
}
public static function get kioskTimeoutEnabled():Boolean { return kioskTimeoutEnabled_; };
/**
* Resets the timeout period for the kiosk reset timeout feature - called on a global mouse_down event.
* #param e - unused mouse_down event
*/
public static function kioskTimeoutReset(e:Event = null):void {
cancelKioskTimeout();
setKioskTimeout();
}
/**
* used to cancel the kiosk timeout period temporarily
*/
public static function cancelKioskTimeout():void {
kioskTimeoutTimer.reset();
}
/**
* Set or reset the time (in milliseconds) before the kiosk times out.
* #param overrideTime - if not 0 (default), sets a temporary new time (in milliseconds) before the kiosk times out.
*/
public static function setKioskTimeout(overrideTime:Number = 0):void {
if(!kioskTimeoutEnabled) return;
try { cancelKioskTimeout(); } catch (e:Error) { };
var time:Number = (overrideTime > 0) ? overrideTime : defaultTime;
kioskTimeoutTimer.delay = time;
kioskTimeoutTimer.start();
}
/**
* after the set inactivity period passes, this function is called to let the user know the kiosk is about to reset giving them a chance to keep their session alive
*/
private static function timeoutKiosk(e:Event = null):void {
dialogFunction("Are you still there?", "Reset in " + String(Preferences.kioskTimeout_dialogTime / 1000) + " seconds");
timeoutCountdownTimer.start();
kioskTimeout = setTimeout(goReset, dialogTime);
stage.addEventListener(MouseEvent.MOUSE_DOWN, clearKioskTimeout2,false,0,true);
}
protected static function countdownTick(e:TimerEvent):void {
dialogFunction("Are you still there?", "Reset in " + String((Preferences.kioskTimeout_dialogTime / 1000) - timeoutCountdownTimer.currentCount) + " seconds");
}
/**
* Cancels the timeout prompt timeout
* #param e - unused mouse event
*/
private static function clearKioskTimeout2(e:Event = null):void {
try {
stage.removeEventListener(MouseEvent.MOUSE_DOWN, clearKioskTimeout2,false);
}catch (e:Error) { trace(e.toString()); };
clearTimeout(kioskTimeout);
timeoutCountdownTimer.reset();
}
private static function goReset(e:Event = null):void {
timeoutCountdownTimer.reset();
resetFunction();
}
}
}

AS3 - Local P2P networking receiving only "undefined" data

I'm trying to make a simple P2P networking system to send messages to other Flash Players on your network.
However, when I send a message the receiving player doesn't receive a message but rather a undefined object.
I did allow Flash Player in my Virus Scanner (NOD 32) and my Windows Firewall by the way.
Here's my P2P class:
package com.snakybo.as3framework.network {
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.net.GroupSpecifier;
import flash.net.NetConnection;
import flash.net.NetGroup;
/** #author Kevin */
public class P2P extends NetConnection {
private var netCon:NetConnection;
private var netGroup:NetGroup;
private var handler:Function;
private var groupName:String;
public function P2P(groupName:String, handler:Function) {
this.groupName = groupName;
this.handler = handler;
netCon = new NetConnection();
netCon.addEventListener(NetStatusEvent.NET_STATUS, conHandler);
netCon.connect("rtmfp:");
}
/** Post a message */
public function post(txt:*):void {
var data:Object = new Object();
data["txt"] = txt;
data["id"] = new Date().time;
netGroup.post(data);
}
/** Handle connection event listener */
private function conHandler(e:NetStatusEvent):void {
if(e.info["code"] == "NetConnection.Connect.Success") {
setupGroup();
}
}
/** Connect to group */
private function setupGroup():void {
var groupSpec:GroupSpecifier = new GroupSpecifier(groupName);
groupSpec.postingEnabled = true;
groupSpec.ipMulticastMemberUpdatesEnabled = true;
groupSpec.addIPMulticastAddress("225.225.0.1:30000");
netGroup = new NetGroup(netCon, groupSpec.groupspecWithAuthorizations());
netGroup.addEventListener(NetStatusEvent.NET_STATUS, handler);
dispatchEvent(new Event(Event.COMPLETE));
}
}
}
Connection seems to be working, since I can send messages and the other player does receive them.. well.. receive something.
Then from my Main.as I call this class like this:
private var p2p:P2P;
public function Main():void {
p2p = new P2P("snakybo", netHandler);
p2p.addEventListener(Event.COMPLETE, onConnected);
}
private function onConnected(e:Event):void {
function send(e:KeyboardEvent):void {
c.post("a");
trace("poseted");
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, send);
}
private function netHandler(e:NetStatusEvent):void {
switch(e.info["code"]) {
case "NetGroup.Posting.Notify":
trace("received: " + e.info["txt"]);
break;
}
}
Also, if I add:
case "NetGroup.Connection.Success":
trace("Connected to group");
break;
It never prints that. Not sure what's wrong with that.
Am I doing anything wrong here? Or did my PC somehow block Flash Player?
In your P2P class you have this...
netCon.connect("rtmfp:");
This tells your NetConnection to connect to a string ("rtmfp:") which isn't a server or valid connection type if you are trying to reach outside members of the rtmfp connection. It appears you are using this for an internal network so "rtmfp" will work locally.
What I do with NetConnection.connect() is I set up my rtmfp constant and a developer key constant (for cirrus server) right off the bat like this...
cons SERVER:String = "rtmfp:";
cons DEVKEY:String = "your developer key here";
then
function connect(): void {
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
nc.connect(SERVER + DEVKEY);
}
You can go to adobes website if you are using their rtmfp server to get a developer key, they are free and easy to get anyway. Once you are connected you will get a NetStatus event string of "NetConnection.Connect.Success" which your conHandler function is set up to receive. I use a Switch Case within mine to listen for the connect string and do something based off each string like this:
function netStatus(event: NetStatusEvent): void {
switch (event.info.code) {
case "NetConnection.Connect.Success":
setupGroup();
break;
} }
Fire your setupGroup() function when you hear "NetConnection.Connect.Success". Then within your setupGroup() go ahead and set your
groupspec.serverChannelEnabled = true;
groupspec.routingEnabled = true;
groupspec.objectReplicationEnabled = true; // and I have
groupspec.peerToPeerDisabled = false;
Also, in your setupGroup you are firing "handler" instead of "conHandler" which is the name of your NetStatus event function handler. Probably just a typo. Setting the new NetGroup itself will fire 1 of 3 NetStatus events telling you the status of the new netgroup connection so you won't need to dispatch the event you are using unless you want to, up to you. You can handle those in your conHandler function as well.
I will typically have a trace statement setup to print out the NetStatusEvent so in your case that would be... trace(e.info.code) and you will be able to see the events as they happen and be able to troubleshoot problems much easier. Once you get this connection up you'll be able to handle the delivering of objects.
This should at least get you a created instance and the connection to others in the group. I have included a couple links I referenced here:
NetGroup
NetStatus
NetConnection
Try googling Tom Krcha, he is with adobe and has some good info on this as well.

Actionscript 3 - checking for an internet connection

I am using this code in my flash file
import air.net.URLMonitor;
import flash.net.URLRequest;
import flash.events.StatusEvent;
var monitor:URLMonitor;
function checkInternetConnection(e:Event = null):void
{
var url:URLRequest = new URLRequest("http://www.google.com");
url.method = "HEAD";
monitor = new URLMonitor(url);
monitor.pollInterval = 1000;
//
monitor.addEventListener(StatusEvent.STATUS, checkHTTP);
//
function checkHTTP(e:Event = null):void
{
if (monitor.available) {
navigateToURL(new URLRequest("flickr.html"),"_top");
} else {
gotoAndPlay(1);
}
}
monitor.start();
}
I am trying to get the flash to check for a connection and navigate to another page if not it will replay.
It doesnt seem to be working.
Am i missing anything?
I have add the library path to aircore.swc also.
Its meant to be a html page with flash rather than an AIR app
Cheers
(My reputation is too low to comment on Tianzhen Lin's answer directly ...)
I needed to make a few changes in order to get Tianzhen Lin's answer to work as expected:
Added:
urlRequest.useCache = false;
urlRequest.cacheResponse = false;
This addition was required because even when the connection was definitely lost, the check was still succeeding because the cache was being read from.
Changed:
if( textReceived.indexOf( _contentToCheck ) )
to:
if( !(textReceived.indexOf( _contentToCheck ) == -1) )
This change was required because while "" (an empty string) was always being found, it was being found at index '0' which was causing the original if() condition to always fail.
Added:
urlRequest.idleTimeout = 10*1000;
In the case where the network cable was physically disconnected from the router, the request could take a very long time to time-out (Honestly, I got tired of waiting after a couple of minutes.)
After making the above changes, I found Tianzhen's code worked perfectly: No matter how I went about disconnecting/reconnecting Wi-Fi (on both iOS and Android devices) the change in connection status was always detected.
I see two issues in your code. One is that while you have the logic to check internet connection, there is not any code calling the function, therefore the logic of redirection would not be called. Second is that using AIRcore.swc would be a bad idea as you have injected a dependency that might not work with or violate browser sandbox.
You may try the following approach which is tested and requires no AIR's SWC:
Step 1, include a new class ConnectionChecker as follow:
package
{
import flash.events.*;
import flash.net.*;
[Event(name="error", type="flash.events.Event")]
[Event(name="success", type="flash.events.Event")]
public class ConnectionChecker extends EventDispatcher
{
public static const EVENT_SUCCESS:String = "success";
public static const EVENT_ERROR:String = "error";
// Though google.com might be an idea, it is generally a better practice
// to use a url with known content, such as http://foo.com/bar/mytext.txt
// By doing so, known content can also be verified.
// This would make the checking more reliable as the wireless hotspot sign-in
// page would negatively intefere the result.
private var _urlToCheck:String = "http://www.google.com";
// empty string so it would always be postive
private var _contentToCheck:String = "";
public function ConnectionChecker()
{
super();
}
public function check():void
{
var urlRequest:URLRequest = new URLRequest(_urlToCheck);
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, loader_complete);
loader.addEventListener(IOErrorEvent.IO_ERROR, loader_error);
try
{
loader.load(urlRequest);
}
catch ( e:Error )
{
dispatchErrorEvent();
}
}
private function loader_complete(event:Event):void
{
var loader:URLLoader = URLLoader( event.target );
var textReceived:String = loader.data as String;
if ( textReceived )
{
if ( textReceived.indexOf( _contentToCheck ) )
{
dispatchSuccessEvent();
}
else
{
dispatchErrorEvent();
}
}
else
{
dispatchErrorEvent();
}
}
private function loader_error(event:IOErrorEvent):void
{
dispatchErrorEvent();
}
private function dispatchSuccessEvent():void
{
dispatchEvent( new Event( EVENT_SUCCESS ) );
}
private function dispatchErrorEvent():void
{
dispatchEvent( new Event( EVENT_ERROR ) );
}
}
}
Step 2, in your main application or anywhere that internet connection should be checked, use the following snippet:
var checker:ConnectionChecker = new ConnectionChecker();
checker.addEventListener(ConnectionChecker.EVENT_SUCCESS, checker_success);
checker.addEventListener(ConnectionChecker.EVENT_ERROR, checker_error);
checker.check();
private function checker_success(event:Event):void
{
// There is internet connection
}
private function checker_error(event:Event):void
{
// There is no internet connection
}
The air.net.URLMonitor is the AIR available class - so will not work outside of the AIR player.
But you could try to do your own as all this monitor class does is "ping" the url and check the response, so you could do similar try to load something from known source like google.com and if it completes wihtout error then it is OK otherwise you will get error.

AS3 for Facebook - why is my login callback not being called?

We're developing a Flash site that integrates with Facebook heavily.
We've noticed a bug where, if a user is not logged into Facebook, and we try to log them in via Facebook.login in the AS3 classes provided by Adobe, the callback is invoked, but the parameters result:Object and fail:Object are BOTH null. If our user then tries to login again, it all works fine, returning the userid in result:Object if successful.
Is this a bug with Facebook itself? Has anyone seen this before? We're sure this wasn't happening about a week ago.
Facebook.login(onLogin, {perms:Config.FB_PERMISSIONS});
private function onLogin(result:Object, fail:Object):void {
// first time this is called after the popup closes returns
// result == null and fail == null
// second time around, results are as expected
}
Cheers,
Mark.
this is a way to connect to Facebook using Graph API. Everything is explained in comment. This is actually the connecting to facebook, no posting to walls or anything. That part can be found below this class.
package com.DAL
{
import com.facebook.graph.Facebook;
import flash.events.Event;
import com.facebook.graph.data.FacebookSession;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import com.fbLoginButton;
import com.adobe.serialization.json.JSON;
public class FBConnect extends EventDispatcher
{
/******************************************
* Variables
******************************************/
private var _applicationID:String;
private var _extendedPermissions:Object;
/******************************************
* Constants
******************************************/
public static const CONNECTED:String = "CONNECTED";
/******************************************
* Properties
******************************************/
public function get applicationID():String
{
return _applicationID;
}
/******************************************
* Constructor
******************************************/
public function FBConnect()
{
super();
//Set applicationid
_applicationID = "YOUR_ID";
//Set permissions to ask for
_extendedPermissions = {perms:"read_stream, publish_stream, user_about_me, read_friendlists, user_photos"};
//Initialize facebook
Facebook.init(_applicationID);
}
/******************************************
* Methods
******************************************/
public function login(e:MouseEvent):void
{
Facebook.login(handleLogin, _extendedPermissions);
}
private function handleLogin(response:Object, fail:Object):void
{
dispatchEvent(new Event(CONNECTED));
}
}
}
That should take care of connecting to facebook. If you want to post to walls or anything, you can find a small example below.
/******************************************
* Constructor
******************************************/
public function FBLogic()
{
super();
_connect = new FBConnect();
_connect.addEventListener(FBConnect.CONNECTED, startLoaders);
initLoaders();
}
/******************************************
* Methods
******************************************/
...
public function post(message:String):void
{
var _params:Object = new Object();
_params.access_token = Facebook.getSession().accessToken;
_params.message = message;
Facebook.api("/" + _userID + "/feed", messagePosted, _params, "POST");
}
public function messagePosted(response:Object, fail:Object):void
{
dispatchEvent(new Event(MESSAGEPOSTED));
}
public function login(e:MouseEvent):void
{
var _loginButton:fbLoginButton = e.target as fbLoginButton;
_loginButton.alpha = 0;
_loginButton.visible = false;
_connect.login(e);
}
If this doesn't do the trick you might have forgotten to add some code to your html file. Be sure to add the following code to the head of your html file:
<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
And you also need a div called fb-root, declared like this.
<body>
<div id="fb-root"></div>
<div id="flashContent">
</div>
</body>
This is kinda dirty, but for me a timeout before calling login worked fine:
setTimeout(Facebook.login, 200, onLogin, {perms:Config.FB_PERMISSIONS});
_extendedPermissions = {perms:"read_stream, publish_stream, user_about_me, read_friendlists, user_photos"};
Blockquote
"perms" is now "scope"
{scope:"read_stream, publish_stream, user_about_me, read_friendlists, user_photos"};
This is not very well documented on the Adobe Facebook API page.
SHORT ANSWER
Just keep Facebook.init() looping every 0.5 seconds until it finds a valid credential cookie.
LONG ANSWER
The docs describe Facebook.init() as a setup function. But it does more than that, it looks for valid fb logon cookie. As does Facebook.login().
The idea is call Facebook.init() at startup and see if user already have access. Else use Facebook.login() to make the user logon.
Not executable code:
/**
* Start the app, and see if there are any valid credentials
**/
public function startApp() {
Facebook.init(fbAppid, handleFbLogin);
}
/**
* This is a method to call the app didnt login successfully
* at startup.
**/
private function tryLogin() {
Facebook.login(handleFbLogin, {});
}
private var lastLoginSuccess:Object; //being a bit pedantic maybe
/**
* This is the callback that is <i>supposed</i> to run
* ones the user has logged in.
* Unfortunately the callback assoc. with the login/init
* goes off almost instantly; and so often fails before
* valid credentials have been creations >:(
**/
public function handleFbLogin(success:Object, fail:Object) {
lastLoginSuccess = success;
if(success){
//yay!
} else {
//taps foot impatiently...
flash.utils.setTimeout(tryFbInitIfLastFailed, 500);
}
}
/**
* And also the user could be taking their sweet time
* typing in their password.
* Oh and giving their device informative names like 'qwe'
*
* So when they finally login, and the regularly executing
* handleFbLogin() will finally find some valid credentials
**/
private function tryFbInitIfLastFailed() {
if (lastLoginSuccess == null)
Facebook.init(view.fbApp.id, handleFbLogin);
}
Any why not keep calling Facebook.login()? because the opens the Facebook login popup - so you will have a steady stream of popups.
This works for me, either if im not logged in or if im already:
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
Facebook.init("APPID", onInit);
}
private function onInit(response:Object, fail:Object):void
{
if(response)
{
handleLoginResponse(true, null);
}
else
{
Facebook.login(handleLoginResponse, { scope: "email, user_photos, publish_stream" } );
}
}
private function handleLoginResponse(result:Object, fail:Object):void
{
if (result != null) {
// Logged in
} else {
// Goodbye :(
}
}
Add https for all.js in the tag you use in the html file