출처: http://blog.naver.com/goodvirus?Redirect=Log&logNo=50002831680

Flash 8에서 ExternalInterface 사용하기

김정헌

Macromedia Korea, User Interface Architect

소개

많은 플래시 웹사이트에서 플래시 자체적으로 해결 할 수 없는 부분들을 서버사이드 프로그램의 도움을 받아서 해결합니다. 서버사이드 프로그램의 도움을 받을려면 플래시에서 Javascript 을 호출을 하거나 Javascript 에서 Flash를 호출하여 Javscript 와 Flash 가 서로 통신을 하여 문제를 해결 하였습니다. Flash mx2004 버전까지는 Flash 에서 getURL() 또는 fscommand()로 Javascript 과 통신 하였고 Javascript 에서는 SetVariable(), callFrame(), callLable() 등을 통해 Flash와 통신을 하였습니다.

Flash 8 에서는 Flash 와 외부 프로그램간에 직접 통신을 가능하게 하는 외부 API(응용 프로그래밍 인터페이스)인 ExternalInterface 클래스가 새로이 추가 되었습니다. 다음에서는 ExternalInterface 클래스에 대해서 자세히 알아보겠습니다.

요구 사항

이 자습 과정을 수행할려면 다음과 같은 소프트웨어와 파일이 필요합니다.

Macromedia Flash Professional 8

자습서 및 샘플 파일


필요한 배경 지식

JavaScript에 대한 사전지식이 필요합니다.

Flash 8 플래이어에 변경된 보안 사항

플래시 플래이어 8 에서는 플래이어 7 버전과 다른 다음과 같은 제한 사항이 있습니다.

  • 로컬 샌드박스

    기본적으로 로컬 SWF는 더 이상 인터넷에 연결하거나, HTTP 통신을 수행하거나 로컬 HTML 파일과 통신할 수 없습니다. SWF 7 이전 버전에서 이와 같은 작업을 수행하려고 시도하면 경고 대화 상자에 해당 작업을 수행할 수 없다는 메시지가 표시됩니다. 이 대화 상자의 모양이나 기존 내용에서 깨진 부분은 최종 사용자나 Flash 개발자가 알맞은 권한을 부여해서 수정할 수 있습니다.

  • 로드 제한 사항

    이제 로컬이 아닌 URL의 SWF 및 HTML 내용에서 로컬 경로의 내용(SWF, HTML, PNG 등)을 로드할 수 없습니다.

  • 타사 저장소

    이제 Flash Player 사용자는 타사 SWF(브라우저의 주소 표시줄에 표시된 도메인과 다른 도메인의 SWF)에서 영구 공유 객체를 읽거나 쓰지 못하도록 선택할 수 있습니다. 이 제한 사항은 기본적으로 적용되지 않으므로 사용자가 적용 여부를 미리 결정해야 합니다.

  • allowScriptAccess 기본값

    SWF 8 이상 버전에서 HTML allowScriptAccess 매개 변수의 기본값은 "always"가 아니라 "sameDomain"입니다. 이것은 SWF 7 이전 버전에는 적용되지 않습니다. allowScriptAccess 매개 변수는 SWF에서 HTML 페이지의 JavaScript를 호출할지 여부를 제어합니다.

위의 4가지 제한 사항 중 Flash – Javascript 의 통신과 관련해서는 allowScriptAccess 부분이 밀접한관계가 있습니다.

allowScriptAccess 의 세팅은 다음과 같습니다.

  • allowScriptAccess가 "never"이면 아웃바운드 스크립팅은 항상 실패합니다. 
  • allowScriptAccess가 "always"이면 아웃바운드 스크립팅은 항상 성공합니다. 
  • allowScriptAccess가 "sameDomain"(버전 8부터 SWF 파일에서 지원)인 경우 SWF 파일이 호스팅하는 웹 페이지와 같은 도메인에 있으면 아웃바운드 스크립팅이 허용됩니다. 
  • HTML 페이지에 allowScriptAccess가 지정되어 있지 않으면 기본값은 버전 8 SWF 파일의 경우 "sameDomain"이고 그 이전 버전의 SWF 파일의 경우 "always"입니다.

