Displaying articles with tag actionscript

Debugging ActionScript with Firebug

Posted by PunNeng, Tue Apr 15 23:26:00 UTC 2008

ผมทำ flash ก้อนนึง ให้เพื่อนผมอยู่ ตอนทำก็ปกติดี แต่ตอนเอาขึ้นเว็บแล้วต้องทดสอบนี่สิ ไอ้หยาาา!! มัน trace ไม่ได้

เมื่อ trace(); ไม่แสดงผลบน browser จะ debug ยังไง ??

เมื่อก่อนใช้ xRay ก็ ok นะ trace ได้เยอะดี

แต่ตอนนี้ ขี้เกียจติดตั้ง เล่นมันง่ายๆ กับ Firebug นี่แหละ ไม่เคยใช้ ?? เข้านี่เลย -> Firebug

ใน Firebug เราสามารถ print ค่าอะไรบางอย่างได้ด้วย colsole.debug(whatyouwant); ใน JavaScript ยังมี console.log, console.info, console.warn, and console.error อีกด้วย ตอนที่ให้ flash แสดงผล ก็บน browser เช่นกัน !! อะฮ้า จัดการต่อ flash(AS3) ไปยัง JavaScript เสียเลย ได้หน้าตาแบบนี้

  1
  2
  3
  4
function firebug(msg:String):void{
  ExternalInterface.call("console.debug", msg);
}
firebug("what_you_want");

สำหรับ AS2 ก็เหมือนๆ กัน

  1
  2
  3
  4
function firebug(msg:String):void{
  getURL("javascript:console.debug(msg)");
}
firebug("what_you_want");

เฮ้ละ IE(และศัตรูอย่าง Safari/Opera) ไม่มี Firebug!!

โหลด Firebug lite ไปใช้ได้

ปล. ที่ไม่ค่อยได้เขียน blog เพราะทำ flash ให้เพื่อนผมอยู่(เป็นแพะไปซะ วะฮะฮ่า)
ปอ. ผมรัก Firebug

5 comments | Filed Under: General | Tags: actionscript

Flash :: Introduction to ActionScript 3.0

Posted by PunNeng, Sat May 26 04:19:00 UTC 2007

เล็กน้อย สำหรับ ActionScript
ActionScript หรือเรียกย่อๆ ว่า AS เป็น programming language ที่ใช้บน Flash ทำหน้าที่ควบคุมต่างๆ นานา บน flash มันจะทำงานบน ActionScript Virtual Machine(AVM) ซึ่งเป็นส่วนหนึ่งบน flash player มันจะถูก compile เป็น bytecode ที่จะเอาไปใช้ต่อไป นอกจากใช้บน flash ได้แล้ว มันยังใช้บน flex ได้ด้วย ซึ่งการนำไปใช้ มันจะติดไปกับไฟล์ .swf ซึ่งจะถูก flash player เรียกใช้งานอีกทีนึง

มาถึง ActionScript 3.0 บ้าง
ActionScript 3.0 ได้ถูกออกแบบมาให้เป็น Object-Oriented(OO) เต็มตัว ใครที่คุ้นเคยกับ OO อยู่แล้ว ก็จะสบายไป
มาดูว่า AS3 มันทำอะไรได้บ้าง

  • Virtual Machine ตัวใหม่ เรียกว่า AVM2 มีประสิทธิภาพมากกว่าเดิมด้วย bytecode แบบใหม่
  • Compiler ตัวใหม่ ที่ปรับให้เข้ากับมาตรฐานของ ECMAScrpt(ECMA 626) ซึ่งผ่านการปรับปรุงและ optimize ให้ดีขึ้นมากกว่าตัวเก่า
  • ปรับปรุงและเพิ่มเติม application programming interface(API) ด้วยตัวควบคุมระดับต่ำ(low-level - ใกล้เคียงภาษาที่ computer ใช้ประมวลผล ทำให้ประมวลผลเร็วขึ้น) และรูปแบบที่เป็น OO จริงๆ
  • ตัวภาษาหลัก ก็ใช้มาตรฐานของ ECMAScript(ECMA -262) ที่ปรับปรุงครั้งที่ 4 ซึ่งกำลังร่างอยู่(อันบนเป็นการปรับปรุงครั้งที่ 3)
  • XML API ก็ใช้มาตรฐานของ ECMAScript for XML(E4X-ECMA-357 ปรับปรุงครั้งที่ 2) E4X เป็นตัวที่เพิ่มให้ XML เป็น Data type อีกชนิดนึงของ ActionScript(ลองแล้ว ง่ายโคตร)
  • รูปแบบของ Event ใช้มาตรฐานของ Document Object Model(DOM) Level 3

