외부 API 예제: 웹 브라우저에서 ActionScript와 JavaScript 간의 통신

Flash Player 9 이상, Adobe AIR 1.0 이상

이 샘플 응용 프로그램은 다른 사람과 채팅이 가능한 인스턴트 메시징 응용 프로그램(응용 프로그램 이름은 Introvert IM)을 사용할 때 웹 브라우저의 ActionScript와 JavaScript 간의 적절한 통신 기법을 보여 줍니다. 외부 API를 사용하여 웹 페이지와 SWF 인터페이스의 HTML 양식 간에 메시지가 전송됩니다. 이 예제에서 보여 주는 기술은 다음과 같습니다.

  • 통신을 설정하기 전에 브라우저가 통신 가능한 상태인지 확인하여 제대로 통신 초기화

  • 컨테이너의 외부 API 지원 여부 확인

  • ActionScript에서 JavaScript 함수 호출, 매개 변수 전달 및 응답으로 값 수신

  • ActionScript 메서드를 JavaScript에서 호출할 수 있는 상태로 만들고 이러한 호출 수행

이 샘플에 대한 응용 프로그램 파일을 가져오려면 www.adobe.com/go/learn_programmingAS3samples_flash_kr 을 참조하십시오. Introvert IM 응용 프로그램 파일은 Samples/IntrovertIM_HTML 폴더에 있습니다. 이 응용 프로그램은 다음과 같은 파일로 구성됩니다.

파일

설명

IntrovertIMApp.fla

또는

IntrovertIMApp.mxml

Flash(FLA) 또는 Flex(MXML) 형식의 기본 응용 프로그램 파일입니다.

com/example/programmingas3/introvertIM/IMManager.as

ActionScript 및 컨테이너 간에 통신을 구축하고 관리하는 클래스입니다.

com/example/programmingas3/introvertIM/IMMessageEvent.as

컨테이너에서 메시지를 수신할 때 IMManager 클래스에서 전달되는 사용자 정의 이벤트 유형입니다.

com/example/programmingas3/introvertIM/IMStatus.as

값이 응용 프로그램에서 선택할 수 있는 다른 "가용성" 상태 값을 나타내는 열거입니다.

html-flash/IntrovertIMApp.html

또는

html-template/index.template.html

Flash 응용 프로그램의 HTML 페이지(html-flash/IntrovertIMApp.html)이거나 Adobe Flex 응용 프로그램의 컨테이너 HTML 페이지(html-template/index.template.html) 작성에 사용된 템플릿입니다. 이 파일에는 응용 프로그램의 컨테이너 부분을 구성하는 모든 JavaScript 함수가 포함되어 있습니다.

ActionScript 브라우저 통신 준비

외부 API는 주로 ActionScript 응용 프로그램이 웹 브라우저와 통신할 수 있도록 허용하는 데 사용됩니다. 외부 API를 사용하면 ActionScript 메서드가 JavaScript에서 작성한 코드를 호출할 수 있으며 그 반대도 마찬가지입니다. 브라우저의 복잡성과 내부에서 페이지를 렌더링하는 방법으로 인해 HTML 페이지의 첫 번째 JavaScript를 실행하기 전에 SWF 문서에서 콜백을 등록하도록 보장할 수 있는 방법은 없습니다. 이러한 이유로 JavaScript에서 SWF 문서의 함수를 호출하기 전에 항상 SWF 문서에서 HTML 페이지를 호출하여 SWF 문서가 연결을 허용할 수 있는 상태임을 알려야 합니다.

예를 들어 IMManager 클래스에서 수행한 몇 가지 단계를 통해 Introvert IM에서 브라우저가 통신할 수 있는 상태인지 확인하고 통신을 위해 SWF 파일을 준비합니다. 브라우저가 통신 가능한 상태인지 확인하는 첫 번째 단계는 다음과 같이 IMManager 생성자에서 이루어집니다.