따라서 웹에서는 같은 도메인의 경우만 Javascript 함수가 호출 되고 다른 도메인과 로컬에서 테스트 할 시에는 allowScriptAccess = "always" 로 변경을 해 주셔야 합니다.

Flash 에서 HTML 을 Publish 하면 다음과 같은 코드가 생성이 됩니다.

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr" />
<title>allowScriptAccess</title>
</head>
<body bgcolor="#ffffff">
<!--url's used in the movie-->
<!--text used in the movie-->
<!-- saved from url=(0013)about:internet -->
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="550" height="400" id="allowScriptAccess" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="allowScriptAccess.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed src="allowScriptAccess.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="allowScriptAccess" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
</body>
</html>

위의 코드 중 하이라이트한 코드인 allowScriptAccess="sameDomain" 를 allowScriptAccess = "always" 로 변경을 해 주셔야 합니다.

Flash 8 이전 버전에서의 통신방법

플래시 8 이전 버전에서 Falsh – Javascript 간의 통신 방법은 getURL() , fscommand() 를 사용하였고,. Javascript- Flash 간의 통신방법은 SetVariable() 을 사용 했습니다.

getURL

플래시에서 Javascript 를 호출하는 가장 쉬운 방법은 getURL() 을 이용하는 것입니다. 플래시에서 Javaccript 의 callJavascript() 함수롤 호출하는 다음의actinoscript 를 작성합니다.

var msg:String = "'안녕하세요. ^^'";
var callJas:String = 'javascript:callJavascript('+msg+')';
getURL(callJas);

HTML 에서는 <head><body> 사이에 다음과 같이 Javaccript 함수를 작성합니다.

플래시에서 Javscript의 함수 callJavascript 를 호출하고 매개변수로 msg 인 “안녕하세요.^^” 문자열을 보냅니다. 따라서 결과는 다음 그림 1과 같습니다.

<script language="JavaScript">
function callJavascript(str){
alert(str)
}
</script>

플래시에서 JavaScript의 함수 callJavascript 를 호출하고 매개변수로 msg 인 “안녕하세요.^^” 문자열을 보냅니다. 따라서 결과는 다음 그림 1과 같습니다.

alert 창

그림 1. alert 창

getURL() 을 이용한 Javascript 호출은 문법상으로 아주 쉬운 반면 플래시 플래이어가 포함된 브라우저의 환경을 건드려서 gif 에니메이션이 멈추는 현상을 발생 시킵니다.

주의: 로컬에서 테스트 할 때 에는 플래시 플래이어 8의 환경에서는 allowScriptAccess="sameDomain"allowScriptAccess="always" 로 변경 해야 합니다. 또한 전역 보안 설정 패널에서 swf 파일에 대한 접근을 허용하여야 정상적으로 보입니다.

fscommand

fscommand() 는 SWF 파일이 Flash Player나 웹 브라우저 같이 FlashPlayer를 호스팅하는 프로그램과 통신할 수 있도록 합니다. 플래시에서 Javaccript 의 callJavascript() 함수롤 호출하는 다음의actinoscript 를 작성합니다.

var msg:String = "'안녕하세요. ^^'"; var callJas:String = "callJavascript"; fscommand(callJas, msg);

플래시의 Publish Setting 설정(ctrl+shift+ F12) 에서 그림 2와 같이 HTML 탭을 선택하고 Template 에서 Flash with FSCommand 를 선택하고 Publish 합니다.

Publish Setting 설정

그림 2. Publish Setting 설정

Publish 한 HTML 페이지를 보면 다음과 Javascript 가 설정이 되어 있습니다.

<script language="JavaScript">
<!--
var isInternetExplorer = navigator.appName.indexOf("Microsoft") != -1;
// Handle all the FSCommand messages in a Flash movie.
function fscommand_DoFSCommand(command, args) {
var fscommandObj = isInternetExplorer ? document.all.fscommand : document.fscommand;
//
// Place your code here.
//
}
// Hook for Internet Explorer.
if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
document.write('<script language=\"VBScript\"\>\n');
document.write('On Error Resume Next\n');
document.write('Sub fscommand_FSCommand(ByVal command, ByVal args)\n');
document.write(' Call fscommand_DoFSCommand(command, args)\n');
document.write('End Sub\n');
document.write('</script\>\n');
}
//-->
</script>

