2005年12月31日 星期六

不同swf檔案之SharedObject資料一致性   [+/-]

Ticore's Blog

SharedObject 從 Flash 6 開始支援到現在已經有好幾年的時間了
使用上雖然相當容易
但是很多特性仍然是不清楚
尤其是文件上都沒有寫
以下為個人對於「不同 swf 使用單一 SO 物件時的一致性」的一些心得:
  • 要保持不同 swf 檔案之間 so 物件的一致性
    一定要將舊的 SharedObject Ref. 刪除
    重新呼叫 SharedObject.getLocal(),以更新 so 物件

  • 直接重新指定參考so = SharedObject.getLocal() 是沒有用的
    因為舊的 so 物件不會被回收

  • 丟棄 so 物件可以用 delete 或是指定為 null

  • 單一 swf 內,重複使用 SharedObject.getLocal() 取得相同名稱的so 物件
    假如未將之前取得的 so 物件丟棄
    後續用 SharedObject.getLocal() 取得的so永遠是同一個so物件參考
    (ref. equal) Singleton?

  • 多個 swf 陸續呼叫 SharedObject.getLocal() 取得相同 so 物件之後
    假如都沒有釋放取得的 so 物件,進行指定資料的動作
    在沒有呼叫 flush() 情況下,so 物件並不會立即寫入資料
    而是在 so 釋放時,才將資料寫入
    只有最後一個取得 so 物件的 swf 具有真正寫入 *.sol file 的權力

  • 不違反上一個條件的情況下
    上述情況可以用 SharedObject.flush() 讓資料立即寫入
Read more...

2005年12月26日 星期一

Flash 8 組件的的 Bug   [+/-]

Ticore's Blog

最近又遇到奇怪的Bug
搞了一下午才找到問題..
竟然是這麼的不起眼.....Orz

構成條件:
1. 工作區域包含一自訂組件,而此組件的Class未繼承MovieClip
2. 工作區域有兩個以上UIComponent ComboBox
3. swf發布為Flash 7格式

觸發條件:
以Flash Player 7 or 8 or 8.5撥放
兩個ComboBox各點一下,Flash Player就會卡住了
過一會兒,就會問你是否要終止該Script~~

Read more...

2005年12月18日 星期日

LoadVars 外部資料脫逸   [+/-]

Ticore's Blog

使用LoadVars讀取外部變數資料的時候
外部資料格式通常是以raw data或是&key=value&方式撰寫
假如想要在&key=value&方式中value使用"&"字元
要先把"&"字元跳脫,不然會被當作分隔字元處理
比較統一的做法可以把整個value作escape、URLEncoding的動作
像原本

"台北市&"

資料經過Big5編碼跳脫之後,變成
"%A5x%A5%5F%A5%AB%26"

&area=%A5x%A5%5F%A5%AB%26&
使用的時候就不用擔心"&"字元被當作分隔符號處理
而Flash LoadVars讀取這種資料時
也會自動作unescape的動作
假如使用UTF-8,是正常的
但是假如使用Big-5就會出現問題了
LoadVars無法正常地將Big5編碼跳脫的資料正確還原
以上面的例子來說

"台北市"就會變成"x北市"

這應該是LoadVars.onData函式的問題
可以使用下面的方式覆寫onData
強制讓它作比較正確的unescape動作
System.useCodePage = true;//注意這是在Big5編碼環境下
if (LoadVars.prototype._onData == null) {
 LoadVars.prototype._onData = LoadVars.prototype.onData;
 LoadVars.prototype.onData = function(raw) {
  this._onData(unescape(raw));
 };
}

但是使用舊式的做法loadVariables卻沒有發現這個問題~~
不過那實在太難用了,不用也罷
總歸一句話,能用UTF-8是最好的
否則編碼的問題永遠搞不完
要不是因為那個爛爛的ASP
也不會遇到這麼多問題

更正,應該是LoadVars.decode的問題

if (LoadVars.prototype._decode == null) {
 LoadVars.prototype._decode = LoadVars.prototype.decode;
 LoadVars.prototype.decode = function(raw) {
  this._decode(unescape(raw));
 };
}
Read more...

2005年12月16日 星期五

SharedObject 共用以及存放位置   [+/-]

Ticore's Blog

SharedObject

Usage

SharedObject.getLocal(objectName:String [, localPath:String]) : SharedObject

getLocal有兩個參數,第一個是SO物件名稱,第二個是路徑

SharedObject 物件的存放位置由三個條件決定:

  1. 網域
  2. 區域路徑(local path)
  3. SO物件名稱

