外部SWFをFlashのクッキーである、SharedObjectに保存できるとはおもいもしませんでした。。。
これにより、私の研究のFlashでのオンライン同期も実現することができます。
参考サイト
外部SWFをSharedObjectに保存
[結果]
サンプル – swf_to_so.swf
ソース – swf_to_so.zip
[概要]
ForcbleLoaderで読み込んだByteArrayのものを、インデックスアクセスにて、Array型の配列に格納し、それをSharedObjectに保存する。
[詳細]
参考サイトによると、SharedObjectに保存するために、バイナリ型で読み込んだSWFを配列から1文字ずつ取り出して文字列にして結合しているようだ。
まず、バイナリ型で読み込むには、URLLoaderを使えばいいのだが、AS3からAS1,2で作成されたムービーを読み込んで扱うには、ForcibleLoaderを使わなくてはいけない。
(ForcibleLoaderについてはこちら)
そこで、まず読み込んだ外部SWFをバイナリで扱うために、ForcibleLoaderをちょっと改造した。
ForcibleLoaderは一度バイナリで読み込んだ後、バイナリの値をあちこちをいじっている。
そして、いじったあとを再びLoaderにloadByteさせることで読み込ませているようだ。
そこで、バイナリの値をいじくったあとのバイナリ型SWFを保存させて・・・
後から取り出せるように変えた。
以下がそのソースである。
ForcibleLoader.as (改造Ver)
package { import flash.display.Loader; import flash.net.URLRequest; import flash.net.URLStream; import flash.events.IOErrorEvent; import flash.events.SecurityErrorEvent; import flash.events.Event; import flash.utils.ByteArray; import flash.utils.Endian; import flash.errors.EOFError; import flash.display.LoaderInfo; public class ForcibleLoader { public function ForcibleLoader(loader:Loader) { this.loader = loader; _stream = new URLStream(); _stream.addEventListener(Event.COMPLETE, completeHandler); _stream.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); _stream.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); } private var _loader:Loader; public var _stream:URLStream; private var aByte:ByteArray = new ByteArray(); public function get loader():Loader { return _loader; } public function set loader(value:Loader):void { _loader = value; } public function load(request:URLRequest):void { _stream.load(request); } private function completeHandler(event:Event):void { var inputBytes:ByteArray = new ByteArray(); _stream.readBytes(inputBytes); _stream.close(); inputBytes.endian = Endian.LITTLE_ENDIAN; if (isCompressed(inputBytes)) { uncompress(inputBytes); } var version:uint = uint(inputBytes[3]); if (version >> 3; result += (5 + rectNBits * 4) / 8; // stage(rect) result += 2; result += 1; // frameRate(byte) result += 2; // totalFrames(16bit-uint) return result; } private function findFileAttributesPosition(offset:uint, bytes:ByteArray):uint { bytes.position = offset; try { for (;;) { var byte:uint = bytes.readShort(); var tag:uint = byte >>> 6; if (tag == 69) { return bytes.position - 2; } var length:uint = byte & 0x3f; if (length == 0x3f) { length = bytes.readInt(); } bytes.position += length; } } catch (e:EOFError) { } return NaN; } private function flagSWF9Bit(bytes:ByteArray):void { var pos:uint = findFileAttributesPosition(getBodyPosition(bytes), bytes); if (!isNaN(pos)) { bytes[pos + 2] |= 0x08; } } private function insertFileAttributesTag(bytes:ByteArray):void { var pos:uint = getBodyPosition(bytes); var afterBytes:ByteArray = new ByteArray(); afterBytes.writeBytes(bytes, pos); bytes.length = pos; bytes.position = pos; bytes.writeByte(0x44); bytes.writeByte(0x11); bytes.writeByte(0x08); bytes.writeByte(0x00); bytes.writeByte(0x00); bytes.writeByte(0x00); bytes.writeBytes(afterBytes); afterBytes.length = 0; } private function updateVersion(bytes:ByteArray, version:uint):void { bytes[3] = version; } private function ioErrorHandler(event:IOErrorEvent):void { loader.contentLoaderInfo.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR)); } private function securityErrorHandler(event:SecurityErrorEvent):void { loader.contentLoaderInfo.dispatchEvent(new SecurityErrorEvent(SecurityErrorEvent.SECURITY_ERROR)); } public function getInputBytes():ByteArray { return this.aByte; } } }
これでバイナリ型の外部SWFを扱えるようになった。
今度は、SharedObjectへの保存だが、参考サイトではString型で値をつなげて保存しているようである。
readStrでも使ってるのかな?
しかし、バイナリ型のデータは普通にインデックスアクセスもできる。
インデックスアクセスすると数値がでるので、それをArrayに保存することにした。
このほうが簡単でわかりやすい!
ちなみに、保存する前にcompressかけることによってサイズを小さくしてます(`・ω・´)
そして、保存した配列をSharedObjectに保存!
次にFlashを読み込んだときは、SharedObjectから逆の操作をして復元!
以下にソースを示す。
main.as
package { import com.yahoo.astra.fl.managers.AlertManager; import flash.display.*; import flash.events.*; import flash.net.URLRequest; import flash.system.Security; import ForcibleLoader; public class main extends Sprite { private var fLoader:ForcibleLoader; private var loader:Loader = new Loader(); private var bynarySwf:SwfToBynary; public function main() { var url:String; this.loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _swfComplete); this.bynarySwf = new SwfToBynary( loaderInfo.url ); if ( !this.bynarySwf.isSwfExist() ) { //swf_dataがなければ、ロードする url = "pptest.swf"; AlertManager.createAlert( root, "SharedObjectにSWFがない為読み込みます。" ); this.forceSwfload( url ); } else { //swf_dataがあれば、SharedObjectからロードする AlertManager.createAlert( root, "SharedObjectからSWFを読み込みます。" ); this.loader.loadBytes( this.bynarySwf.getSwf() ); } } /** * AS2Swfの強制読み込み * @param url SWFアドレス */public function forceSwfload( url:String ):void { this.fLoader = new ForcibleLoader(this.loader); this.fLoader.load(new URLRequest( url )); } /** * 外部SWF読み込み完了後処理モジュール * @param event SWFの読み込みが終わった際に出るEvent.COMPLETE */public function _swfComplete(event:Event):void { var mc:MovieClip = new MovieClip(); if ( !this.bynarySwf.isSwfExist() ) { //外部SWFが保存されてぁEかったらSharedObjectに保存する this.bynarySwf.toConvertData( this.fLoader.getInputBytes() ); } mc = event.currentTarget.content as MovieClip; addChild( mc ); } } }
SwfToBynary.as
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.utils.ByteArray; import flash.events.*; import flash.net.SharedObject; import flash.net.SharedObjectFlushStatus; import flash.external.ExternalInterface; import flash.display.Loader; import flash.net.URLLoader; import flash.net.URLRequest; import flash.net.URLLoaderDataFormat; /** * MovieClipをByteArrayに変換してSharedObjectに保存する * @author Mogmet */public class SwfToBynary extends Sprite { private var so:SharedObject; private var byteLaoder:Loader = new Loader(); /** * コンストラクタ * @param url loader.info */public function SwfToBynary ( url:String ) { this.so = SharedObject.getLocal( "swf_data" ); } /** * バイナリ型のMovieClipをintの配列に変える * @param data ByteArray型のMovieClip */public function toConvertData ( data:ByteArray ):void { var aResult:Array = new Array(); var i:int = 0; data.compress(); //データの圧縮 for ( i = 0; i
こんなかんじでSharedObjectに外部SWFを保存できました。
バイナリで読み込めればなんでもSharedObjectに保存できそうですね。
まいにち食べたい“ごはんのような”クッキーとビスケットの本
こんにちは。virapture…
View Comments
I don't think the title of your enticle matches the content lol. Just kidding, mainly because I had some doubts after reading the enticle. https://accounts.binance.com/en/register-person?ref=P9L9FQKY
Can you be more specific about the content of your article? After reading it, I still have some doubts. Hope you can help me.