위의 코드에서 플래시 유저가 다루어야 할 부분은 하이라이트한 코드 부분 중 Place your code here 부분입니다.

즉 함수 안에서 Command 와 args 를 받아서 처리하면 됩니다.

아래는 command 와 args 를 받아서 alert 창을 뛰우는 코드 입니다.

function fscommand_DoFSCommand(command, args) {
var fscommandObj = isInternetExplorer ? document.all.fscommand : document.fscommand;
//
if(command=="callJavascript") {
alert(args)
}
//
}

fscommand 는 VBScript를 이용하여 통신을 하기 때문에 다른 VBScript와 충돌이 날 확률이 있고, 매개변수를 1개만 전달 할 수 있기 때문에 2개 이상의 매개변수를 전달하기 위해서는 Javascript 함수에서 split 를 이용하여 처리 하여야 합니다.

다음의 코드는 2개 이상의 매개변수를 전달 하는 fscommand 의 사용 예 입니다.

플래시에서는 다음과 같은 코드를 작성합니다.

var msg:String = "'안녕하세요. ^^'#반갑습니다.*^^*";
var callJas:String = "callJavascript";
fscommand(callJas, msg);

여기서 # 은 구분자의 역할을 합니다.

Javascript 의 fscommand_DoFSCommand () 코드는 다음과 같습니다.

function fscommand2_DoFSCommand(command, args) {
var fscommand2Obj = isInternetExplorer ? document.all.fscommand2 : document.fscommand2;
//
if(command=="callJavascript") {
arg = args.split("#")
alert(arg[0]+'\n'+arg[1])
}
//
}

위 코드에서 보면 #의 구분자로 문자열을 분리해서 alert 창에 \n 을 이용하여 줄바꿈을 하고 첫번째 인자와 두번째 인자를 줄바꿈 하여 그림 3과 같이 alert 창으로 보여줍니다.

2개의 매개변수의 값을 확인 하는 alert 창

그림 3. 2개의 매개변수의 값을 확인 하는 alert 창

주의: 로컬에서 테스트 할 때 에는 플래시 플래이어 8의 환경에서는 allowScriptAccess="sameDomain"allowScriptAccess="always" 로 변경 해야 합니다.


SetVariable

Javaccript 에서 Flash 와 통신하는 방법은 많은 메쏘드를 통해서 할 수 있지만 그 중에서 SetVariable() 이 가장 많이 쓰입니다. SetVariable()은 Javascript 에서 플래시에서의 정의한 변수의 값을 플래시로 넘겨주는 메쏘드 입니다. 플래시는 변수가 변경이 되면 이벤트를 발생시키는 watch() 메쏘드를 통해서 값이 변경 될 때마다 callback 함수를 호출하여 통신을 합니다.

다음의 코드를 Flash 에 작성합니다.

var testValue:String = "";
// 변수가 변경되면 실행되어질 callback 함수
watchCallback = function (id, oldval, newval):String {
//변경된 값은 newval 을 통해 받습니다.
result_txt.text = newval;
return newval;
};
_root.watch("testValue", watchCallback);

위의 코드는 testValue 라는 값이 변경이 될 때마다 watchCallback 함수를 호출하는 코드입니다. Callback 함수가 호출이 되면 _root 에 있는 result_txt 텍스트에 변경된 값을 보여 줍니다.

다음의 코드는 body 안에 들어가는 코드입니다.

<input type=button value="플래시로 변수 넘기기" onClick="callJavascript()">
<form name="inputValue">
Value <input type="text" name="vars" size="10" >
</form>

HTML 의 인풋텍스트에 입력된 값을 inputValue의 vars 라는 속성으로 저장을 하고 “플래시로 변수 넘기기” 버튼을 클릭하면 callJavascript() 함수를 호출합니다.

다음의 코드는 Javascript 코드입니다.