AS3 เหมาะสำหรับงานทีมีความซับซ้อนสูงๆ งานที่ออกแบบด้วย OO หรืองานที่ต้องการที่จะนำกับไปใช้ใหม่(reuseable)

สำหรับสิ่งใหม่ๆ สำหรับ AS3
นอกจากจะเพิ่ม features ใหม่ๆ แล้ว มันยังเปลี่ยนรูปแบบต่างจาก version ก่อน ไม่ว่าจะเป็น syntax หรือรูปแบบของ OO และอื่นๆ อีก
มาดู features ของฝั่งภาษาหลัก
Run-time exceptions
เพิ่มมาแล้ว สามารถดักจับในขณะที่งานเรากำลังเล่นอยู่ ซึ่งใน version ก่อน เราต้องเขียนสั่งเอง ก็ช่วยในการ debug นั่นแล
Run-time types
อันนี้เกี่ยวกับการประกาศ data type ซึ่งใน version ก่อน ตอน compile มันจะ check ให้ เพื่อตรวจสอบการเขียน code ของเราให้ผิดพลาดน้อยที่สุด แต่พอรันแล้ว มันกลายเป็นชนิด dynamic(duck type1) ซึ่งจริงๆ มันก็ถูกแปลงให้เป็น bytecode ของ AS1 อีกที แต่ในตัวใหม่ ไม่เป็นแล้ว ก็ช่วยให้เราใช้หน่อยความจำน้อยลง ทำงานเร็วขึ้น เพราะไม่ต้องไปตรวจสอบอีกที ว่ามันเป็นชนิดอะไร
Sealed classes
sealed class คือ class ที่ไม่สามารถเพิ่ม property และ method ในขณะที่มันกำลังเล่นอยู่ได้ มีส่วนทำให้งานมีประสิทธิภาพมากขึ้น เพราะไม่ต้องเสียหน่วยความจำหรือการประมวลผลไปกับเพิ่มส่วนนี้ ยกเว้น Object class ก็ยังคงทำได้ และถ้าเราไม่ต้องการลักษณะของ sealed class สามารถทำได้โดยประกาศ dynamic หน้า class นั้นๆ
Method Closures
เป็นการสั่งให้ method จำ object ที่ตัวเองอาศัยอยู่ได้ ปัญหามักจะเกิดกับการคุม event อธิบายด้วย code ดีกว่า
มาดูของเก่ากับ AS2

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
import mx.controls.Button;
import mx.utils.Delegate;

function clickHandler(eventObj:Object):Void {
    trace("[" + eventObj.type + "] event on " + eventObj.target + " instance.");
    trace("\t this -> " + this);
}

var buttonListener:Object = new Object();
buttonListener.click = function(eventObj:Object):Void {
    trace("[" + eventObj.type + "] event on " + eventObj.target + " instance.");
    trace("\t this -> " + this);
};

this.createClassObject(Button, "one_button", 10, {label:"One"});
one_button.move(10, 10);
one_button.addEventListener("click", clickHandler);

this.createClassObject(Button, "two_button", 20, {label:"Two"});
two_button.move(120, 10);
two_button.addEventListener("click", buttonListener);

this.createClassObject(Button, "three_button", 30, {label:"Three"});
three_button.move(230, 10);
three_button.addEventListener("click", Delegate.create(this, clickHandler));

เมื่อคลิกที่ one_button จะได้

[click] event on _level0.one_button instance. this -> _level0.one_button

คลิกที่ two_button จะได้

[click] event on _level0.two_button instance. this -> [object Object]

คลิกที่ three_button จะได้

[click] event on _level0.three_button instance. this -> _level0

ในกรณีนี้ this จะเปลี่ยนไป ขึ้นอยู่กับว่ามันอยู่ object ตัวไหน พระเอกเลยเป็นmx.utils.Delegate แทน
แต่ของใหม่ ไม่สามารถสร้าง object ที่จะมารับดัก event ได้ มันจึงเป็นการบังคับ this ไปในตัวว่าต้องเป็นบน object ที่ method ตัวนั้นอยู่เท่านั้น
ECMAScript for XML (E4X)
โม้ไปข้างบนละ

XML API ก็ใช้มาตรฐานของ ECMAScript for XML(E4X-ECMA-357 ปรับปรุงครั้งที่ 2) E4X เป็นตัวที่เพิ่มให้ XML เป็น Data type อีกชนิดนึงของ ActionScript(ลองแล้ว ง่ายโคตร)

เอาเป็นว่าการใช้ xml มันจะง่ายขึ้นเยอะ
Regular expressions
แน่นอน ผมเคยบอกไปแล้ว ว่า AS3 จะใช้ RegExp ได้
Namespaces
นอกจาก xml ในของเก่าแล้ว ของใหม่ก็รองรับเหมือกัน สามารถสร้าง namespace ใช้เองได้
New primitive types มีชนิดของข้อมูลแบบพื้นฐานใหม่ เช่น int หรือ uint ซึ่ง int คือ 32 bit sign interger ส่วน uint คือ 32 bit unsigned integer ใช้ให้ถูกต้องตามลักษณะจะช่วยเพิ่มประสิทธิภาพการทำงานให้ flash player เยอะเลย

