Gérer les Notifications Push sur IOs dans AIR

1/ Utilisez tout d’abord le SDK 4.6 avec AIR 3.4 minimum

2/Créer une classe qui gérera la notification en se connectant sur Urban Airship

package notifications
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.RemoteNotificationEvent;
	import flash.events.StatusEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestDefaults;
	import flash.net.URLRequestMethod;
	import flash.notifications.NotificationStyle;
	import flash.notifications.RemoteNotifier;
	import flash.notifications.RemoteNotifierSubscribeOptions;

	import ressources.tacSkinnableContainerDefault;

	import spark.components.Group;

	import taccomponents.tacEventsTools;

	public class NotifierAPN extends Sprite
	{
		private var _subscribeOptions:RemoteNotifierSubscribeOptions = new RemoteNotifierSubscribeOptions();
		private var _preferredStyles:Vector. = new Vector.();
		private var _remoteNot:RemoteNotifier = new RemoteNotifier();
		private var _urlString:String;
		private var _urlreq:URLRequest;
		private var _urlLoad:URLLoader = new URLLoader();

		/**
		 *
		 *
		 */
		public function NotifierAPN()
		{
			init();
		}

		/**
		 *
		 *
		 */
		private function init():void
		{
			trace("SupportedNotification Styles: " + RemoteNotifier.supportedNotificationStyles.toString() + "\n");

			trace("Before Preferred notificationStyles: " + _subscribeOptions.notificationStyles.toString() + "\n");

			_preferredStyles.push(NotificationStyle.ALERT ,NotificationStyle.BADGE,NotificationStyle.SOUND );

			_subscribeOptions.notificationStyles= _preferredStyles;

			trace("After Preferred notificationStyles:" + _subscribeOptions.notificationStyles.toString() + "\n");

			_remoteNot.addEventListener(RemoteNotificationEvent.TOKEN,tokenHandler);
			_remoteNot.addEventListener(RemoteNotificationEvent.NOTIFICATION,notificationHandler);
			_remoteNot.addEventListener(StatusEvent.STATUS,statusHandler);

			this.addEventListener(Event.ACTIVATE,activateHandler);
		}

		/**
		 *
		 * @param e
		 *
		 */
		public function tokenHandler(e:RemoteNotificationEvent):void
		{
			trace("\nRemoteNotificationEvent type: "+e.type +"\nBubbles: "+ e.bubbles + "\ncancelable " +e.cancelable +"\ntokenID:\n"+ e.tokenId +"\n");

			_urlString = new String("https://go.urbanairship.com/api/device_tokens/" + e.tokenId);
			_urlreq = new URLRequest(_urlString);

			_urlreq.authenticate = true;
			_urlreq.method = URLRequestMethod.PUT;

			URLRequestDefaults.setLoginCredentialsForHost("go.urbanairship.com","Application id","Application Secret");

			_urlLoad.load(_urlreq);
			_urlLoad.addEventListener(IOErrorEvent.IO_ERROR,iohandler);
			_urlLoad.addEventListener(Event.COMPLETE,compHandler);
			_urlLoad.addEventListener(HTTPStatusEvent.HTTP_STATUS,httpHandler);
		}

		/**
		 *
		 * @param e
		 *
		 */
		public function notificationHandler(e:RemoteNotificationEvent):void
		{
			trace("\nRemoteNotificationEvent type: " + e.type +"\nbubbles: "+ e.bubbles + "\ncancelable " +e.cancelable);

			for (var x:String in e.data)
			{
				trace("\n"+ x + ":  " + e.data[x]);
			}
		}

		/**
		 *
		 * @param e
		 *
		 */
		public function activateHandler(e:Event):void
		{
			if(RemoteNotifier.supportedNotificationStyles.toString() != " ")
			{
				_remoteNot.subscribe(_subscribeOptions);
			}
			else
			{
				trace("\n Remote Notifications not supported on this Platform !");
			}
		}

		/**
		 *
		 * @param e
		 *
		 */
		private function compHandler(e:Event):void
		{
			trace("\n In Complete handler,"+"status: " +e.type + "\n");
		}

		/**
		 *
		 * @param e
		 *
		 */
		private function httpHandler(e:HTTPStatusEvent):void
		{
			trace("\n in httpstatus handler,"+ "Status: " + e.status);
		}

		/**
		 *
		 * @param e
		 *
		 */
		private function iohandler(e:IOErrorEvent):void
		{
			trace("\n In IOError handler" + e.errorID +" " +e.type);
		}

		/**
		 *
		 * @param e
		 *
		 */
		public function statusHandler(e:StatusEvent):void
		{
			trace("\n statusHandler");

			trace("event Level" + e.level +"\nevent code " + e.code + "\ne.currentTarget: " + e.currentTarget.toString());
		}
	}
}

