Flash 6 Detection von Carlo Blatz
|
Dieses
Tutorial stammt aus dem Buch "Flash MX und Actionscript professionell
- Fortgeschrittene Workshops aus der Praxis". vielen Dank für die Genehmigung an den Autoren und den Verlag. |
|
Vorwort
Zur Theorie
Kommen wir zum Script
Vorwort![]()
Seit der 3. Version von Flash ist es für Flashentwickler notwendig geworden
die installierte Version des Flashplugins zu überprüfen. Dank dem
Softupdate kann immerhin bei neueren Internet Explorern auch ohne Detection
überprüft werden, ob Flash installiert ist oder nicht.
Wenn man aber von allen Browser wissen möchte, ob Flash 2, Flash 3, Flash 4, Flash 4 mit Printfeature, Flash 4 mit domainübergreifenden Scripten, Flash 5, Flash 5 mit XML-Bugfix oder nun Flash 6 (mit welchen Unterversionen auch immer hier noch folgen werden) installiert ist, muss man sich schon etwas einfallen lassen. Mit Flash 5 kreierte HTML Files können das Softupdate von Flash 5 einleiten, auch wenn Flash 4 bereits installiert ist. Dafür ist die Versionsnummer am Ende des Objecttags zuständig. Spätestens wenn wir das aber verhindern wollen, Flash 4 kompatible Files publizieren oder sogar für mehrere Flashversionen ein File anbieten möchten benötigen wir eine Flashdetection.
Vorweg - eine solche Detection ist nur geeignet, wenn man eine bestimmte Flashpluginversion sicherstellen muss und/oder wenn man die User zur Installation des Flashplugins bewegen möchte. Will man "nur" automatisch erkennen ob und wenn welches Plugin der User installiert hat, ohne Update oder ggf. Installation braucht man eine Javascriptdetection die nicht das Softupdate einleitet.
Flashdetections gibt es schon seit einigen Jahren. Leider funktionieren die meisten nicht so wie gewünscht. Macromedia selbst bietet auf der Homepage und bei Dreamweaver eine Flashdetection an, die auf Javascript basiert - was aber wenn Javascript deaktiviert oder browserseitig nicht verfügbar ist? Moock hat die erste Flash-basierte Flashdetection kreiert, leider funktionierte Sie nicht auf dem Macintosh. Sie hatte auch einen Fehler - um Flash 4 zu erkennen, wurde eine Variable gesetzt und wenn diese Variable erkannt wurde, sollte zur Flash 4 Seite umgeleitet werden. Leider hat Flash 3 einfach die IF-Abfrage ignoriert (weil Flash 3 das noch nicht konnte), die Bedingung aber trotzdem ausgeführt - denn GETURL kannte Flash 3 bereits. Es ist also keineswegs trivial.
Einem Kunden kann man nicht verkaufen, dass man nicht sicher zwischen Flash 3 und Flash 4 unterscheiden kann und schon gar nicht, dass die ganze Detection nicht auf dem Macintosh funktioniert. Also haben wir einige Wochen experimentiert und mit den Entwicklern der "Problemkinder" Kontakt aufgenommen. Gemeinsam haben wir eine Detection entwickelt, die bis Flash 4 nahezu perfekt zwischen NoFlash, Flash 2, Flash 3 und Flash 4 unterscheiden konnte. Bis auf eine Version des Internet Explorers 4.71 (die ein grundsätzliches Problem mit der Plugininitialisierung hatte), haben wir keine Ausfälle gefunden. Mit dem Printfeature und dem neuen Plugin das keine domainübergreifenden Scripte mehr unterstützte, wurde es aber komplizierter. Wir konnten nicht mehr nur mit Versionsbedingten Aktionen überprüfen, sondern mussten auf die (ab Flash 4 Print 4,0,20,0) interne Variable $version zurückgreifen. Diese Variable wird aber nicht von jedem Unix/Linux-Plugin unterstützt. Es gibt also eine Toleranz von durchschnittlich 4% bei denen nicht die Unterversionen eines Plugins erkannt werden können.
Aber die Historie soll ich Euch nicht weiter belasten, endlich können
wir Euch die neuste Version der in Deutschland meist genutztesten Flashdetection
anbieten. Sie unterscheidet zwischen: Flash2, Flash3, Flash4, Flash4 mit Printfeature
(4,0,20,0), Flash5, Flash 5 mit XML Bug-Fix (5,0,40,0), Flash 6 und wenn Ihr
wollt zwischen jeder weiteren Unterversion eines Plugins. Solltet Ihr mit dieser
Detection z.B. nur ein Flash 4 Plugin sicherstellen wollen, linkt Ihr einfach
auch bei allen Resultaten einer späteren Pluginversion zur gewünschten
Flash 4 Seite.
![]()
![]()
![]()
Zur Theorie![]()
Ein Flashfile wird in einem HTML File aufgerufen,
dass nach 10 Sekunden automatisch zur NoFlashSeite weiterleitet (MetaRefresh).
Im Flashfile wird versucht vor dem Ende dieses 10 Sekundencountdowns zur entsprechenden
FlashSeite umzuleiten. Dazu fängt man hinten an und versucht erst Flash
6 zu erkennen, dann Flash 5, dann Flash 4, Flash 3 und Flash 2. Allein diese
Detection funktionierte aber nun nicht auf dem Macintosh sowie auf einigen Windows
NT System nicht. Und wenn sie im Internet Explorer funktionierten, dann doch
meist im Netscape nicht. Damit diese Detection möglichst unsichtbar verläuft,
wurden die meisten Flashdetections auf der minimalen Pixelgröße 18x18
Pixel erstellt. Einige haben das Flashfile sogar noch mit vielen Zeilenumbrüchen
aus der HTMLSeite gerückt, aber eben da liegt das Problem. Die Detection
muss sichtbar sein, damit sie rechtzeitig initialisiert wird und dafür
muss sie auch deutlich größer als 18 Pixel sein.
Es geht sogar noch weiter, es muss etwas dargestellt und gestreamed werden, damit z.B. Macintosh Netscape rechtzeitig das Plugin initialisiert. Wir schalten also als altererstes ein Formtweening. Damit die Detection unsichtbar ist, ist die Hintergrundfarbe des SWFs, die des HTMLs und die Farbe des Formtweenings die gleiche websave Farbe. Das mag sich nach Aberglaube anhören aber es war ein reproduzierbares Phaenomen eine MAC NN Version (an dem wir uns die Zähne ausgebissen haben).
Achtung noch einmal: Diese Detection eignet sich
nur, wenn die richtige Flashversion gefunden und ggf. installiert werden soll.
Will man die User nur trennen also Flashbesitzer dahin, andere dahin, darf man
natürlich nicht das Flashplugin initialisieren, weil sonst das IE-Softupdate
greift. In diesem Fall muss eine Javascriptdetection her. In Macromedia Dreamweaver
4 ist eine gute Javascript Detection enthalten.
![]()
![]()
Kommen wir zum Script
Die
Detection ist zur Sicherheit 200x200 Pixel groß, spielt mit 20 Bildern
pro Sekunde und beginnt mit einem Preloader um sicher zu stellen, dass alle
Sprungziele bereits geladen sind. Danach kommt das besagte kleine Formtweening
in 3 Keyframes von einem Kreis zu einem 4Eck, damit ist sichergestellt, dass
das File streamed und das Plugin initialisiert sein muss. Die eigentliche Detection
ist linear aufgebaut und fängt nun hinten an. Es
ist wichtig, dass alle Detections einige Frames auseinander liegen, weil langsame
System sonst nicht schnell genug reagieren.