มาดู features ของฝั่ง flash player บ้าง โดยส่วนใหญ่จะเป็นเรื่องของ api อันใหม่ เตรียม class ใหม่ๆ ไว้ให้ code เราสั่งมันทางาน
DOM3 event model
ข้างบนก็แว่บๆ มาแล้วทีนึง มันก็เป็นมาตรฐานของ event handling ที่กำหนดโดย World Wide Web Consortium เป็นแนวทางใหม่กับการจัดการเรื่อง event handling ใน flash Display list API
ฝั่งการแสดงผล ก็มีของใหม่มาอีก เช่น Sprite class และ Shape class หรือของเก่าที่มีอยู่แล้วอย่าง MovieClip class ซึ่งความเหมือน หรือแตกต่าง เดี๋ยวมาว่ากันทีหลัง ซึ่งล้วนแต่เพิ่มประสิทธิภาพในการทำงานทั้งสิ้น
Handling dynamic data and content
กลไกใหม่ๆ เพิ่มมาอีกแล้ว อย่างการโหลดของภายนอกอย่างภาพต่างๆ หรือข้อมูลจาก file จะมี Loader class ที่ไว้โหลด .swf หรือภาพต่างๆ ซึ่งจะบอกข้อมูลรายละเอียดต่างๆ ของสิ่งที่เราโหลดเข้ามา ผมว่ามันง่ายดีนะ สำหรับการจัดการพวก preload ทั้งหลาย หรือ URLLoader class ก็จะจัดการกับการโหลด text เข้ามา หรือ Socket class ที่ไว้จัดการกับการต่อ server socket ต่างๆ
Low-level data access
ต่อจากอันบน กับการโหลดสิ่งต่างๆ จากภายนอก มันใช้สิ่งนี้แหละ ในการติดต่อกับข้อมูลระดับต่ำในการเก็บข้อมูลต่างๆ เข้ามา เช่น URLStream class ซึ่ง URLLoader class เอามาทำต่อยอดอีกที ก็ใช้ในการเข้าถึงข้อมูลดิบที่ยังไม่ได้ผ่านการแปลงอะไรเข้ามา หรือ ByteArray class จะใช้ในการจัดการกับ binary data ได้ ไม่ว่าจะอ่านหรือเขียนก็ตาม และของใหม่อย่าง Sound API ที่มีสิ่งที่เพิ่มมาอย่าง SoundChannel และ SoundMixer แค่ชื่อก็น่าเล่นแล้ว และนอกจากนี้ ชุด API ใหม่นี้ ยังจัดการในเรื่องความปลอดภัยในการให้สิทธิ์กับ SWF file หรือการโหลดข้อมูลต่างๆ ซึ่งจะเพิ่มความสามารถด้านความปลอดภัย
Working with text
AS3 แยกการทำงานกับ text ออกมาต่างหากเลย อย่าง TextLineMetrics class, TextField class และอีกต่างๆ นานา รวมถึง Font class ด้วย ที่จะให้เราจัดการเรื่อง font ได้เต็มที่ ผมก็หวังว่ามันคงจะดีนะ(ที่หวัง เพราะยังไม่ได้ลองเลย)

ทีนี้ มาลองดูว่า มันจะเข้าอะไรได้หรือไม่ได้กับ flash ของเก่าบ้าง
สำหรับตัว player ซึ่งตอนนี้คงเป็น version 9 ก็สามารถแสดงผล .swf ที่สร้างจาก version เก่าๆ ได้หมด แต่ของเรา แสดงผลของใหม่ได้ไม่หมดนะ ก็รีบ update กันนะ แต่ก็ใช่ว่าจะเข้ากันได้หมดทุกอย่าง ดังนี้

  • ไม่สามารถเขียน AS1-2 รวมกับ AS3 ได้ - ต้องแยก
  • AS3 โหลด .swf ที่เขียนด้วย AS1-2 ได้ แต่ไม่สามารถเข้าถึง property หรือ method ได้ - ใช้ได้ในการเตรียม asset ต่างๆ อย่างเดียว
  • ในทางตรงกันข้าม .swf ที่เขียนด้วย AS1-2 ไม่สามารถโหลด .swf ที่เขียนด้วย AS3 ได้ - ถ้าสร้างจาก flash8 หรือ Flex Builder 1.5 ละก็ ทำงานร่วมกันไม่ได้เลย มีข้อยกเว้นหน่อย คือ .swf ที่เขียนด้วย as2 สามารถโหลด .swf ที่เขียนด้วย as3 เข้ามาทับตัวมันได้ โดยที่ต้องยังไม่โหลดหรือทำอะไรกับ level ของมัน ซึ่งทำได้โดยใช้ loadMovieNum() method แล้วส่ง 0 ไปเป็น level
  • ถ้าอยากให้มันทำงานร่วมกัน ต้องแปลงของเก่า ไปเป็นของใหม่ครับ ใน help จะมี index บอกอยู่ว่าอะไรที่เปลี่ยนไปบ้าง คงต้องปรับๆ ครับ