3/ Enfin ajouter dans le fichier Manifest :

<![CDATA[

<key>aps-environment</key>

<string>development</string>

]]>


Enveloppe d’une forme convexe en Action Script

Aujourd’hui voici un petit tutoriel sur la création d’une enveloppe d’une forme convexe.

notre forme sera un polygone constitué d’une nombre indéfinis de points.Le code présenté est inspiré de l’algorithme du parcours de Graham

on crée un tableau enveloppe qui stockera les points à relier. Le tableau d’objet points à au départ 2 propriétés : X et Y

var enveloppe:Array = [];

//Recherche du point le plus bas
var bas:Object = points.sortOn("y",Array.NUMERIC)[points.length-1];
points.pop();

Puis on affecte une propriété angle définies par rapport au point le plus bas

//Tri du reste du nuage en fonction des angles par rapport au point le plus bas
sens_trigo( bas,points ) ;
points.sortOn("angle",Array.NUMERIC);
enveloppe.push(bas);
points.push(bas);

enfin , nous pouvons créer l’enveloppe :

while(points.length > 0)
{
	//On retire le premier point du nuage et on le place dans l'enveloppe
	enveloppe.push(points.shift() ) ;
}

var spr:Shape = new Shape();
spr.graphics.lineStyle(group.@weight,group.@color);
spr.graphics.beginFill(group.@color);

for (var incS:int = 0; incS < enveloppe.length ; incS++)
{
	if(incS == 0)
	{
		spr.graphics.moveTo(enveloppe[incS].x,enveloppe[incS].y+20);
	}
	else
	{
		var deltaX:Number = enveloppe[incS].x-enveloppe[incS-1].x;
		var deltaY:Number = enveloppe[incS].y-enveloppe[incS-1].y;
		if(deltaX > 0)
			spr.graphics.curveTo(enveloppe[incS].x-deltaX/2,enveloppe[incS].y+Math.abs(deltaY),enveloppe[incS].x+20,enveloppe[incS].y);
		else
			spr.graphics.curveTo(enveloppe[incS].x-deltaX/2,enveloppe[incS].y-Math.abs(deltaY),enveloppe[incS].x-20,enveloppe[incS].y);
	}
}
spr.graphics.endFill();

Méthode sens_trigo :

private function sens_trigo(bas:Object,points:Array):void
{
     for each(var p:Object in points)
     {
	var angleRadian:Number = Math.atan2(bas.x - p.x, bas.y - p.y);
	var angleDegree:Number = angleRadian * (180 / Math.PI);
	p.angle = angleDegree;
      }
}

Pour rappel le pseudo code du parcours de Graham est celui ci :