public function IMManager(initialStatus:IMStatus) 
{ 
    _status = initialStatus; 
 
    // Check if the container is able to use the external API. 
    if (ExternalInterface.available) 
    { 
        try 
        { 
            // This calls the isContainerReady() method, which in turn calls 
            // the container to see if Flash Player has loaded and the container 
            // is ready to receive calls from the SWF. 
            var containerReady:Boolean = isContainerReady(); 
            if (containerReady) 
            { 
                // If the container is ready, register the SWF's functions. 
                setupCallbacks(); 
            } 
            else 
            { 
                // If the container is not ready, set up a Timer to call the 
                // container at 100ms intervals. Once the container responds that 
                // it's ready, the timer will be stopped. 
                var readyTimer:Timer = new Timer(100); 
                readyTimer.addEventListener(TimerEvent.TIMER, timerHandler); 
                readyTimer.start(); 
            } 
        } 
        ... 
    } 
    else 
    { 
        trace("External interface is not available for this container."); 
    } 
}

우선 이 코드는 ExternalInterface.available 속성을 사용하여 현재 컨테이너에서도 외부 API를 사용할 수 있는지 여부를 확인합니다. 가용성 상태인 경우 통신을 설정하는 프로세스가 시작됩니다. 외부 응용 프로그램과 통신을 시도하면 보안 예외 및 기타 오류가 발생할 수 있으므로 이 코드는 try 블록에서 래핑됩니다(편의상 해당 catch 블록은 샘플에서 생략).

그런 다음 이 코드는 여기에 나열된 isContainerReady() 메서드를 호출합니다.

private function isContainerReady():Boolean 
{ 
    var result:Boolean = ExternalInterface.call("isReady"); 
    return result; 
}

이제 isContainerReady() 메서드가 다시 ExternalInterface.call() 메서드를 사용하여 JavaScript 함수 isReady() 를 호출합니다.

<script language="JavaScript"> 
<!-- 
// ------- Private vars ------- 
var jsReady = false; 
... 
// ------- functions called by ActionScript ------- 
// called to check if the page has initialized and JavaScript is available 
function isReady() 
{ 
    return jsReady; 
} 
... 
// called by the onload event of the <body> tag 
function pageInit() 
{ 
    // Record that JavaScript is ready to go. 
    jsReady = true; 
} 
... 
//--> 
</script>

isReady() 함수는 jsReady 변수 값만 반환합니다. 처음에 이 변수는 false 이며, 웹 페이지의 onload 이벤트가 트리거되면 변수 값이 true 로 바뀝니다. 즉, 페이지가 로드되기 전에 ActionScript가 isReady() 함수를 호출하면 JavaScript가 ExternalInterface.call("isReady") false 를 반환하고, 그 결과 ActionScript isContainerReady() 메서드가 false 를 반환합니다. 페이지가 로드되면 JavaScript isReady() 함수가 true 를 반환하므로 ActionScript isContainerReady() 메서드도 true 를 반환합니다.

IMManager 생성자로 돌아가면 컨테이너의 준비 상태에 따라 두 가지 중 하나가 발생합니다. isContainerReady() true 를 반환하면 코드가 setupCallbacks() 메서드만 호출하여 JavaScript와 통신을 설정하는 프로세스를 완료합니다. 그와 반대로 isContainerReady() false 를 반환하면 프로세스는 기본적으로 보류됩니다. Timer 객체가 만들어지고 100밀리초마다 timerHandler() 메서드를 호출하도록 지시됩니다.

private function timerHandler(event:TimerEvent):void 
{ 
    // Check if the container is now ready. 
    var isReady:Boolean = isContainerReady(); 
    if (isReady) 
    { 
        // If the container has become ready, we don't need to check anymore, 
        // so stop the timer. 
        Timer(event.target).stop(); 
        // Set up the ActionScript methods that will be available to be 
        // called by the container. 
        setupCallbacks(); 
    } 
}

timerHandler() 메서드가 호출될 때마다 isContainerReady() 메서드의 결과를 다시 확인합니다. 컨테이너가 초기화되면 이 메서드는 true를 반환합니다. 그런 다음 이 코드는 Timer를 중지하고 setupCallbacks() 메서드를 호출하여 브라우저와의 통신 설정 프로세스를 마칩니다.