จากทั้งหมดที่เล่ามา สรรพคุณที่เห็นกันอย่างเด่นชัดเลยคือประสิทธิภาพในการทำงานของ Flash Player ที่ดีขึ้น เนื่องมาจากการจัดการกับ bytecode ใหม่ ซึ่งต้องสร้างจาก ActionScript 3.0 นอกจากเรื่องประสิทธิภาพแล้ว ยังมีเรื่อง OO ที่ดูเป็นรูปเป็นร่างขึ้นมามากกว่าของเก่า ซึ่งตัวนี้แหละ จะช่วยให้เราจัดการกับงานใหญ่ๆ ได้ดีขึ้น

1duck type คือ เป็นชนิดอะไรก็ได้ ขึ้นอยู่กับการใช้งาน เหมือนเป็ด ทำได้ทุกอย่าง

ปล. thaiflashdev ตายอยู่ ชาว flash ใจเย็นนะครับ :)
ข้อมูลจาก help ของ flash

1 comment | Filed Under: General | Tags: actionscript

AOP :: ActionScript 2.0 on As2lib

Posted by PunNeng, Wed Apr 18 21:58:00 UTC 2007

หลังจากลองบน Ruby ไปแล้ว คราวนี้มาถึงตาของ ActionScript บ้าง(ให้ตายเถอะ นานๆ จะได้มาเล่นอะไรบน Flash คิดถึงจริงๆ)

ฝั่ง Ruby ใช้ตัวช่วยคือ AspectR
ฝั่ง ActionScript 2.0 ใช้ตัวช่วยคือ As2lib

เล็กน้อย สำหรับ As2lib
As2lib เป็น open source framework ตัวนึงที่ถูกออกแบบมาให้ทำงานกับ Flash MX 2004+(หนักไปทาง ActionScript 2.0) โดยมันจะไปช่วยในเรื่อง event handling, error handling, logging, overloading and reflections และยังบรรจุ testing framework,input/output(io) framework, aspect-oriented programming (AOP) framework และ regular expression (RegExp) framework(เป็นอีกหนึ่งอย่างที่ผมจะลอง)

เริ่มต้นด้วยการ download As2lib มาติดตั้งกันก่อน

จากนั้น extract เอา src folder มาใช้ โดยการ copy ไปวางไว้ที่ path เดียวกับ file.fla ที่เราจะใช้งาน แล้วก็สร้าง file.fla มาเลย แล้วไป set classpath ก่อน ไปที่ File > Publish Settings เลือก tab ที่เป็น Flash กดปุ่ม Settings (ข้างๆ ActionScript version dropdown) จากนั้นปุ่ม + บนหน้าต่างที่เด้งขึ้นมา แล้วเพิ่ม ./src เข้าไปแล้วกด ok แล้ว save file นี้ไว้บน path เดียวกับ src folder

มาลง code กันบ้าง เริ่มต้นจาก Product class

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
class Product{
  private var price:Number;
  // private var logger:Logger;
  public function Product(){
    price = 0;
    // logger = new Logger();
  }
  public function setPrice(p:Number):Number{
    // logger.writeLog(price + " is changed to " + p);
    price = p;
    return price;
  }
  public function getPrice():Number{
    return price;
  }
}

save เป็น Product.as ไว้ที่ path เดียวกับ file.fla ของเรา มาดู Logger class บ้าง

  1
  2
  3
  4
  5
  6
  7
  8
  9
class Logger{
  function Logger(){
    // open log file
  }
  public function writeLog(msg:String){
    // write msg to log file
    trace(msg);
  }
}

save เป็น Logger.as ไว้ที่ path เดียวกับ file.fla ของเรา จริงๆ แล้ว flash เขียนต่อ file ไม่ได้ แต่มันเป็นแค่ตัวอย่างครับ จะได้เหมือนกับของ Ruby

บน Product class ถ้าเอา comment ออก ก็จะทำงานได้ตามปกติ โดยไม่ต้องอาศัย aspect

ทีนี้ จะมาลองสร้าง aspect กันบ้าง

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
import org.as2lib.aop.Aspect;
import org.as2lib.aop.aspect.AbstractAspect;
import org.as2lib.aop.advice.AbstractAdvice;
import org.as2lib.aop.JoinPoint;

