引越しました!

http://blog.mogmet.com/blog-entry-24.html

へアクセスしてください。

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[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 <= 10) {
if (version == 8 || version == 9 || version == 10){
flagSWF9Bit(inputBytes);
}
else if (version <= 7) {
insertFileAttributesTag(inputBytes);
}
updateVersion(inputBytes, 9);
}
this.aByte = inputBytes;
loader.loadBytes(inputBytes);
}
private function isCompressed(bytes:ByteArray):Boolean
{
return bytes[0] == 0x43;
}
private function uncompress(bytes:ByteArray):void
{
var cBytes:ByteArray = new ByteArray();
cBytes.writeBytes(bytes, 8);
bytes.length = 8;
bytes.position = 8;
cBytes.uncompress();
bytes.writeBytes(cBytes);
bytes[0] = 0x46;
cBytes.length = 0;
}
private function getBodyPosition(bytes:ByteArray):uint
{
var result:uint = 0;
result += 3; // FWS/CWS
result += 1; // version(byte)
result += 4; // length(32bit-uint)
var rectNBits:uint = bytes[result] >>> 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 < data.length; i++ ) {
aResult[i] = data[i];
}
this.saveSwf( aResult );
}

/**
* SharedObjectに圧縮SWFを保存する
* @param swf_data 圧縮SWF配列
*/
public function saveSwf ( swf_data:Array ):void
{
var obj = new Object();

if ( this.so ) {
obj = this.so.data;
obj["swf"] = new Array();
obj["swf"] = swf_data;
try {
var str = this.so.flush();
switch (str) {
case SharedObjectFlushStatus.FLUSHED :
trace( "正常にハードディスクに書き込めました。");
break;
case SharedObjectFlushStatus.PENDING :
trace( "ユーザーにSWFを書き込むためのハードディスク書き込み要求を出します。");
this.so.addEventListener(NetStatusEvent.NET_STATUS, this._flushStatus);
break;
}
} catch (e) {
trace( "書き込みに失敗しました。");
}
}
}

/**
* HDD書き込み要求がでた場合のユーザーの選択によって表示メッセージを変える。
* @param event ハードディスク書き込み要求イベント
*/
public function _flushStatus(event:NetStatusEvent):void {
switch (event.info.code) {
case "SharedObject.Flush.Success":
trace( "正常にハードディスクに書き込めました。");
break;
case "SharedObject.Flush.Failed":
trace( "test", "ユーザーの拒否により書き込みに失敗しました。");
break;
}
}

/**
* SharedObjectからByteArray型のSWFを復元する
* @return ByteArray型のSWF
*/
public function getSwf():ByteArray
{
var obj:Object = new Object();
var aByte:ByteArray = new ByteArray();

if ( this.so ) {
obj = this.so.data;
if ( obj["swf"] ) {
for ( var i = 0; i < obj["swf"].length; i++ ) {
aByte[i] = obj["swf"][i];
}
try {
aByte.uncompress();
} catch (e) {
trace( "かいとうえらー");
}
return aByte;
} else {
return null;
}
}
return null;
}

/**
* SharedObjectに外部SWFがあるかどうかをチェックする
* @return 判定結果
*/
public function isSwfExist ():Boolean
{
var so:SharedObject;
var obj:Object = new Object();


if ( this.so ) {
obj = this.so.data;
if ( obj["swf"] != null ) {
return true;
} else {
return false;
}
} else {
return false;
}

}

}

}



こんなかんじでSharedObjectに外部SWFを保存できました。


バイナリで読み込めればなんでもSharedObjectに保存できそうですね。
まいにち食べたい“ごはんのような”クッキーとビスケットの本

コメントの投稿

非公開コメント

スポンサーリンク
FC2カウンター
最新記事
最新コメント
カテゴリ
アマゾンドリンク
検索フォーム
リンク
ブロとも申請フォーム

この人とブロともになる

アクセスランキング
[ジャンルランキング]
コンピュータ
1913位
アクセスランキングを見る>>

[サブジャンルランキング]
未設定
--位
アクセスランキングを見る>>
バックリンク
最新トラックバック
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。