<script language="JavaScript">
function callJavascript(){
var sendText = inputValue.vars.value
   window.document.setVariable.SetVariable("testValue", sendText);
}
</script>

하이라이트한 부분의 코드를 살펴보면
window.document.FlashID.SetVariable(변수, 값) 의 기본형식에서 callJavascript() 함수는 SetVariable 메쏘드를 통해 testValue 의 값을 sendText 로 보내기 위해 아래와 같은 코드로 작성이 되었습니다.

window.document.setVariable.SetVariable("testValue", sendText);
HTML 에서 Javascript 을 통해서 플래시로 값을 전달

그림 4. HTML 에서 Javascript 을 통해서 플래시로 값을 전달

ExternalInterface class

ExternalInterface class는 ActionScript와 Flash Player 컨테이너(예: JavaScript HTML 페이지 또는 Flash Player를 포함한 데스크톱 응용 프로그램) 사이의 직접 통신을 가능하게 하는 외부API(응용 프로그래밍 인터페이스)입니다.

ExternalInterface의 기능은 fscommand(), CallFrame() 및 CallLabel() 메서드와 비슷하지만 보다 유연하고 보다 일반적인 적용이 가능합니다. JavaScript-ActionScript 통신에는ExternalInterface를 사용하는 것이 좋습니다.

ActionScript에서 HTML 페이지의 모든 JavaScript 함수를 호출하여 모든 데이터 유형의 인수를 수 제한 없이 전달하고 호출에서 반환값을 받을 수 있습니다.

HTML 페이지의 JavaScript에서 Flash Player의 ActionScript 함수를 호출할 수 있습니다. ActionScript 함수는 값을 반환할 수 있고 JavaScript는 호출의 반환값을 즉시 수신합니다. ExternalInterface를 지원하는 브라우저와 운영 체제의 조합은 다음과 같습니다.

브라우저 운영체계
Internet Explorer 5.0 이상 Windows  
Netscape 8.0 이상 Windows Macintosh
Mozilla 1.7.5 이상 Windows Macintosh
Firefox 1.0 이상 Windows Macintosh
Safari 1.3 이상   Macintosh

웹표준이 대두 되고 있는 지금의 시점에서 다양한 브라우저를 지원하는 ExternalInterface class 는 정말 유용한 class 입니다.

ExternalInterface.call()

ExternalInterface.call() 은 Javascript 함수를 호출하고 return 값을 받을 수 있습니다.

이전에 Flash 에서 Javascript 함수를 호출하고 return 값을 SetVariable 을 통해서 받는 것보다 하나의 함수를 호출하여 바로 retrun 값을 받기 때문에 사용자의 입장에서 편해 졌습니다.

가장 기본적인 형태는

ExternalInterface.call(methodName:String, [parameter1:Object])

입니다.

매개변수는 다음과 같은 의미를 지닙니다.

MethodName : 호출할 자바스크립트 함수 입니다.
parameter1 : 매개변수 입니다. 0개 이상의 매개 변수를 쉼표로 구분하여 지정할 수 있습니다


다음의 코드를 Flash 에 작성합니다.

import flash.external.*;
// 호출할 자바스크립트 함수 이름
var callJasFunction:String = "callJavascript";
//매개변수
var msg:String = "안녕하세요. ^^";
//  자바스크립 호출 후 반환되는 값
var returnValue:String = ExternalInterface.call(callJasFunction, msg).toString();
return_txt.text = returnValue;

다음과 같은 JavaScript 코드를 작성합니다.

<script language="JavaScript">
function callJavascript(str) {
alert(str)
return "플래시 8의 새로운 class 인 ExternalInterface.call() 입니다^^."
}
</script>
 

callJavascript 함수가 호출이 되면 alert 창을 뛰우고 확인을 누르는 순간 return 의 값을 플래시로 반환 해 줍니다. 플래시에서는 반환값을 받아서 return_txt 에 표현해줍니다.

Javascript 에서 반환 받은 값을 표현

그림 5. Javascript 에서 반환 받은 값을 표현

주의: 로컬에서 테스트 할 때 에는 플래시 플래이어 8의 환경에서는 allowScriptAccess="sameDomain" 을 allowScriptAccess="always" 로 변경 해야 합니다.