class LoggingAspect extends AbstractAspect implements Aspect {
  private var logger:Logger;
  function LoggingAspect(){
    logger = new Logger();
    addAdvice(AbstractAdvice.BEFORE, getBeforeOperationsPointcut(), beforeOperationsAdvice);
    // addAdvice(AbstractAdvice.AROUND, getOperationsPointcut(), aroundOperationsAdvice);
  }
  private function getOperationsPointcut(Void):String {
    return "execution(Product.setPrice())";
    // or you can use execution(Product.setPrice()) || execution(Product.getPrice()) instead, 
    // an advice will be operated when setPrice or getPrice are invoked.
  }

  private function beforeOperationsAdvice(joinPoint:JoinPoint, args:FunctionArguments) {

    //trace(joinPoint.getInfo().getDeclaringType().getName() + "." + joinPoint.getInfo().getName() + "(" + args + ")");
    //trace("Before: " + Product(joinPoint.getThis()).getPrice());
    logger.writeLog(Product(joinPoint.getThis()).getPrice() + " is changed to " + args);
  }

  private function aroundOperationsAdvice(joinPoint:JoinPoint, args:FunctionArguments) {
    logger.writeLog(Product(joinPoint.getThis()).getPrice() + " is changed to " + args);
    var result = joinPoint.proceed(args);
    logger.writeLog(tick() + " " + joinPoint.getInfo().getDeclaringType().getName() + "#" + joinPoint.getInfo().getName() + ": returned " + result + " and exited");
    return result;
  }
  private function tick():String{
    return new Date().getFullYear() + "-" + new Date().getMonth() + "-" + new Date().getDate();
  }
}

ที่ comment ใน beforeOperationsAdvice ไว้ จะเป็นวิธีการเอาข้อมูลออกมาใช้งาน ไม่ว่าจะเป็น classname, method name หรือว่า arguments ต่างๆ ที่รับเข้ามา เริ่มต้นที่การ import class ต่างๆ เข้ามาใช้งาน ใน constructor

  1
addAdvice(AbstractAdvice.BEFORE, getOperationsPointcut(), beforeOperationsAdvice);

อันนี้เป็นการ set pointcut โดยการใส่ advice และ join point เข้าไป ที่เหลือก็เป็นการประกาศการทำงาน

จากนั้นมาดูการ weave กันบ้าง

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
import org.as2lib.aop.Aspect;
import org.as2lib.aop.Weaver;
import org.as2lib.aop.weaver.SimpleWeaver;

var logging_aspect = new LoggingAspect();
var weaver:SimpleWeaver = new SimpleWeaver();
weaver.addAspect(logging_aspect, [Product]);
weaver.weave();

var product:Product = new Product();
product.setPrice(7);
product.setPrice(5);

code ตรงนี้ ก็ import library ต่างๆ ที่จำเป็น แล้วมาประกาศการ weave (ถ้ามีหลาย class ให้เพิ่มตรง addAspect เอา เป็น [Product, AnyClass] เป็นต้น) แล้วค่อยมาเป็นการประกาศการทำงานบน class ของเรา ซึ่งจะคล้ายๆ กับของ Ruby แต่จริงๆ ผมชอบแบบ AspectJ มากกว่า ที่ไป weave กันตอน compile เอา(บน Ruby เด๋วมีแบบนี้เหมือนกัน ใจเย็นพี่น้อง)

มาดูผลที่ได้

มาลอง Around บ้าง ก็สลับ comment เป็น

  1
  2
// addAdvice(AbstractAdvice.BEFORE, getBeforeOperationsPointcut(), beforeOperationsAdvice);
addAdvice(AbstractAdvice.AROUND, getOperationsPointcut(), aroundOperationsAdvice);

มาดูผลที่ได้

ข้อมูลจาก www.simonwacker.com (as2lib version ใหม่มันมีปัญหา ถ้าลองตามใน site ของ simon wacker จะรันไม่ออก ลองตามของไอ่เหน่งดีกว่า modify ให้แล้ว)

0 comments | Filed Under: General | Tags: actionscript

Red5 :: SharedObject

Posted by PunNeng, Tue Sep 12 00:28:00 UTC 2006

กลับมาแล้วครับ หลังจากไปซ่อมเว็บอยู่เสียนาน แต่ตอนนี้ก็ยังคงซ่อมอยู่ มีอะไรต้องทำอีกเยอะ เข้าเรื่องกันเลยดีกว่า จากครั้งที่แล้ว ผมได้ค้างไว้ว่าจะมา implement ให้ดู ไปๆ มาๆ ผมขี้เกียจครับ เลยเอาเป็นแบบรวบรัดละกัน ตัวอย่างต่อไปนี้ จะเป็นตัวอย่างการส่งผ่านตัวแปรจาก client ตัวนึง ไปยัง client ทุกๆ ตัว โดยผ่าน SharedObject ซึ่งสามารถนำไปต่อยอดในการทำ game online หรือ chat ได้

