AIR pour mobile – Requêtes HTTP qui fonctionnent en Wifi mais pas en 3G (HTTPStatusEvent 403) [Résolu]
Alors voilà sûrement le bug le plus obscur et le plus improbable que j'ai jamais résolu. Entre le diagnostic, le debug peu facile et la résolution, je pense que j'ai bien passé 4 heures sur ce bug venu de nulle part.
Voici quelques explications qui devraient intéresser tout les développeurs d'applications mobile (et c'est presque une "exclusivité" puisque ce bug n'est référencé dans aucune forum, aucune bugbase Adobe).
Diagnostic
Ce bug ce produit uniquement sur les applications mobiles AIR pour Android et AIR pour iOS, selon certaines conditions.
Pour vous présenter rapidement mon application, celle-ci commence par faire des appels à des fichiers XML, puis à des fichiers Perl qui renvoient du XML (en faisant un pont vers Java) et des fichiers image. L'application fonctionnait correctement sur mon HTC Desire sous Android (chez SFR) mais avait des problèmes de connexion sur iPad (chez Bouygues Telecom en 3G). Parfois, l'application "perd la connexion" de manière complètement aléatoire et il faut relancer l'application.
Entre temps, j'ai lâché mon vieil HTC Magic pour un Samsung Galaxy S sous Android 2.2, toujours chez SFR. Pour tester d'autres développements sans devoir attendre la (longue) compilation pour iPad, je décide de compiler un APK pour le transférer sur mon téléphone.
Lancement de l'application en connexion Wifi, aucun problème l'application fonctionne de manière très fluide. Comme je suis un peu loin de ma box Numericable et que le signal Wifi n'est pas très bon, je décide de désactiver le Wifi et de passer en 3G (connexion maximale). Lancement de l'application … le premier chargement s'effectue mais la suite de l'application échoue, comme si les informations que je recevais en XML n'étaient pas les bonnes.
Recherche de la solution
Je décide donc d'aller voir du côté de mon URLLoader. Celui-ci ne renvoyait ni un SecurityErrorEvent, ni un IOErrorEvent mais bien un Event.COMPLETE. Après passage sur la propriété "data" de mon URLLoader censée contenir mon XML, je m'aperçoit que celle-ci est vide.
Après une longue recherche sur le net, je tombe sur un des seuls threads qui parlent d'un problème similaire:
La personne qui a lancé le thread a le même comportement bizarre Wifi / 3G. Celui-ci signale un élément important que je n'avais pas noté, il reçoit un évènement HTTPStatusEvent.HTTP_STATUS avec comme status HTTP 403. Pour ceux qui ne s'en rappellent plus, 403 correspond à un retour serveur Forbidden, la plupart du temps pour un problème de droit d'accès sur un fichier / répertoire. Mais malheureusement, ce thread se termine en queue de poisson car personne n'a trouvé la solution (ils vont être contents de voir ce billet ^^). Je vérifie et je reçoit moi aussi un 403 de la part du serveur.
Comme on dirait que le serveur renvoie un 403, je vais voir logiquement du côté de mon serveur HTTP, Apache en l'occurrence. Un petit tour dans le fichier access.log m'indique qu'aucune trame n'a été reçue! Rien dans les log, aucun code d'erreur HTTP. Je reçois donc un Event.COMPLETE alors que le serveur ne me répond même pas.
Bien inquiété par ce problème (il fallait quand même que je le corrige), je continue mes recherches pendant une petite heure. J'apprends sur certains forums que certains opérateurs téléphoniques renvoient parfois des erreurs HTTP 403 pour protéger leurs systèmes . Cela intervient avec des applications codées avec d'autres langages ou même en navigation mobile classique. Cela correspond bien à mon problème de 3G / Wifi, je continue donc à chercher de ce côté là.
Après de longues recherches, je tombe sur ce forum de BeyondPod for Android Support Forum:
Impossible to update when WiFi is off
Et la lumière vient d'un utilisateur nommé "StefanK" qui nous dit:
This appears to be user agent related issue. SFR does appears to check
the user agent strings and does not allow any connections if the User
Agent is not on the "approved" list.One of BeyondPod users figured that putting this User Agent (without
the >> and <<):>>>Mozilla/5.0 (Linux; U; Android 2.2; fr-fr; Desire_A8181 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1<<<
worked for him on SFR.
You can set the user agent in BeyondPod’s advanced settings: Menu >
More > About BeyondPod > Tap and hold on the line that has the version
number > Advanced Settings > User Agent.Stefan
On dirait que l'on chauffe, le bug est reproduit et en plus chez SFR. Il suffit selon lui de modifier le User-Agent HTTP. Les opérateurs comme SFR doivent vérifier les headers HTTP et interdire les connexions "applicatives" sur les réseaux 3G pour éviter que les PC ne profitent de la connexion 3G d'un portable comme connexion internet (à mon avis).
Je commence à rechercher comment faire cette modification en AS3 dans la documentation et les nouvelles sont plutôt mauvaises, notamment quand je tombe sur la documentation de URLRequestHeader:
In Flash Player and in Adobe AIR content outside of the application security sandbox, the following request headers cannot be used, and the restricted terms are not case-sensitive (for example, Get, get, and GET are all not allowed). Also, hyphenated terms apply if an underscore character is used (for example, both Content-Length and Content_Length are not allowed):
Accept-Charset, Accept-Encoding, Accept-Ranges, Age, Allow, Allowed, Authorization, Charge-To, Connect, Connection, Content-Length, Content-Location, Content-Range, Cookie, Date, Delete, ETag, Expect, Get, Head, Host, If-Modified-Since, Keep-Alive, Last-Modified, Location, Max-Forwards, Options, Origin, Post, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, Public, Put, Range, Referer, Request-Range, Retry-After, Server, TE, Trace, Trailer, Transfer-Encoding, Upgrade, URI, User-Agent, Vary, Via, Warning, WWW-Authenticate, x-flash-version.
Certains trouvent des solutions sur le net en passant par un proxy (un proxy PHP par exemple) qui va modifier les headers HTTP et faire suivre la requête. Ce n'est pas une solution pour moi car cela voudrait dire que je dois modifier tous mes URLLoader et Loader et implémenter un proxy: no way.
La solution
En allant fouiner plus loin dans les documentations Adobe, je trouve que l'on peut en fait modifier le User-Agent HTTP mais seulement dans l'API Adobe AIR:
Cette solution fonctionne et mes XML reviennent correctement. Excellent, mais cela me demande de modifier tous mes Loader et URLLoader et en plus, cela m'oblige à lier certaines de mes librairies au framework AIR alors qu'elles étaient auparavant pures AS3, pas top. La solution ultime vient de la classe URLRequestDefaults:
Cette variable static permet de donner un userAgent par défaut à tous les URLLoader et Loader, exactement ce qu'il me fallait
.
Voici donc la solution à mon problème qui tient en fait en une ligne:
URLRequestDefaults.userAgent = "Mozilla/5.0 (Linux; U; Android 2.2; fr-fr; Desire_A8181 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
Voilà, si votre application marche très bien chez vous mais ne fonctionne pas chez certains utilisateur (qui ne vont pas manquer de vous le signaler dans les commentaires), la solution est peut-être là !
Articles similaires
- Flex / Air – Configurer le Proxy Internet dans une application Adobe Air [Résolu]
- AIR Mobile – Détecter la présence d'une connexion Wifi ou 3G
- AIR pour Android – Debug sur mobile FroYo / emulateur avec Flash Builder 4
- AIR pour Android – Détecter les interfaces réseau (Wifi) avec NetworkInfo et NetworkInterface
- AIR pour Android – Commander des appareils domotiques avec une application Air
Aucun trackbacks pour l'instant






7 janvier 2011
Super !
ça m'a enlevé une belle épine du pied .
Merci encore
7 janvier 2011
Il est tellement vicieux ce bug
Fabien
19 janvier 2011
je ne comprend pas la méthode es que quelqun peut m expliquer etape par etape parce g exactement ce bug c vraiment génant
please
19 janvier 2011
Salut,
il te suffit de mettre ce code à l'initialisation de l'application:
URLRequestDefaults.userAgent = "Mozilla/5.0 (Linux; U; Android 2.2; fr-fr; Desire_A8181 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
C'est écrit dans l'article
Fabien
19 janvier 2011
je vais te praitre stupide mais c'est quelle application et es que apres toute les autres aplication marche en 3g??
19 janvier 2011
g un sonny ericsson xperia x8 et plain d appli ne fonctionne pas en 3g
19 janvier 2011
Salut,
Et bien ton projet mobile est une Application, si tu regarde le MXML principal (MonNomDeProjet.mxml), tu devrais avoir en haut Application ou MobileApplication. Ca c'est ton application. Après, si tu ne sais pas ajouter un évènement pour capter l'initialisation de ton application, je te conseille plutôt de lire le reste des tutoriaux.
Les applications AIR pour Android qui ont ce code fonctionnent ensuite en 3G. Mais si tu télécharges une application AIR sur Android sur le Market qui n'a pas ce code, elle ne fonctionnera pas en 3G (suivant certaines conditions comme expliqué dans l'article).
Fabien
19 janvier 2011
Si ces applications ne sont pas des applications basées sur AIR, le problème ne vient pas de là, voit avec ton opérateur.
Fabien
19 janvier 2011
je ne trouve pas l application projet sur l android market je suis vraiment novice et je ne connait pas tou vos termes
19 janvier 2011
Je pense que votre problème n'a aucun lien avec cet article. Si certaines de vos applications Android ne fonctionne pas en 3G, veuillez contacter votre opérateur.
Merci
Fabien
24 février 2011
Dans le même genre…
Le code ci-dessous fonctionne en flex, mais pas en Air. Quelqu'un a une idée ?
L'erreur renvoyée en AIR est du au serveur de google qui n'accepte pas la requête (enfin c'est ce que je pense)
24 février 2011
Salut,
Où se situe l'erreur? Si il manque du code, envoie le moi par mail (bas de page) pour que je l'intègre
Fabien
24 février 2011
J'ai envoyé le code complet en répponse à la notification.
Sinon, l'erreur se produit sur le sound.load(urlR);
L'event erreur :
[IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2032: Stream Error. URL: http://translate.google.com/translate_tts?tl=FR&q=une%2520phrase%2520de%2520test" errorID=2032]
24 février 2011
Salut,
l'url ne fonctionne pas dans un navigateur chez moi (problème d'encodage?)
Fabien
24 février 2011
Si tu tape cette url ça doit marcher:
http://translate.google.com/translate_tts?tl=FR&q=une phrase de test
24 février 2011
Je pense que cela ne fonctionne pas car ce domaine ne spécifie pas de crossdomain.xml
Fabien
25 février 2011
Pour une application flex ça pourrait se comprendre, mais pour une application AIR pourquoi avoir besoin d'un crossdomain sur le serveur ?
De plus, ce code fonctionne en Flex (exécuté sur un serveur).
12 avril 2011
Hello,
il me semble que j'ai exactement le même problème mais avec des requêtes remoting (AMFPHP) du coup je ne sais pas comment modifier ce fameux userAgent... J'ai bien sûr essayé de modifier URLRequestDefaults.userAgent mais sans succès.
Une idée ?
12 avril 2011
Salut Quentin,
tu as fais la modification au bon moment (avant l'envoi des trames vers AMFPHP)? A part ça, je ne vois pas trop. Regarder sur le serveur les logs d'apache voir s'il a reçu quelque chose ou non.
Fabien
12 avril 2011
Le truc c'est qu’apparemment les appels remoting ne prennent pas en compte les URLRequestDefaults ! Pour l'instant je n'ai pas accès aux logs d'Apache donc je suis un peu coincé.
La suite au prochain épisode !
29 avril 2011
Un énorme merci pour cette explication et cette solution, j'avais le même souci avec mon appli et la soluce marche nickel !
J'aurais bien galéré à résoudre ça tout seul, ça c'est sûr.
Bravo !
29 avril 2011
C'était tellement tordu que j'ai préféré partager la solution
Merci,
Fabien