$version
Ab Flash 4 mit Printfeature stand die Flash interne Variable $version
mit dem damaligen Rückgabewert: WIN 4,0,20,0 zur Verfügung.
Mittels Substring konnten wir so das fünfte Zeichen extrahieren und wußten
so die Pluginversion. Was viele (auch wir in der letzten Version) nicht berücksichtigten,
war das ein Unix Plugin folgenden Wert zurückliefert: UNIX 4,0,12,0
- das fünfte Zeichen war somit ein Leerzeichen und erste das sechste Zeichen
die Versionnummer.
MAC 5,0,41,0 WIN 5,0,30,0 UNIX 4,0,12,0
Die Zahl hinter dem 1. Komma wäre eine Unterversion (secondHalf) die Macromedia aber bisher in keinem Plugin verwendet hat. Hinter dem 2. Komma steht die jeweilige Release (minorVersion) und hinter dem 3. Komma ggf. noch eine Build. Für eine Detection der bisherigen Flashplugins interessiert uns also pauschal formuliert nur die Zahl hinter dem Leerzeichen (die Versionnummer) und die Zahl hinter dem 2. Komma (die Release). Zur Sicherheit haben wir den Substring mit einem Flash4kompatible gemacht - man hätte sonst auch getVersion() verwenden können. Folgende kleinen Scriptzeilen speichern uns diese Werte in die Variablen version und rel und sind somit der erste Schritt der eigentlich Detection:
for (blankKey =-1; substring(eval("$version"),blankKey,1) ne " "; blankKey++) { }
version = substring(eval("$version"), blankKey+1, 1);
for (comma1=blankKey+1; substring(eval("$version"),comma1,1) ne ","; comma1++) {}
for (comma2=comma1+1; substring(eval("$version"),comma2,1) ne ","; comma2++) {}
rel = substring(eval("$version"), comma2+1, 2);
Flash 6
Wir haben ja bereits festgestellt: Flash ist
abwärtskompatibel. Also beginnen wir mit der Abfrage der höchsten
Plugunversion, da ältere Plugins versionspezifische Befehle (die wir uns
zu nutze machen) noch nicht kennen und somit ignorieren.
Die naheliegenste Abfrage ist eine If-Abfrage. Sie wird ab Flash 4 unterstützt, der Befehl in der Klammer darf also auch nicht unterhalb von Flash 4 Plugins ausgeführt werden, da sonst z.B. von Flash 3 zwar die Abfrage ignoriert wird, der Befehl im Container aber ausgeführt wird. So verwenden wir Call statt GetURL. Bitte auch nicht einfach ein getURL mit einer Variable benutzen. Flash 3 unter MAC öffnet u.U. so noch eine 404-Seite. Call ruft also in einem Frame am Ende des Films den gewünschten GetURL auf und stoppt den Film damit nicht weiter gesucht wird. Das haben viele andere Detections falsch gemacht.
if (version >= 6) {
call("Flash6");
} else {
setInterval( function(){ if(!i){ call("Flash6"); i=true;} }, 100 );
}
Der Else-Befehl testet sicherheitshalber noch einmal unabhängig von der Versionsvariable ob ein Flash 6 Player vorliegt. SetIntervall wird erst ab Flash 6 unterstützt. Ist auch dies nicht möglich spielt Flash weiter zum nächsten Frame.
Flash 5 + Flash 5 XML per $version
Wenn der Wert der Variable version "5"
entspricht, wird die Aktion des Frames "Flash 5" aufgerufen. Noch
einmal: Die Aktion Call gibt es erst seit Flash 4, kommt also ein Flash 2 oder
3 Player kennt er weder die Bedingung If,
noch die Aktion Call
und findet das "play".
if (version == 5 && rel>40) {
call("Flash5xml");
} else if (version == 5) {
call("Flash5");
} else {
play();
}
Flash 5 mit Onclipevent detecten
Auch hier gehen wir auf Nummer sicher, da z.B.
einige Linux/UnixPlugins das $version-Tag nicht besitzen :(. Was eignet sich
da besser als ein OnClipEvent?!
onClipEvent (load) {
_root.gotoAndStop ("Flash5");
}
Hier könnte auch direkt die URL stehen, dann muss ich sie aber fehleranfällig 2x eingeben, weil in der Aktion zuvor ebenfalls die Flash5 URL aufgerufen wird.
Flash 4 Print
Wenn Version auch nicht "5" entspricht,
wird die Flash 4 Print Abfrage startet. Dies
geschieht wieder mit einigen Frames Abstand falls ein Rechner zu schnell ist
und die Aktion des nächsten Frames ausführt bevor das GETURL
von Flash5 ausgeführt ist. Das Flash 4
Plugin mit Printfeature war das erste Plugin mit der Eigenschaft "$version"
es reicht also zu überprüfen ob es diese Eigenschaft gibt.
Die vorhandene Variable version hat im Flash 4 Player nicht den richtigen Wert,
da sie mittels einer For-Schleife erstellt wurde (ab Flash 5).
if (eval("$version") gt "") {
call ("Flash4Print");
} else {
play ();
}
Flash 4 (kann Domainübergreifende Scripte ausführen)
Wenn also weder Flash 5 noch Flash 4 print gefunden
wurde, nutzen wir einfach die Abwärtskompatibilität der Plugins und
starten wiederum einige Frames später einen einfachen CALL des Frames "Flash4".
Dort ist auch nur ein GETURL
der Flash 4 Seite und ein STOP.
call ("Flash4");
Flash 3
Ein Flash 3 Plugin kennt diese Aktion nicht und führt einige Frames später
ein GETURL
in einem Movieclip aus. In diesem Movieclip ist natürlich noch eine Aktion
um die Hauptzeitleiste zu stoppen, damit diese nicht zur Flash 2 Detection gelangt.
Das darf natürlich keine DotSyntax sein sondern guter alter Flash3kompatibler
Telltarget.
getURL("flash3.htm", "_self");
tellTarget ("../") {
stop();
}
stop();
Flash 2
Hat alles davor versagt, bleibt noch ein ganz
normales GetURL auf der Hauptzeitleiste, das sogar der Flash 2 Player versteht
;)
NOFLASH
Die Detection wird natürlich aus einem HTML-File aufgerufen. Hier (wo sonst)
ist auch die NoflashDetection. Wenn es das Flashfile nicht schafft zu einer
anderen URL weiterzuleiten - weil eben kein Flashplugin da ist, das das veranlassen
könnte, leitet die HTML-Datei nach 10 Sekunden weiter zur Noflashseite.
<HTML> <HEAD> <TITLE>Flash Detection in Progress...</TITLE> <META HTTP-EQUIV="Refresh" CONTENT="10;URL=http://www.powerflasher.de/noflash.htm"> <meta name="author" content="Carlo Blatz - http://www.powerflasher.de"> </HEAD>Die 10 hinter Content=" bestimmt die Zeit nach der per HTML umgeleitet wird und die URL dahinter ist der Pfad zu dem eben im Falle "kein Flash ist installiert" umgeleitet wird.
<body bgcolor="#000000" text="#FFFFFF"> <OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" WIDTH=200 HEIGHT=200> <PARAM NAME=movie VALUE="fw6det.swf"> <PARAM NAME=quality VALUE=high> <PARAM NAME=bgcolor VALUE=#000000> <EMBED src="fw6det.swf" quality=high bgcolor=#000000 WIDTH=200 HEIGHT=200 TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"></EMBED> </OBJECT> <center> <FONT FACE="Arial,Helvetica" SIZE="+1"><B><font color="#FFFFFF">Loading...</font></B></FONT> </center> </BODY> </HTML>
Denkt an die Größe - geht nicht unter 50 pixel - wir sind zur Sicherheit
nie unter 200 Pixel.
Übrigens die erste Zahl hinter "Version" im Objecttag (Die Zeile
unter dem Body): "...swflash.cab#version=6,0,0,0" besagt die Softupdateanforderung.
Wenn die Detection also nur Flash 4 als Minimum anfordert, sollte die Zahl auch
nur "#version=4,0,0,0" abfragen. Das Softupdate vom Internetexplorer
würde also aufgehen wenn jemand eine Version unter Flash 4 installiert
hat. Die Zahlen dahinter sind u.a. für die Unterversionen.
Ich hoffe die Logik Detection konnte nachvollzogen werden. Verändern muss man sie ja eigentlich nicht mehr, schaut einfach ins FLA und ändert die URLs wie gewünscht. Wir haben die Detection so seit Jahren im Einsatz und bisher noch keine Beschwerden bekommen. Natürlich ist kein System perfekt zumal es ständig erweitert wird und sich Fehler einschleichen können. Wenn z.B. das Netz besonders langsam ist oder in dieser HTMLDatei noch andere Elemente liegen die lange laden (also nichts weiter reinlegen) dann greift der Refresh. Aber viel sicherer wird man es wohl kaum bekommen.
Vielen Dank an alle die mitgetestet haben und besonders auch an alle die die Entwicklung mitfinanziert haben. Ich bin nicht unfehlbar, vielleicht verändert sich auch etwas, also bitte mailt mir wenn Ihr Verbesserungsvorschläge habt, dann könnt Ihr es hier wieder lesen.