JavaScript에 ActionScript 메서드 표시

앞의 예제와 같이, 브라우저가 대기 상태임을 확인한 코드는 setupCallbacks() 메서드를 호출합니다. 이 메서드는 ActionScript를 준비하여 다음과 같이 JavaScript에서 호출을 수신합니다.

private function setupCallbacks():void 
{ 
    // Register the SWF client functions with the container 
    ExternalInterface.addCallback("newMessage", newMessage); 
    ExternalInterface.addCallback("getStatus", getStatus); 
    // Notify the container that the SWF is ready to be called. 
    ExternalInterface.call("setSWFIsReady"); 
}

setCallBacks() 메서드는 ExternalInterface.addCallback() 을 호출하여 JavaScript에서 호출 가능한 두 개의 메서드를 등록함으로써 컨테이너와 통신할 준비를 마칩니다. 이 코드의 첫 번째 매개 변수는 ActionScript의 메서드 이름과 같습니다. 이 메서드는 JavaScript에 이 이름으로 인식됩니다( "newMessage" "getStatus" ). 이 경우 다른 이름을 사용해도 별 다른 장점이 없으므로 간편하게 같은 이름을 다시 사용합니다. 마지막으로 ExternalInterface.call() 메서드를 사용하여 JavaScript 함수 setSWFIsReady() 를 호출합니다. 이 함수는 컨테이너에 ActionScript 함수가 등록되었음을 알려 줍니다.

ActionScript에서 브라우저로 통신

Introvert IM 응용 프로그램은 컨테이너 페이지에서 JavaScript 함수를 호출하는 다양한 예를 보여 줍니다. 가장 간단한 경우( setupCallbacks() 메서드의 예제)는 매개 변수를 전달하거나 반환값을 수신하지 않고 JavaScript 함수 setSWFIsReady() 를 호출하는 것입니다.

ExternalInterface.call("setSWFIsReady");

isContainerReady() 의 다른 예제에서 ActionScript는 isReady() 함수를 호출하고 그 응답으로 부울 값을 수신합니다.

var result:Boolean = ExternalInterface.call("isReady");

외부 API를 사용하여 매개 변수를 JavaScript 함수로 전달할 수도 있습니다. 예를 들어 IMManager 클래스의 sendMessage() 메서드를 생각해 보십시오. 이 메서드는 사용자가 "대화 상대"에게 새 메시지를 보낼 때 호출됩니다.

public function sendMessage(message:String):void 
{ 
    ExternalInterface.call("newMessage", message); 
}

여기에서도 지정된 JavaScript 함수를 호출하고 브라우저에 새 메시지를 알리는 데 ExternalInterface.call() 이 사용됩니다. 뿐만 아니라 메시지 자체가 추가 매개 변수로 ExternalInterface.call() 에 전달되고, 그 결과 JavaScript 함수 newMessage() 에 매개 변수로 전달됩니다.

JavaScript에서 ActionScript 코드 호출

통신은 두 갈래 길이라고 할 수 있으며 Introvert IM 응용 프로그램도 예외는 아닙니다. Flash Player IM 클라이언트만 JavaScript를 호출하여 메시지를 보내는 게 아니라 HTML 양식도 JavaScript 코드를 호출하여 SWF 파일에 메시지를 보내고 SWF 파일에서도 정보를 요구합니다. 예를 들어 SWF 파일이 컨테이너에 연락처 구축이 끝나 통신할 수 있는 상태가 되었음을 알리면 브라우저에서 처음 하는 일은 IMManager 클래스의 getStatus() 메서드를 호출하여 SWF IM 클라이언트에서 첫 사용자의 가용성 상태를 검색하는 것입니다. 웹 페이지에서 updateStatus() 함수로 다음과 같이 수행하면 됩니다.

<script language="JavaScript"> 
... 
function updateStatus() 
{ 
    if (swfReady) 
    { 
        var currentStatus = getSWF("IntrovertIMApp").getStatus(); 
        document.forms["imForm"].status.value = currentStatus; 
    } 
} 
... 
</script>