實際存放的位置就是 [Flash SO預設資料夾] + 1. + 2. + 3. + ".sol"

  • 網域是沒辦法決定的,這同時也保障了資料不被其它網域swf存取
  • 區域路徑,假如沒有設定的話,就是依照swf所在domain的相對位置來決定。
  • 假如要設定的話也不能夠隨意設定,還是有所限制
    舉例來說,位於www.ticore.idv/flash/so_test.swf的檔案
    它能夠設定的區域路徑就只有以下幾種:

    • "/"
    • "/flash"
    • "/flash/so_test.swf"

    假如同一domain的swf要共用so的話,最簡單的方式就是使用"/"路徑

  • SO物件名稱參數是必要的,決定了.sol檔案的主檔名
  • SharedObject.getLocal("so"); //產生so.sol file
Read more...

2005年12月15日 星期四

Flex 2 WebService + Axis   [+/-]

Ticore's Blog

最近剛好有人問Flex 2.0怎樣使用WebService
於是便嘗試分別使用Flex MXML Tag與AS 3.0的方式建立WebService
不過由於這還在Alpha 1
並不保證以後也是這樣

至於後端WebService
我是使用Java Apache Axis,以JWS的方式建置

連線的時候,要注意Flash Crossdomain Security
請自行參考相關文件,加上crossdomain.xml

嘗試錯誤的過程中~
覺得Flex 2.0 AS 3.0的設計實在有些奇怪
像是webservice.getOperation回傳型別
以及< mx : operation ..... >為什麼是小寫

還有WebService的Operation,都只能夠用getOperation取得
可是文件上明明就有從Operation建構子傳入ws的方式
但是就是無法成功執行動作~~

當然目前最大的問題就是相關文件相當缺乏
我這樣寫法也不知道是不是標準的做法


Flex 2.0 WebService Tag MXML:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2005/mxml" xmlns="*"
 creationComplete="init();">
 <mx:Script>
  <![CDATA[
   
   import mx.rpc.*;
   import mx.rpc.soap.*;
   import mx.rpc.events.*;
   import flash.util.*;
   
   public function init():Void {
    /*/
    trace("ws.endpointURI : " + ws.endpointURI);
    trace("ws.wsdl : " + ws.wsdl);
    trace("ws.port : " + ws.port);
    trace("ws.rootURL : " + ws.rootURL);
    trace("ws.service : " + ws.service);
    trace("ws.useProxy : " + ws.useProxy);
    trace(ws.hasEventListener("load"));
    //*/
   }
   
   public function fault(target:AbstractOperation):Void {
    trace("fault() " + target);
    output.text += result + "\n";
   }
   public function result(target:AbstractOperation):Void {
    trace("result() " + target.result);
    output.text += target.result + "\n";
    for(var i:String in target.result) {
     trace("result[" + i + "] : " + target.result[i]);
     output.text += "result[" + i + "] : " + target.result[i] + "\n";
    }
   }
   public function load():Void {
    trace("wsdl loaded");
    output.text += "wsdl loaded\n";
   }
   
  ]]>
 </mx:Script>
 <mx:WebService id="ws"
   load="load()"
   useProxy="false"
   wsdl="http://localhost:8080/axis/Test.jws?wsdl">
  <mx:operation name="getDate" fault="fault(ws.getOperation('getDate'))"
   result="result(ws.getOperation('getDate'))" />
  <mx:operation name="getObj" fault="fault(ws.getOperation('getObj'))"
   result="result(ws.getOperation('getObj'))" />
 </mx:WebService>
 
 <mx:Canvas width="100%" height="100%">
  <mx:TextArea x="45" y="73" width="321" height="269" id="output"/>
  <mx:Button label="Get Date"
   click="ws.getOperation('getDate').send();"  x="92" y="34" />
  <mx:Button label="Get Obj"
   click="ws.getOperation('getObj').send({aa:1, bb:2});"  x="172" y="34" />
 </mx:Canvas>