Trouver le pivot P;
Trier les points par angle (les points d'angle égal seront triés par rapport à leur abscisse);

# Points[1] est le pivot, Points[longueur] aussi (fin du circuit)
Pile.empiler(Points[1]);
Pile.empiler(Points[2]);
POUR i = 3 A Points.longueur
        TANT QUE (Pile.hauteur >= 2) ET (Produit_vectoriel(Pile.second, Pile.haut, Points[i]) <= 0)
                Pile.dépiler;
        FIN TANT QUE
        Pile.empiler(Points[i]);
FIN POUR

FONCTION Produit_vectoriel(p1, p2, p3)
        RENVOYER(p2.x - p1.x)*(p3.y - p1.y) - (p3.x - p1.x)*(p2.y - p1.y);
FIN FONCTION


H.D Richards cas désespérés

HD Richard

Les Tanukis ont décidé pour leur nouveau jeu de faire appel aux dons sur Internet pour financer une partie d’ H.D. Richards-Cas désespérés, une enquête de détective embauché par une jeune fille pour faire innocenter son ami en prison.

Article sur 20 Minutes.fr

le teaser d’H.D Richard cas désespérés

http://vimeo.com/20887124





Design pattern en AS3 [Decorator] 7/7

Voici le 7 eme et dernier article sur les design pattern en Action Script 3 : le decorateur.

Un décorateur permet d’attacher dynamiquement de nouvelles responsabilités à un objet. Les décorateurs offrent une alternative assez souple à l’héritage pour composer de nouvelles fonctionnalités.

chaque couche implémente l’interface et delege a la couche inférieure. il invente de nouvelles fonctionnalités mais pas de nouvelles méthodes publiques.

Cette classe est un decorator :

package userInterface.contenu
{
	import flash.display.Sprite;
	import flash.events.IEventDispatcher;

	import userInterface.IInitDestroy;

	public interface IContenu extends IEventDispatcher , IInitDestroy
	{
		// 2 methodes implementes par AUserIterface
		function get content():Sprite;
		function active(value:Boolean):void;

		// 4 methodes implementes par BContenu
		function open():void;
		function close():void;
		function set animatorOpen(value:ContentAnimator):void;
		function set animatorClose(value:ContentAnimator):void;
	}
}

Cette classe utilise le decorateur pour utiliser les méthodes du decorateur , sans rajouter de nouvelle méthodes a celle ci :

package userInterface.contenu
{
	import flash.display.Sprite;
	import flash.events.Event;

	/* classe abstraite implementant icontenu
	les classes heritant de cette classe ont les memes methodes */
	public class AContenuDecorator implements IContenu
	{
		protected var _contenuAdecorer:IContenu;

		public function AContenuDecorator(contenuAdecorer:IContenu)
		{
			_contenuAdecorer = contenuAdecorer;
		}

		public function init():void
		{
			_contenuAdecorer.init();
		}

		public function destroy():void
		{
			_contenuAdecorer.destroy();

		}

		public function active(value:Boolean):void
		{
			_contenuAdecorer.active(value);
		}

		public function open():void
		{
			_contenuAdecorer.open();
		}

		public function close():void
		{
			_contenuAdecorer.close();
		}
	}
}





Design pattern en AS3 [Command] 6/7

Le patron de conception Command est un patron de type comportemental qui encapsule la notion d’invocation. Il permet de séparer complètement le code initiateur de l’action, du code de l’action elle-même. Le design pattern Command est souvent utilisé dans les IHM où, par exemple, un élément de menu peut actionner différentes Commandes de façons à ce que l’objet de cet élément n’ait pas besoin de connaître les détails de l’action effectuée par la Commande.

L’utilisation de ce patron de conception est recommandé lorsqu’il y a trop de commandes similaires et que le code devient difficile à maintenir.

Un objet Commande sert à communiquer une action à effectuer, ainsi que les arguments requis. L’objet est envoyé à une seule méthode dans une classe, qui traite les Commandes du type requis. L’objet est libre d’implémenter le traitement de la Commande par un switch, ou un appel à d’autres méthodes. Cela permet d’apporter des modifications aux Commandes définies simplement dans la définition de la Commande, et non dans chaque classe qui utilise la Commande.

Exmple d’utilisation du patron de conception Command en Action Script 3 :

// création d'un objet command

var clickMenu:clickMenuCommand = new clickMenuCommand(*);
// eexecution de cet objet

MainController.instance.commandManager.exec(clickMenu);