이 코드는 swfReady 변수의 값을 확인합니다. 이 값은 SWF 파일이 ExternalInterface 클래스로 메서드를 등록했음을 브라우저에 알렸는지 여부를 추적합니다. SWF 파일이 통신을 수신할 수 있는 상태가 되면 다음 줄( var currentStatus = ...)이 IMManager 클래스에서 실제로 getStatus() 메서드를 호출합니다. 코드의 이 줄에서는 다음 세 가지가 발생합니다.

  • getSWF() JavaScript 함수가 호출되어 SWF 파일을 나타내는 JavaScript 객체에 대한 참조를 반환합니다. getSWF() 에 전달된 매개 변수는 HTML 페이지에 둘 이상의 SWF 파일이 있는 경우 브라우저 객체가 반환되는지 여부를 결정합니다. 이 매개 변수에 전달된 값은 SWF 파일을 포함하는 데 사용되는 object 태그의 id 특성 및 embed 태그의 name 특성과 일치해야 합니다.

  • SWF 파일에 대한 참조를 사용하면 getStatus() 메서드가 SWF 객체의 메서드인 것처럼 호출됩니다. 이 경우 함수 이름 " getStatus "가 사용됩니다. ExternalInterface.addCallback() 을 사용하여 ActionScript 함수를 등록할 때 이 이름을 사용합니다.

  • getStatus() ActionScript 메서드는 값을 반환하고 이 값이 currentStatus 변수에 지정됩니다. 그 다음 이 변수는 status 텍스트 필드의 내용( value 속성)으로 지정됩니다.

참고: 코드를 따라 실행하다 보면 updateStatus() 함수에 대한 소스 코드에서 getSWF() 함수를 호출하는 코드 행이 실제로는 var currentStatus = getSWF("${application}").getStatus()로 작성되어 있음을 알 수 있습니다. ${application} 텍스트는 HTML 페이지 템플릿 내의 자리 표시자이며, Adobe Flash Builder에서 응용 프로그램의 실제 HTML 페이지를 생성할 때 이 자리 표시자 텍스트는 object 태그의 id 특성과 embed 태그의 name 특성으로 사용되는 것과 동일한 텍스트(이 예제의 경우 IntrovertIMApp )로 대체됩니다. 이 값은 getSWF() 함수에 필요한 값입니다.

sendMessage() JavaScript 함수는 ActionScript 함수에 매개 변수를 전달하는 방법을 보여 줍니다. sendMessage() 는 HTML 페이지에서 사용자가 [전송] 버튼을 누를 때 호출되는 함수입니다.

<script language="JavaScript"> 
... 
function sendMessage(message) 
{ 
    if (swfReady) 
    { 
        ... 
        getSWF("IntrovertIMApp").newMessage(message); 
    } 
} 
... 
</script>

newMessage() ActionScript 메서드에는 매개 변수가 하나 필요하므로 JavaScript 코드의 newMessage() 메서드를 호출할 때 JavaScript message 변수를 매개 변수로 사용하여 ActionScript에 전달합니다.

브라우저 유형 검색

브라우저마다 내용에 액세스하는 방법이 다르므로, 다음 예제의 getSWF() JavaScript 함수에서 보듯이 항상 JavaScript로 사용자가 실행하고 있는 브라우저가 무엇인지 검색하고 해당 브라우저의 구문에 따라 Window 객체나 Document 객체를 사용하여 동영상에 액세스해야 합니다.

<script language="JavaScript"> 
... 
function getSWF(movieName) 
{ 
    if (navigator.appName.indexOf("Microsoft") != -1) 
    { 
        return window[movieName]; 
    } 
    else 
    { 
        return document[movieName]; 
    } 
} 
... 
</script>

스크립트에서 사용자의 브라우저 종류를 검색하지 않으면 HTML 컨테이너에서 SWF 파일을 재생할 때 예상치 못한 비헤이비어가 표시될 수도 있습니다.