ExternalInterface.addCallback()

ExternalInterface.addCallback() 은 Javascript 에서Flash 의 사용자 정의 함수를 호출할 수 있게 callback 함수를 등록하는 메쏘드 입 니다. 이전의 Javascript 에서는 제한적으로 Flash 의 내장함수만으로 호출 할 수 있었으나 ExternalInterface.addCallback()을 통해서 Flash 에서 정의된 사용자 함수를 직접 호출 하여 사용성이 편리해졌습니다. 또한 여러 개의 매개변수를 넘겨 줄 수 있기 때문에 더 이상 split 으로 쪼개어서 사용하지 않아도 됩니다.

가장 기본적인 형태는

ExternalInterface.addCallback (methodName:String, instance:Object,method:Function)

입니다.

매개변수는 다음과 같은 의미를 지닙니다.

MethodName : JavaScript에서 ActionScript 함수가 호출되는 이름입니다.
instance: 메서드에서 this가 확인하는 객체입니다. 이 객체는 해당 메서드를 찾을 수 있는 객체일 필요는 없으며, 객체 또는 null을 지정할 수 있습니다.
method : JavaScript에서 호출되는 ActionScript 메서드입니다.

다음의 코드를 Flash 에 작성합니다.

import flash.external.*; // 자바스크립에서 호출할 플래시 변수명 var flashFunction:String = "callPlayBall"; var instance:Object = null; // 변수명에 의해 실행되는 콜백함수 var realFunction:Function = playBall; ExternalInterface.addCallback(flashFunction, null, realFunction); function playBall(tgX:Number, tgY:Number, spd:Number):Void { moveMC(ball_mc, tgX, tgY, spd); } // 감속의 움직임 function moveMC(tgMC:MovieClip, tgX:Number, tgY:Number, spd:Number):Void { var mc:MovieClip = tgMC.createEmptyMovieClip("tp_chProp", 98765); mc.onEnterFrame = function() { this._parent._x += spd*(tgX-this._parent._x); this._parent._y += spd*(tgY-this._parent._y); var diffX:Number = Math.abs(tgX-this._parent._x); var diffY:Number = Math.abs(tgY-this._parent._y); if (diffX<0.5 && diffY<0.5) { this._parent._x = tgX; this._parent._y = tgY; this.removeMovieClip(); } }; }

다음과 같은 JavaScript 코드를 작성합니다.

<script language="JavaScript">
function callExternalInterface() {
// FlashID(ExternalInterface_addCallback) 에 있는 callPlayBall 에 등록되어 있는 함수를 를 매개변수 의 값으로 호출 합니다.
getMovieName("ExternalInterface_addCallback").callPlayBall(inputValue.x.value, inputValue.y.value, inputValue.spd.value);
}
// flashID 의 이름을 받아서 브라우저의 속성에 따라 flashID 의 값을 브라우저에 맞게 변경해 주는 함수 입니다.
function getMovieName(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName]
}
else {
return document[movieName]
}
}
</script>

다음의 코드를 HTML 의 body 에 작성합니다.

<!--  버튼을 클릭하면 "callExternalInterface()" 함수를 호출합니다.-->
<input type="button" onClick="callExternalInterface()" value="Call Flash Function" />
</form>
<!—inputValue 에 각각 인풋텍스트에서의 값 x, y, spd 의 변수값을 저장합니다.-->
<form name="inputValue">
Positon X <input type="text" name="x" size="10" >
Position Y <input type="text" name="y" size="10" >
Speed  <input type="text" name="spd" size="10" >
</form>
HTML 에서 x, y의 좌표값과 스피드 값을 플래시의 함수로 넘겨서 공을 움직이는 장면

그림 6. HTML 에서 x, y의 좌표값과 스피드 값을 플래시의 함수로 넘겨서 공을 움직이는 장면

주의: 로컬에서 테스트 할 때 에는 플래시 플래이어 8의 환경에서는 allowScriptAccess="sameDomain" 을 allowScriptAccess="always" 로 변경 해야 합니다.


저자 소개

AND