Categories: ActionScript3.0

[ActionScript3.0]ForcibleLoaderで読み込んだ外部SWFをSharedObjectに保存する

外部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に保存できそうですね。
まいにち食べたい“ごはんのような”クッキーとビスケットの本

mogmet

View Comments

Share
Published by
mogmet