อ่า...
เปิด red5 มารันก่อน ใน Start->All Programs->Red5->Red5.exe แล้วเราจะได้หน้าต่าง dos มาหน้านึง

จากนั้นไปที่ flash ของเรา เริ่มด้วยการต่อกับ NetConnection ตามนี้

var my_nc:NetConnection = new NetConnection();
my_nc.connect("rtmp://localhost/SOSample");

ส่วน event ต่างๆ ของ NetConnection สามารถดูได้ที่นี่

โดยตัว service ที่เป็น default มันมีอยู่แล้ว และ SOSample ก็เป็นหนึ่งในนั้น สำหรับการสร้าง service ขึ้นมาใช้เอง ผมแปะไว้ก่อนละกัน(อีกแล้ว มันต้องใช้ eclipse มา build project กันใหม่เลย มันวุ่นวาย เอาไว้ก่อนละกัน) เมื่อรันได้แล้ว ในหน้า dos อันนั้น จะมีข้อความชุดนี้ขึ้น

jvm 1    | [WARN] 1323984 IoWorker-1:( org.red5.server.net.rtmp.RTMPMinaIoHandle
r.warn ) Is tcp delay enabled: false
jvm 1    | [DEBUG] 1323984 IoWorker-1:( org.red5.server.Server.debug ) Check hos
t and path: localhost/SOSample
jvm 1    | [DEBUG] 1323984 IoWorker-1:( org.red5.server.CoreHandler.debug ) Conn
ect to core handler ?
jvm 1    | [DEBUG] 1323984 IoWorker-1:( org.red5.server.adapter.ApplicationAdapt
er.debug ) appConnect: RTMPMinaConnection from 127.0.0.1:1209 to localhost (in:
3312, out: 3073)
jvm 1    | [DEBUG] 1323984 IoWorker-1:( org.red5.server.adapter.ApplicationAdapt
er.debug ) appJoin: Client: 2 >> [WebScope@aae86e Depth = 1, Path = '/default',
Name = 'SOSample']

ในนี้จะเป็น logs ที่บอกรายละเอียดต่างๆ สำหรับ event ที่เข้ามา

ต่อจากนี้ จะเป็นหัวใจสำหรับการใช้งาน ShareObject

เพิ่ม code ต่อจากข้างบนดังนี้

var get_so:SharedObject = SharedObject.getRemote("test",my_nc.uri, true);
get_so.onSync = function() {
  trace(get_so.data.my_text);
};
get_so.connect(my_nc);

บรรทัดแรกก็ประกาศตัวแปร SharedObject ขึ้นมาก่อน ซึ่งเราจะใช้ getRemote คือการเรียกใช้ SharedObject ผ่าน server แล้วบรรทัดต่อมา จะเป็น event ที่ชื่อว่า onSync ซึ่ง event ตัวนี้จะเป็นตัวที่จะถูกเรียกเมื่อได้รับข้อมูลที่ส่งมาจาก server ผมว่าส่วนสำคัญอยู่ที่ตรง onSync ตัวนี้ละครับ เขียนจัดการกับมันให้ดีๆ

เขียนส่วนรับไปแล้ว มาดูส่วนที่ส่งกันบ้าง

_root.onMouseDown = function(){
  var set_so:SharedObject = SharedObject.getRemote("test",my_nc.uri, true);
  set_so.data.my_text = "helloworld";
}

จากน้นก็ประกาศตัวแปร SharedObject มาอีกตัว เพื่อทำการส่งข้อมูล เมื่อ onMouseMove ทำงาน มันจะทำการ set ข้อมูล แต่การเซ็ตนี้สร้างจาก getRemote คือเซ็ตบนฝั่ง server เมื่อเซ็ตแล้ว onSync ของ client แต่ละตัวก็จะทำงาน

ปล. มีปัญหา เปิด help ได้ที่ http://livedocs.macromedia.com/flashcom/mx2004 ปอ. ในความเป็นจริง ยังสามารถใช้ library ของ red5 เองได้ด้วย เข้าไปได้ดูไ้ด้ที่นี่

แก้ไขล่าสุด วันที่ 13 กรกฏาคม 2550 เวลา 23.23 น.

0 comments | Filed Under: General | Tags: actionscript

Testing your Web Services on Flash

Posted by PunNeng, Sun Dec 18 15:17:00 UTC 2005

Note:ผมติ๊งต่างว่าที่เข้ามาอ่านเรื่องอันนี้ มีความเข้าใจและรู้จัก Web Services ดีแล้วนะครับ

