I am planing a project that involves a cross platform (Android and I.O.S) mobile app that logs in using Facebook. I have no experience with the face book API and cant find any use full material for newbies. I want to use air for its cross platform capabilities so want to avoid multiple solutions for each platform. I have done many searches for help but haven't found much. Can any of you point me to resources you found use full starting off with this sort of thing.
The AS3 Facebook API is all you need. ( http://code.google.com/p/facebook-actionscript-api/ ) Maybe you will have to change a few things (like the JSON methods in there) but otherwise it seems to work alright. You can download several examples from there as well, you can see the usage for different types of environment.
Also, read this article from Tom Krcha http://www.adobe.com/devnet/games/articles/getting-started-with-facebooksdk-actionscript3.html
If you have more specific questions, ask. This one is too generic.
EDIT:
Here is a class I wrote some time ago for a small project
package com.company.social {
import com.facebook.graph.FacebookMobile;
import com.company.AppConst;
import com.company.IDestroyable;
import com.company.Main;
import com.company.displayassets.WebViewCloseStripe;
import com.company.events.FacebookControllerEvent;
import com.company.events.TwitterControllerEvent;
import flash.display.BitmapData;
import flash.display.PNGEncoderOptions;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.media.StageWebView;
import flash.utils.ByteArray;
import flash.utils.clearTimeout;
import flash.utils.setTimeout;
public class FacebookController extends EventDispatcher implements IDestroyable {
private static const APP_ID:String = "1234512345"; // Your App ID.
private static const SITE_URL:String = "some_url";
//Extended permission to access other parts of the user's profile that may be private, or if your application needs to publish content to Facebook on a user's behalf.
private var _extendedPermissions:Array = ["publish_stream","user_website","user_status","user_about_me"];
private var _stage:Stage;
private var _webView:StageWebView;
private var _topStripe:WebViewCloseStripe;
private var _activity:String;
private var _timeoutID:uint;
public static const ACTIVITY_LOGIN:String = "login";
public static const ACTIVITY_POST:String = "post";
public function FacebookController(stage:Stage) {
_stage = stage;
init();
}
private function init():void {
_activity = ACTIVITY_LOGIN;
startTimeout();
FacebookMobile.init(APP_ID, onHandleInit, null);
}
private function onHandleInit(response:Object, fail:Object):void {
if (response) {
stopTimeout();
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.LOGIN_COMPLETE));
//FacebookMobile.api("/me", handleUserInfo);
}
else {
/*trace("no response, login -->");
for(var prop in fail["error"]) {
trace(prop+": "+fail["error"][prop]);
}*/
loginUser();
}
}
private function startTimeout():void {
trace("timeout start");
clearTimeout(_timeoutID);
_timeoutID = setTimeout(timeout, AppConst.TIMEOUT_TIME);
}
private function timeout():void {
trace("timed out");
clearTimeout(_timeoutID);
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.TIMEOUT));
}
private function stopTimeout():void {
trace("timeout stop");
clearTimeout(_timeoutID);
}
private function loginUser():void {
stopTimeout();
_topStripe = new WebViewCloseStripe();
_topStripe.getCloseButton().addEventListener(MouseEvent.CLICK, closeClickHandler);
_stage.addChild(_topStripe);
_webView = new StageWebView();
_webView.viewPort = new Rectangle(0, _topStripe.height, _stage.fullScreenWidth, _stage.fullScreenHeight - _topStripe.height);
FacebookMobile.login(handleLogin, _stage, _extendedPermissions, _webView);
}
private function handleLogin(response:Object, fail:Object):void {
if(_topStripe) {
_topStripe.getCloseButton().removeEventListener(MouseEvent.CLICK, closeClickHandler);
_topStripe.destroy();
_stage.removeChild(_topStripe);
_topStripe = null;
}
if(_webView) {
_webView = null;
}
if(response) {
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.LOGIN_COMPLETE));
//FacebookMobile.api('/me', handleUserInfo);
}
else {
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.LOGIN_ERROR));
}
}
private function closeClickHandler(e:MouseEvent):void {
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.CLOSE));
}
private function handleUserInfo(response:Object, fail:Object):void {
if (response) {
for(var prop in response) {
trace(prop+": "+response[prop]);
}
}
}
private function handleUploadImage(result:Object, fail:Object):void {
stopTimeout();
if(result) {
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.POST_COMPLETE));
}
else {
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.POST_ERROR));
}
}
public function postWithImage(message:String, imageData:BitmapData):void {
_activity = ACTIVITY_POST;
var byteArray:ByteArray = imageData.encode(new Rectangle(0, 0, imageData.width, imageData.height), new PNGEncoderOptions());
var params: Object = new Object;
params.image = byteArray;
params.fileName = "image.png";
params.message = message;
startTimeout();
FacebookMobile.api("/me/photos", handleUploadImage, params, "POST");
}
public function reset():void {
FacebookMobile.logout(handleReset, SITE_URL);
}
public function handleReset(response:Object):void {
dispatchEvent(new FacebookControllerEvent(FacebookControllerEvent.RESET));
}
public function destroy():void {
if(_webView) {
_webView.dispose();
_webView = null;
}
if(_topStripe) {
_topStripe.getCloseButton().removeEventListener(MouseEvent.CLICK, closeClickHandler);
_topStripe.destroy();
_stage.removeChild(_topStripe);
_topStripe = null;
}
_stage = null;
}
}
}
Alternatively you can use a native extension like this:
http://www.milkmangames.com/blog/tools/#iosgv
There are free versions from other publishers available as well.
Related
I am working on a multiplayer game in AS3/AIR for mobile (both android & iOS) and I want to implement a local multiplayer (on same wifi network/bluetooth) functionality in the game. What could be the best option to do this ??
it would be great if it is cross platform (android <-> iOS)
if i use peer-to-peer and Adobe Cirrus service (RTMFP) for local multiplayer, can I get into any problems, since the project is in beta ??
I already know about this post : http://forum.starling-framework.org/topic/google-play-game-services-ane-1#post-74449
I have also gone through this post : http://www.as3gamegears.com/category/multiplayer/ But some of the options that I like uses RTMFP which I am doubtful about !! So please suggest me if its ok to use ??
can I use Datagram Sockets class provided by the AIR sdk..?? Although I am not sure but is there any connection between RTMFP and TCP/Datagram sockets ??
If I any more details are required I can specify !!!
Thanks
I use Adobe Cirrus and it's work well. I used available docs and it takes me about 30 min to start communication between two devices. In my opinion it is best choice.
You can use RTMFP without Cirrus using the LAN NetGroup method.
This method is described in the documentation for NetConnection/connect():
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetConnection.html#connect()
A good example of this can be found here:
http://tomkrcha.com/?p=1803
private var connection:NetConnection;
private var group:NetGroup;
private function connect():void {
connection = new NetConnection();
connection.connect("rtmfp:");
connection.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
}
private function netStatus(event:NetStatusEvent):void {
switch(event.info.code){
case "NetConnection.Connect.Success":
joinGroup();
break;
case "NetGroup.Posting.Notify":
receive(event.info.message);
break;
}
}
private function joinGroup():void{
var groupspec:GroupSpecifier = new GroupSpecifier("myGroup/groupOne");
groupspec.postingEnabled = true;
groupspec.ipMulticastMemberUpdatesEnabled = true;
groupspec.addIPMulticastAddress("225.225.0.1:30303");
group = new NetGroup(connection, groupspec.groupspecWithAuthorizations());
group.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
}
public function send(text:String):void {
var message:Object = {
sender: connection.nearId,
text: text
}
group.post(message);
}
public function receive(message:Object):void {
trace("Received message from " + message.sender + ": " + message.text);
}
This is in my experienced the easiest way to do multi-user apps on a local network, because it requires no server (even to discover neighbors) and just the Flash Player.
You can try to use Bluetooth Low Energy in AIR for iOS(and OSX).
Demonstration here: http://www.youtube.com/watch?v=tiRfYjq4wh0&index=1&list=PLw76-mHQ5mhdmHPJy05n424-DKde1XM8G . ANE library here: http://flashpress.ru/blog/ane/bluetooth/?lang=en
CentralManager:
package
{
import flash.display.Sprite;
import ru.flashpress.ane.queue.FPQueueData;
import ru.flashpress.ane.queue.FPQueueTypes;
import ru.flashpress.bluetooth.FPBluetooth;
import ru.flashpress.bluetooth.constants.FPbtState;
import ru.flashpress.bluetooth.data.FPBluetoothOptions;
import ru.flashpress.bluetooth.events.FPBluetoothEvent;
import ru.flashpress.bluetooth.events.FPCentralManagerEvent;
import ru.flashpress.bluetooth.events.FPCharacteristicEvent;
import ru.flashpress.bluetooth.events.FPPeripheralEvent;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristic;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicValueFormat;
import ru.flashpress.bluetooth.helpers.characteristic.stream.FPStreamIn;
import ru.flashpress.bluetooth.helpers.peripheral.FPPeripheral;
import ru.flashpress.bluetooth.helpers.service.FPService;
import ru.flashpress.bluetooth.helpers.service.FPServiceEvent;
import ru.flashpress.bluetooth.managers.central.FPCentralManager;
import ru.flashpress.bluetooth.managers.central.FPcmScanOptions;
public class CentralView extends Sprite
{
public static const SERVICE_UUID:String = 'E20A39F4-73F5-4BC4-A12F-17D1AD07A961';
public static const CHARACTERISTIC_UUID:String = '08590F7E-DB05-467E-8757-72F6FAEB13D4';
//
public function CentralView()
{
var options:FPBluetoothOptions = new FPBluetoothOptions();
options.nativeLogEnabled = true;
FPBluetooth.init(options);
//
startBluetooth();
}
// Bluetooth Methods ****************
private var cm:FPCentralManager;
private function startBluetooth():void
{
trace('startBluetooth');
var queue:FPQueueData = new FPQueueData('ru.flashpress.chat.central', FPQueueTypes.SERIAL);
cm = new FPCentralManager(null, queue);
cm.addEventListener(FPBluetoothEvent.UPDATE_STATE, updateStateHandler);
cm.addEventListener(FPCentralManagerEvent.PERIPHERAL_DISCOVER, discoverPeripheralHandler);
}
private function updateStateHandler(event:FPBluetoothEvent):void
{
trace('updateStateHandler', event.state);
if (event.state != FPbtState.POWERED_ON) {
return;
}
var options:FPcmScanOptions = new FPcmScanOptions(true, null);
cm.startScan(options, SERVICE_UUID);
}
private var peripheral:FPPeripheral;
private function discoverPeripheralHandler(event:FPCentralManagerEvent):void
{
trace('discoverPeripheralHandler', event.peripheral);
if (peripheral) return;
peripheral = event.peripheral;
trace(' name:', peripheral.advertisementInited ? peripheral.advertisementInited.localName : null);
//
peripheral.addEventListener(FPPeripheralEvent.CONNECTED, peripheralConnectedHandler);
peripheral.addEventListener(FPPeripheralEvent.DISCONNECT, peripheralDisconnectedHandler);
peripheral.connect();
}
private function peripheralConnectedHandler(event:FPPeripheralEvent):void
{
trace('peripheralConnectedHandler');
peripheral.discoverServiceUUIDs(SERVICE_UUID);
peripheral.addEventListener(FPPeripheralEvent.DISCOVER_SERVICES, discoverServicesHandler);
}
private function peripheralDisconnectedHandler(event:FPPeripheralEvent):void
{
trace('peripheralDisconnectedHandler');
peripheral.removeEventListener(FPPeripheralEvent.CONNECTED, peripheralConnectedHandler);
peripheral.removeEventListener(FPPeripheralEvent.DISCONNECT, peripheralDisconnectedHandler);
peripheral = null;
}
private var service:FPService;
private function discoverServicesHandler(event:FPPeripheralEvent):void
{
trace('discoverServicesHandler');
if (event.error) {
trace('discoverServicesHandler, error:', event.error);
return;
}
//
service = peripheral.services.list[0];
trace(' service:', service);
//
service.discoverCharacteristicUUIDs(CHARACTERISTIC_UUID);
service.addEventListener(FPServiceEvent.DISCOVER_CHARACTERISTICS, discoverCharacteristicsHandler);
}
public var characteristic:FPCharacteristic;
private var streamIn:FPStreamIn;
private function discoverCharacteristicsHandler(event:FPServiceEvent):void
{
trace('discoverCharacteristicsHandler');
if (event.error) {
trace('discoverCharacteristicsHandler, error:', event.error);
return;
}
characteristic = service.characteristics.list[0];
trace(' characteristic:', characteristic);
characteristic.initValueFormat(FPCharacteristicValueFormat.MESSAGES);
streamIn = characteristic.streamIn;
characteristic.setNotify(true);
characteristic.addEventListener(FPCharacteristicEvent.UPDATE_NOTIFICATION, updateNotificationHandler);
//
characteristic.addEventListener(FPCharacteristicEvent.UPDATE_MESSAGES, updateMessageHandler);
}
private function updateNotificationHandler(event:FPCharacteristicEvent):void
{
trace('updateNotificationHandler:', event.isNotifying);
}
private function updateMessageHandler(event:FPCharacteristicEvent):void
{
trace('updateMessageHandler');
trace(' error:', event.error);
trace(' messages:', event.messages);
}
}
}
Peripheral Manager:
package
{
import flash.display.Sprite;
import ru.flashpress.bluetooth.FPBluetooth;
import ru.flashpress.bluetooth.constants.FPbtState;
import ru.flashpress.bluetooth.data.FPAdvertisementData;
import ru.flashpress.bluetooth.data.FPBluetoothOptions;
import ru.flashpress.bluetooth.events.FPBluetoothEvent;
import ru.flashpress.bluetooth.events.FPCharacteristicEvent;
import ru.flashpress.bluetooth.events.FPPeripheralManagerEvent;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristic;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicPermissions;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicProperties;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicValueFormat;
import ru.flashpress.bluetooth.helpers.service.FPService;
import ru.flashpress.bluetooth.managers.peripheral.FPPeripheralManager;
public class PeripheralView extends Sprite
{
public static const SERVICE_UUID:String = 'E20A39F4-73F5-4BC4-A12F-17D1AD07A961';
public static const CHARACTERISTIC_UUID:String = '08590F7E-DB05-467E-8757-72F6FAEB13D4';
//
public function PeripheralView()
{
var options:FPBluetoothOptions = new FPBluetoothOptions();
options.nativeLogEnabled = true;
FPBluetooth.init(options);
//
startBluetooth();
}
// Bluetooth Methods ****************
private var pm:FPPeripheralManager;
private function startBluetooth():void
{
trace('startBluetooth');
pm = new FPPeripheralManager();
pm.addEventListener(FPBluetoothEvent.UPDATE_STATE, updateStateHandler);
pm.addEventListener(FPPeripheralManagerEvent.ADD_SERVICE, addServiceHandler);
}
private var characteristic:FPCharacteristic;
private var service:FPService;
private function updateStateHandler(event:FPBluetoothEvent):void
{
trace('updateStateHandler:', event.state);
if (event.state != FPbtState.POWERED_ON) {
return;
}
//
var properties:uint = FPCharacteristicProperties.NOTIFY;
var permissions:uint = FPCharacteristicPermissions.WRITEABLE;
var valueFormat:uint = FPCharacteristicValueFormat.MESSAGES;
characteristic = new FPCharacteristic(CHARACTERISTIC_UUID, properties, permissions, valueFormat);
characteristic.addEventListener(FPCharacteristicEvent.SUBSCRIBED_TO_CENTRAL, subscribedToCentralHandler);
characteristic.addEventListener(FPCharacteristicEvent.UNSUBSCRIBED_FROM_CENTRAL, unsubscribedFromCentralHandler);
characteristic.notifyMTU = 50;
//
service = new FPService(SERVICE_UUID, true);
service.addCharacteristic(characteristic);
//
pm.addService(service);
}
private function addServiceHandler(event:FPPeripheralManagerEvent):void
{
trace('addServiceHandler');
if (event.error) {
trace(' error:', event.error);
return;
}
if (!pm.isAdvertising) {
var uuids:Vector. = new [SERVICE_UUID];
var advertisementData:FPAdvertisementData = new FPAdvertisementData('My Local name', uuids);
pm.startAdvertising(advertisementData);
}
}
private function unsubscribedFromCentralHandler(event:FPCharacteristicEvent):void
{
trace('unsubscribedFromCentralHandlers', event.central);
}
private function subscribedToCentralHandler(event:FPCharacteristicEvent):void
{
trace('subscribedToCentralHandler', event.central);
//
characteristic.sendMessage('send my message');
}
}
}
I would like to send an XML message, and receive a response from a server and decode it.
That's my class design approach, I would like to know the best design for that thing.
class XMLRequest extends EventDispatcher
{
private var m_data:XML;
private var m_xmlString:String;
public function XMLRequest(){ m_data = null;}
public function setRequest(xmlString:String):Boolean
{
if(xmlString)
{
m_data = new XML(xmlString);
trace("Request --" + m_xmlString);
return true;
}
return false;
}
}
class XMLResponse extends EventDispatcher
{
private m_xmlString:String;
public function XMLResponse(){ m_data = null;}
public function getResponse(data:XML):String
{
if(data)
{
m_xmlString = data.toString();
trace("Repsonse --" + m_xmlString);
return m_xmlString;
}
return " ";
}
then I will have a class Client, that sends and receives the response.
Is that a good approach or not ?
I recommend use class disign like adobe Loader. Also, I recommend use native class XML instead of String
XMLLoader.as
package {
import flash.events.IEventDispatcher;
[Event(type="flash.events.Event", name="complete")]
public interface XMLLoader extends IEventDispatcher {
function load(requestXML:XML):void;
function getResponseXML():XML;
}
}
XMLLoaderTester.as
package {
import flash.display.Sprite;
import flash.events.Event;
public class XMLLoaderTester extends Sprite {
public function XMLLoaderTester() {
var loader:XMLLoader; //dont forget instantiate
loader.addEventListener(Event.COMPLETE, onResponse);
var requestXML:XML = <command>getData</command>;
loader.load(requestXML);
}
private function onResponse(event:Event):void {
var loader:XMLLoader = XMLLoader(event.target);
trace(loader.getResponseXML());
}
}
}
Hello I am trying to record the user sound using AS3 Worker everything works well when it comes to communication between the worker and the main scene but I think the record functionnality have and issue here I am using the Record Clash from bytearray.org (http://www.bytearray.org/?p=1858)
and here's is my code am I missing something :
package objects
{
import flash.events.Event;
import flash.system.MessageChannel;
import flash.system.Worker;
import flash.system.WorkerDomain;
import flash.utils.ByteArray;
import starling.display.Button;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
public class RecordComponent extends Sprite
{
private var audioContainer:Image;
private var recButton:Button;
private var playButton:Button;
private var stopButton:Button;
//background thread for recording
private var worker:Worker;
private var wtm:MessageChannel;
private var mtw:MessageChannel;
private var output:ByteArray;
public function RecordComponent()
{
super();
worker = WorkerDomain.current.createWorker(Workers.RecordWorker);
wtm = worker.createMessageChannel(Worker.current);
mtw = Worker.current.createMessageChannel(worker);
worker.setSharedProperty("wtm",wtm);
worker.setSharedProperty("mtw",mtw);
worker.start();
wtm.addEventListener(flash.events.Event.CHANNEL_MESSAGE,onChannelMessage);
this.addEventListener(starling.events.Event.ADDED_TO_STAGE, onAddedToStage);
}
protected function onChannelMessage(event:flash.events.Event):void
{
output = wtm.receive();
}
protected function onAddedToStage(event:starling.events.Event):void
{
this.removeEventListener(starling.events.Event.ADDED_TO_STAGE, onAddedToStage);
drawScreen();
}
private function drawScreen():void
{
audioContainer = new Image( Assets.getAtlas().getTexture("audioContainer") );
addChild(audioContainer);
//record button
recButton = new Button( Assets.getAtlas().getTexture("recordButton") );
recButton.x=Math.ceil(194/2 - recButton.width/2);
recButton.y=5;
addChild(recButton);
//stop button
stopButton = new Button( Assets.getAtlas().getTexture("stopButton") );
stopButton.x=recButton.x+10;
stopButton.y=10;
stopButton.visible = false;
addChild(stopButton);
//play button
playButton = new Button( Assets.getAtlas().getTexture("playButton") );
playButton.x=Math.ceil(194 - playButton.width)-25;
playButton.y=10;
playButton.visible = false;
addChild(playButton);
this.addEventListener(starling.events.Event.TRIGGERED, buttons_triggeredHandler);
}
private function buttons_triggeredHandler(event:starling.events.Event):void
{
var currentButton:Button = event.target as Button;
switch(currentButton)
{
case recButton:
startRecording();
break;
case stopButton:
stopRecording();
break;
case playButton:
playRecording();
break;
}
}
private function playRecording():void
{
mtw.send("RECORD_PLAY");
}
private function stopRecording():void
{
stopButton.visible = false;
recButton.x = 25;
playButton.visible = true;
recButton.visible = true;
mtw.send("RECORD_STOP");
//
}
private function startRecording():void
{
recButton.visible = false;
stopButton.visible = true;
playButton.visible = false;
mtw.send("RECORD_START");
}
}
}
RecordWorker
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.media.Microphone;
import flash.system.MessageChannel;
import flash.system.Worker;
import org.as3wavsound.WavSound;
import org.bytearray.micrecorder.MicRecorder;
import org.bytearray.micrecorder.encoder.WaveEncoder;
import org.bytearray.micrecorder.events.RecordingEvent;
public class RecordWorker extends Sprite
{
private var wtm:MessageChannel;
private var mtw:MessageChannel;
// volume in the final WAV file will be downsampled to 50%
private var volume:Number = .75;
// we create the WAV encoder to be used by MicRecorder
private var wavEncoder:WaveEncoder = new WaveEncoder( volume );
// we create the MicRecorder object which does the job
private var recorder:MicRecorder = new MicRecorder( wavEncoder,Microphone.getEnhancedMicrophone() );
public function RecordWorker()
{
wtm = Worker.current.getSharedProperty("wtm");
mtw = Worker.current.getSharedProperty("mtw");
mtw.addEventListener(Event.CHANNEL_MESSAGE,command_Handler);
}
//message received from the main component
protected function command_Handler(event:Event):void
{
switch(mtw.receive())
{
case "RECORD_START":
trace("recording.....");
recorder.record();
recorder.addEventListener(RecordingEvent.RECORDING, onRecording);
recorder.addEventListener(flash.events.Event.COMPLETE, onRecordComplete);
break;
case "RECORD_STOP":
trace("record stopped....");
recorder.stop();
break;
case "RECORD_PLAY":
if(recorder.output.length>0)
{
var player:WavSound = new WavSound(recorder.output);
player.play();
}
break;
}
}
private function onRecording(event:RecordingEvent):void
{
trace ( event.time );
}
private function onRecordComplete(event:flash.events.Event):void
{
}
}
}
anny help will be appriciated
Thanks,
Khaled
Looking at this write-up on Adobe's AS3 reference, it seems that because each created worker is "a virtual instance of the Flash runtime", it has no direct connection to any of the core runtime's input or output channels. The Microphone class is one such cut-off interface, which is why it can't reach the system mic inside a worker.
I would like to check the network status on the iPad with Adobe Air, at this moment i am checking by sending a URLREQUEST to Google.com. Is there any other better way to monitor the network status, and know if there is a connection or connection have been dropped. Thanks for any suggestion.
Tricky part here we are not ping some interval times. so we use
NativeApplication.nativeApplication.addEventListener(Event.NETWORK_CHANGE, onNetwork_ChangeHandler);
It will trigger when ever change net status change so performance wise also good.
Because Ping is very costly operation.So call start() URLMontior after network changed triggered then we call stop().
package com.abc.net
{
import air.net.URLMonitor;
import flash.desktop.NativeApplication;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.StatusEvent;
import flash.net.URLRequest;
[Event(name="networkStatusChanged", type="flash.events.Event")]
public class NetStatusMonitor extends EventDispatcher
{
private var urlMonitor:URLMonitor;
private var url:String;
public function KBNetStatusMonitor(url:String = 'http://www.adobe.com')
{
super();
this.url = url;
NativeApplication.nativeApplication.addEventListener(Event.NETWORK_CHANGE, onNetwork_ChangeHandler);
}
protected function onNetwork_ChangeHandler(event:Event):void
{
start();
}
public function start():void
{
urlMonitor = new URLMonitor(new URLRequest(url));
urlMonitor.addEventListener(StatusEvent.STATUS, onNetStatus_ChangeHandler);
if(!urlMonitor.running)
urlMonitor.start();
}
public function stop():void
{
if(urlMonitor.running)
urlMonitor.stop();
}
private function onNetStatus_ChangeHandler(event:StatusEvent):void
{
trace("event code " + event.code);
trace("event level " + event.level);
dispatchEvent(new NetStatusEvent(NetStatusEvent.NETWORK_STATUS_CHANGED,urlMonitor.available));
stop();
}
}
}
Event Class
package com.abc.net
{
import flash.events.Event;
public class NetStatusEvent extends Event
{
public static const NETWORK_STATUS_CHANGED:String = "networkStatusChanged";
public var status:Boolean;
public function NetStatusEvent(type:String, status:Boolean, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.status = status;
}
override public function clone():Event
{
return new NetStatusEvent(type, status, bubbles,cancelable);
}
}
}
Usage :
var netStatusMonitor:NetStatusMonitor = new NetStatusMonitor();
netStatusMonitor.addEventListener(NetStatusEvent.NETWORK_STATUS_CHANGED,function(event:NetStatusEvent):void {
statusCallBack.call(null,event.status);
});
netStatusMonitor.start();
I have the following situation:
I have an event handler, that displays small messages in my application's statusbar.
These messages get passes through by dispatching events from custom components.
A simple message could be like "HTTP Error" or so.
Now, the main event listener, in the main application file, listens to the event dispatched by any custom component, but seems to refuse listening to events dispatched by custom AS classes.
Here is my code for the custom event:
package main.events
{
import flash.events.Event;
public class ShowNoticeEvent extends Event
{
public var message:String;
public static const SHOW_NOTICE:String = "showNotice";
public function ShowNoticeEvent(type:String, msg:String, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
this.message = msg;
}
override public function clone():Event
{
return new ShowNoticeEvent(type, message);
}
}
}
This is the event listener in the main application file:
addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
And this is the custom AS class that dispatches the custom event. I pasted all the code, so you could see the whole part of it.
package components.dashboard
{
import components.dashboard.models.*;
/* Event imports */
import flash.events.*;
import main.events.*;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="showNotice", type="main.events.ShowNoticeEvent")]
public class Controller extends UIComponent
{
private var baseUrl:String;
public function Controller(baseUrl:String)
{
this.baseUrl = baseUrl;
}
public function getRunningQuotations():void
{
var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();
execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations");
}
public function getRecentProjects():void
{
var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();
execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
}
public function getLatestCustomers():void
{
var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();
execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
}
private function execService(url:String, listener:Function, component:String):void
{
var basicService:HTTPService = new HTTPService(baseUrl);
basicService.showBusyCursor = true;
basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
basicService.method = "POST";
basicService.resultFormat = "text";
basicService.url = url;
basicService.addEventListener(ResultEvent.RESULT, listener);
basicService.send();
}
private function httpFault(event:FaultEvent, component:String = null):void {
var faultstring:String = event.fault.faultString;
var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true);
dispatchEvent(eventObj);
trace(faultstring);
}
}
}
So to sum it all up:
- The event listener listens to the custom event dispatched by any custom component.
- The event listener does not listen to the custom event duspatched by an AS class.
Those who wonder, the event really gets dispatched, that's why I added a trace call.
The instance of Controller Class would have to be added to stage for that to work.
by doing
addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
in the main file you are adding the listener to the stage.
So basically you are doing.
stage.addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
If controler instance is not on stage you won't see the event.
You might want to look into a Singleton type pattern for your data management as that would fit this setup pretty good.
Main:
Controller.getLastInstance().addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true)
.
package components.dashboard
{
import components.dashboard.models.*;
/* Event imports */
import flash.events.*;
import main.events.*;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="showNotice", type="main.events.ShowNoticeEvent")]
public class Controller extends UIComponent
{
static public function getLastInstance():Controller { return _instance; }
static private var _instance:Controller;
private var baseUrl:String;
public function Controller(baseUrl:String)
{
_instance = this;
this.baseUrl = baseUrl;
}
public function getRunningQuotations():void
{
var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();
execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations");
}
public function getRecentProjects():void
{
var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();
execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
}
public function getLatestCustomers():void
{
var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();
execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
}
private function execService(url:String, listener:Function, component:String):void
{
var basicService:HTTPService = new HTTPService(baseUrl);
basicService.showBusyCursor = true;
basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
basicService.method = "POST";
basicService.resultFormat = "text";
basicService.url = url;
basicService.addEventListener(ResultEvent.RESULT, listener);
basicService.send();
}
private function httpFault(event:FaultEvent, component:String = null):void {
var faultstring:String = event.fault.faultString;
var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true);
dispatchEvent(eventObj);
trace(faultstring);
}
}
}
Not Ideal since you could only ever have 1 of them.
But I think better than having to turn a simple EventDispatcher into DisplayObject and add it to stage just to Simply bubble.