</mx:Application>
Flex 2.0 WebService AS 3.0 MXML:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2005/mxml" xmlns="*"
 creationComplete="init();">
 <mx:Script>
  <![CDATA[
   
   import mx.rpc.*;
   import mx.rpc.soap.*;
   import mx.rpc.events.*;
   import flash.util.*;
   
   var wsdl:String = "http://localhost:8080/axis/Test.jws?wsdl";
   var ws:WebService;
   var getDate:AbstractOperation;
   var getObj:AbstractOperation;
   
   
   public function init():Void {
    
    ws = new WebService();
    
    ws.wsdl = wsdl;
    var load:Function = function (evt:Event) {
     trace("wsdl loaded");
     output.text += "wsdl loaded";
    }
    ws.addEventListener("load", load);
    ws.fetchWSDL();
    
    getDate = ws.getOperation("getDate");
    getObj = ws.getOperation("getObj");
    
    /*/
    trace(getDate);
    trace("operation is Operation : " + (getDate is Operation));
    
    trace("operation.resultFormat : " + Operation(getDate).resultFormat);
    trace("operation.targetNamespace : " + Operation(getDate).targetNamespace);
    trace("operation.endpointURI : " + Operation(getDate).endpointURI);
    //*/
    
    
    getDate.addEventListener("fault", fault);
    getDate.addEventListener("result", result);
    getObj.addEventListener("fault", fault);
    getObj.addEventListener("result", result);
    
   }
   
   public function result(evt:ResultEvent):Void {
    trace("result : " + evt.result);
    trace("target : " + evt.target);
    output.text += evt.result + "\n";
    for(var i:String in evt.result) {
     output.text += "result[" + i + "] : " + evt.result[i] + "\n";
     trace("result[" + i + "] : " + evt.result[i] + "\n");
    }
   }
   public function fault(evt:FaultEvent):Void {
    trace("fault");
    output.text += "fault\n";
   }
   
  ]]>
 </mx:Script>
 <mx:Canvas width="100%" height="100%">
  <mx:TextArea x="45" y="73" width="321" height="269" id="output"/>
  <mx:Button label="Get Date" click="getDate.send();" x="78" y="32" />
  <mx:Button label="Get Obj" click="getObj.send({a:1, b:2});" x="154" y="32" />
 </mx:Canvas>
</mx:Application>
Axis JWS:
import java.util.*;
public class Test {
 public String getDate () {
  return new Date().toString();
 }
 public HashMap getObj (HashMap map) {
  Object[] key = map.keySet().toArray();
  for(int i = 0 ; i < key.length ; ++i) {
   System.out.println("map[" + key[i] + "] : " + map.get(key[i]));
  }
  return map;
 }
}
Read more...

2005年12月14日 星期三

Flash 8 Key.onKeyUp Bug   [+/-]

Ticore's Blog

狀況

發布為 Flash 8 swf 格式時,Key class的onKeyUp 事件,遇到同時按下兩個按鍵,無法擷取到第二個放開按鍵的事件

MMUG上的原始文章
同時按多個Key,發佈成8就有問題


敘述 結果
Test 01 分別將含有偵測Key.onKeyUp的swf發布為Flash 7、8格式,以Flash 8 Player執行 發布為Flash 7格式可以成功擷取連續兩次onKeyUp;而Flash 8格式不行 Key.onKeyUp Bug可能與swf格式有關
Test 02 沿用Test 01的兩個key swf,另外撰寫swf loader發布為Flash 7、8格式,分別load Test 01的兩個swf到_level1,以Flash 8 Player執行loader swf進行測試 發布為Flash 7格式的loader無論load哪種格式swf key,都可以成功擷取連續兩次onKeyUp;而Flash 8格式loader則都不行 Key.onKeyUp Bug與程式碼所在的swf格式無絕對關係,而是與最初執行的loader swf格式有關
Test 03 同Test 02,load swf改成load到_level0.anchor MovieClip 同上
Test 04 同Test 02,load swf改成load到_level0 只是要是被load key swf為Flash 7格式的都成功,而被load key swf為Flash 8格式的都失敗 可能是由於load到_level0是完全取代方式所造成
Test 05 將含有偵測Key.onKeyUp的swf發布為Flash 8格式,然後使用UltraEdit直接修改swf signature為ver. 7,以Flash 7、8 Player執行之 均可以成功擷取連續兩次onKeyUp 此Bug與AS Bytecode無關,而是出在Flash 8 Player本身對swf 8的處理方式

 

listener = {};
listener.onKeyDown = function() {
 trace("onKeyDown");
 output.text += "onKeyDown" + new Date() + "\n";
 output.vPosition = output.maxVPosition;
};
listener.onKeyUp = function() {
 trace("onKeyUp");
 output.text += "onKeyUp" + new Date() + "\n";
 output.vPosition = output.maxVPosition;
};
Key.addListener(listener);



改善方式

1.替Flash 8格式的Game swf另外撰寫Flash 7格式的loader swf,當作起始swf,將Game load到_level1以上或者是MovieClip內

2.直接修改swf signature為ver. 7,但是可能會有其它副作用

已經有人寫了一個Class利用setInterval自行偵測onKeyUp事件
Mixmedia Blog Key.onKeyUp bug in flash8

Read more...