เรื่องอันนี้ทำไว้ในTFDมานานแล้ว เอามาให้ดูใหม่ ==' เนื่องจากงม AJAX อยู่ ช่วงนี้อาจจะเอาของเก่าๆ มา recycle เล่าใหม่ไปพลางๆ ก่อน

มาเริ่มกันที่ตัวอย่าง

มาดูว่าจะทำ WS บน FlashMX 2004 Pro1 ต้องรู้จักอะไรบ้าง

WSDL

เป็นตัวกำหนด state ของ WS ถูกสร้างเป็น XML ดูตัวอย่างได้ที่ http://www.webservicex.net/ConvertWeight.asmx?WSDL //WSDL ตัวนี้ผมใช้เป็น tutorial ด้วยคับ จะเป็นตัวบอก URL ของ WS ที่เราเก็บไว้ จะได้ไปเรียกใช้ถูก บอก function ที่มีอยู่ใน WS รวมถึง parameter และค่า return ของ function ด้วย ส่วนตัว source การทำงานจิงๆ เราก็เก็บไว้ใน host ที่ support กับ WS ของเรา

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
- <wsdl:port name="ConvertWeightsSoap" binding="tns:ConvertWeightsSoap">
    <soap:address location="http://www.webservicex.net/ConvertWeight.asmx" /> 
  </wsdl:port><br />
- <wsdl:port name="ConvertWeightsHttpGet" binding="tns:ConvertWeightsHttpGet">
    <http:address location="http://www.webservicex.net/ConvertWeight.asmx" /> 
  </wsdl:port>
- <wsdl:port name="ConvertWeightsHttpPost" binding="tns:ConvertWeightsHttpPost">
  <http:address location="http://www.webservicex.net/ConvertWeight.asmx" /> 
    </wsdl:port>
  </wsdl:service>

WS ConvertWeight ไปเรียกที่ URL"http://www.webservicex.net/ConvertWeight.asmx"

  1
  2
  3
  4
  5
  6
  7
  8
  9
-<s:element name="ConvertWeight">
  -<s:complexType>
    - <s:sequence>
      <s:element minOccurs="1″ maxOccurs="1″ name="Weight" type="s:double" /> 
      <s:element minOccurs="1″ maxOccurs="1″ name="FromUnit" type="s0:WeightUnit" /> 
      <s:element minOccurs="1″ maxOccurs="1″ name="ToUnit" type="s0:WeightUnit" /> 
    </s:sequence>
  </s:complexType>
</s:element>

มี function ชื่อ "ConvertWeight" รับ parameter 3 ตัว เป็น String:Weight,String:FromUnit,String:ToUnit ความหมายมันตรงตัวนะคับ คงไม่ต้องอธิบาย

  1
  2
  3
  4
  5
  6
  7
  8
-<s:element name="ConvertWeightResponse">
  -<s:complexType>
    - <s:sequence>
      <s:element minOccurs="1″ maxOccurs="1″ name="ConvertWeightResult" type="s:double" /> 
    </s:sequence>
  </s:complexType>
</s:element>
<s:element name="double" type="s:double" />

return ค่ากลับมาเป็น String:double

WebserviceConnector

Property หลักๆ ครับ WSDLURL เป็นตัวเก็บ WSDL ตัวอย่าง http://www.webservicex.net/ConvertWeight.asmx?WSDL operation เป็นตัวบอกว่า WS ของเรามี function อะไรบ้าง ที่ใช้หลักๆ ก็มีอยู่แค่นี้ suppressInvalidCalls ถ้าเป็น true เมื่อมีการทำงานผิดพลาดให้หยุดการเรียก WS ส่วนอีกตัว ไม่ขอกล่าวถึงนะครับ(เพราะยังไม่ได้ลอง) ถ้าอยากรู้ก็ลองเปิด help ดูละกัน

ยังมี property อื่นๆ อีกคับที่ต้องสั่งจาก AS คือ WebserviceConnetor.send อันนี้ต้องใช้ร่วมกับ WebserviceConnetor.param ในกรณีที่ function ของเรามีการรับ parameter ตัวอย่างครับ

  1
  2
  3
  4
  5
var wsc:Object = new Object();
var sendFunction = function (sendEnv) {
   sendEnv.target.params = [newParam_txt.text];
}; 
wsc.addEventListener('send', sendFunction);

WebserviceConnetor.result อันนี้ใช้เมื่อ function มีการ return ค่ากลับมา ตัวอย่างครับ

  1
  2
  3
  4
  5
var wsc:Object = new Object();
wsc.result = function(evt:Object) {
    _root.resultW.text = evt.target.results;
};
wsc.addEventListener('result', wscr);

WebserviceConnector.trigger(); ไว้สั่งให้ WS ทำงาน ตัวอย่างครับ//ตัวอย่างนี้เป็นตัวอย่างที่ไม่ได้เรียกใช้ WebserviceConnetor ใส่ code เอาดุ้นๆ เลย

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
import mx.data.components.WebServiceConnector;
var res:Function = function (evt:Object) {
    trace(evt.target.results);
};
var wsConn:WebServiceConnector = new WebServiceConnector();
wsConn.addEventListener('result', res);//สั่งให้รับค่า return 
//wsdl url
wsConn.WSDLURL='http://www.flash-mx.com/mm/tips/tips.cfc?wsdl';
wsConn.operation = 'getTipByProduct';//เลือก function
wsConn.params = ['Flash'];//ใส่ paremeter
//เมื่อมีการทำงานผิดพลาดให้หยุดการเรียก WS
wsConn.suppressInvalidCalls = true;
wsConn.trigger();//สั่งให้ทำงาน

ยังมองไม่เห็นกัน มาดู tutorial กันดีกว่า //เวลาทำต้อง ออนไลน์ด้วย เพราะเอาของจริงมาใช้ หนึ่ง. เปิด WebserviceConnector แล้ว config ตามรูป แล้วจัด form ตามต้องการ ตั้งชื่อ WebserviceConnector ว่า Convert zoom ตั้งชื่อ textbox ด้วยนะ ตัวบนสุดชื่อ weight ตัวล่างสุดชื่อ resultW ส่วนเจ้า ComboBox สองตัวนี้เป็น Component ครับ เลือกที่หน้าต่าง Component หรือกด Ctrl+F7 ตัวบนตั้งชื่อว่า funit ตัวล่างตั้งชื่อว่า tunit สอง. ใส่ค่าให้ ComboBox จิ้มที่ตัว ComboBox แล้วเลือกที่ property labels ดังรูป zoom จิ้มเครื่องหมาย + แล้วใส่ค่าจาก "xxxx" เช่นตัวแรกคือ Grains ใส่ตามนี้คับ มีทั้งหมด 20 ค่า//ต้องดูจาก WSDL

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
-<s:simpleType name='WeightUnit'>
  - <s:restriction base='s:string' >
    <s:enumeration value='Grains' /> 
    <s:enumeration value='Scruples' /> 
    <s:enumeration value='Carats' /> 
    <s:enumeration value='Grams' /> 
    <s:enumeration value='Pennyweight' /> 
    <s:enumeration value='DramAvoir' /> 
    <s:enumeration value='DramApoth' /> 
    <s:enumeration value='OuncesAvoir' /> 
    <s:enumeration value='OuncesTroyApoth' /> 
    <s:enumeration value='Poundals' /> 
    <s:enumeration value='PoundsTroy' /> 
    <s:enumeration value='PoundsAvoir' /> 
    <s:enumeration value='Kilograms' /> 
    <s:enumeration value='Stones' /> 
    <s:enumeration value='QuarterUS' /> 
    <s:enumeration value='Slugs' /> 
    <s:enumeration value='weight100UScwt' /> 
    <s:enumeration value='ShortTons' /> 
    <s:enumeration value='MetricTonsTonne' /> 
    <s:enumeration value='LongTons' /> 
  </s:restriction>
</s:simpleType>

ใส่ใน ComboBox ทั้ง 2 ตัวเลยนะครับ
สาม. ใส่ Code ที่ปุ่ม Convert ดังนี้

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
on(click){//พอดีผมใช้ Component ครับ ถ้าสร้างปุ่ม ก็ใช้ตามปกติ on(release)
    var wscListener:Object = new Object();
    wscListener.result = function(evt:Object) {
        //ให้ TextBox แสดงค่า
        _root.resultW.text = evt.target.results;
    };
    var wscP:Object = new Object();
    wscP.send = function(evt:Object){//ใส่ parameter
        _root.Convert.params = [_root.weight.text, _root.funit.text,_root.tunit.text];
    }
    //สั่งให้ส่ง parameter
    _root.Convert.addEventListener('send',wscP);
    //สั่งให้รับ return
    _root.Convert.addEventListener('result', wscListener);
    _root.Convert.trigger();
}

เป็นการเสร็จสิ้น อันนี้เป็น WS ที่มีคนทำไว้แล้ว ทำจาก .net เลยหา host ที่รองรับง่าย ส่วนตัวที่ผมทำไว้ ผมทำจาก java หา host ที่รองรับยังไม่ได้คับ ที่ทำไว้ทำเป็น localhost ใช้ application server เป็น jboss3.2.5

1 Flash ต้องเป็น professional version เท่านั้น

แก้ไขล่าสุด วันที่ 29 มิถุนายน 2550 เวลา 4.16 น.

0 comments | Filed Under: General | Tags: actionscript

codegent: we're hiring