'ExternalInterface'에 해당되는 글 1건

  1. 2008.09.04 ExternalInterface

ExternalInterface

DEV_FLASH 2008. 9. 4. 16:41 |
예전에 Opera에서 ExternalInterface.call 이 호출이 되지 않는다는 제보를 받고 대강 꽁수처리로 해결을 했던 적이 있었으나 근본적인 대안이 될수가 없어 Opera 브라우저에서도 ExternalInterface를 사용할 수 있는 다른 대안을 회사 랩 동료와 함께 연구를 한적이 있었습니다.

근본적으로 말하면 Opera 브라우저가 NPRuntime 인터페이스를 완벽히 지원한다면 해결이 되지 않을까 싶네요.
브라우저의 근본에 대해 나는 아는 바가 없어 Opera 탓이야! 라고 둘러대지만 사실은 Adobe Flash Player 의 버그일 수도 있구요.
아래 기술한 내용도 임시방편일 뿐 근본적인 솔루션이 될 수 없습니다. 단지 꽁수로 우회해간 방법에 불과 하니까..
아래의 글은 랩웓들에게 공유했던 문서이며, 외부 게시용으로 약간의 수정이 있음을 미리 알립니다.

목차

  1. External API
    • External API
      • ExternalInterface의 요구 사항
      • ExternalInterface의 장점

  2. Opera 브라우저에서의 ExternalInterface
    • Opera 브라우저에서의 ExternalInterface 호출
    • Opera 브라우저에서 ExternalInterface의 호출 성공 조건
      • 예제를 통한 Opera 브라우저에서 ExternalInterface.call 메서드의 실행 결과
    • wmode를 window로 사용할 수 없나?
  3. 해결 방법?
    • Opera 브라우저에서도 ExternalInterface를?
      • 브라우저를 구분하여 처리
      • secodeimeout 함수 이용
    • 마치며...

External API

External API

ActionScript 3.0 External API는 Adobe Flash Player 9가 실행되는 컨테이너 응용프로그램(웹브라우저 또는 Flash Player를 포함하는 데스크탑용-독립 실행형 프로젝터 응용프로그램)과 ActionScript를 통신할 수 있게 하는 API입니다. 예를 들면, ActionScript와 웹브라우저의 JavaScript 또는 컨테이너 응용프로그램 내에 작성한 함수를 서로 호출할 수 있습니다.


"External API의 기능은 ActionScript 3.0의 ExternalInterface 클래스가 제공합니다. Flash Player 8 이전 버전에서는 fscommand() 액션을 사용하여 컨테이너 응용프로그램과 통신을 하였으나, Flash Player 8 버전부터는 ExternalInterface클래스가 fscommand()를 대체하므로, ActionScript와 컨테이너 응용프로그램 내의 API(예를 들어 Javascript)간의 모든 통신에 이 클래스를 사용하는 것이 좋습니다." -- Flash CS3 레퍼런스 - ActoinScript 3.0 Programming > Using External API 에서 인용


ExternalInterface의 요구사항

ExternalInterface 클래스는 다음 경우에만 사용가능합니다.

  • 지원되는 모든 버전의 Internet Explorer for Windows(5.0 이상)
  • Flash Player ActiveX 컨트롤의 인스턴스를 사용하는 컨테이너 응용프로그램
  • NPRuntime인터페이스 를 지원하는 브라우저
    • Firefox 1.0 이상
    • Mozilla 1.7.5 이상
    • Netscape 8.0 이상
    • Safari 1.3 이상

이 외의 모든 경우에는 ExternalInterface.available 의 속성 값은 false 입니다.


ExternalInterface클래스의 장점

  • fscommand() 함수와 함께 사용되는 함수는 물론 모든 JavaScript 함수를 사용할 수 있습니다.
  • 이름과 개수에 상관없이 인수를 전달할 수 있기 때문에 fscommand() 보다 유연성이 뛰어납니다.
  • Boolean, Number, String, Object 등의 다양한 유형의 데이터를 전달 할 수 있습니다.
  • 호출에 대한 값을 바로 ActionScript로 반환 받을 수 있습니다.
  • 컨테이너 응용프로그램에서 ActionScript 내부에 정의한 함수를 호출할 수 있습니다.
  1. ExternalInterface의 호출이 실패되는 경우
    • Flash Player인스턴스를 정의하는 태그인 object 태그의 id 속성 값에 JavaScript의 연산자로 정의된 하이픈(-)이나 다른 연산자 (예: +, *, /, \, . 등) 가 포함되어 있으면 안됩니다.
    • Flash Player인스턴스를 정의하는 태그인 objectembed 태그가 HTML의 form 태그에 중첩이 되어 있으면 ActionScript에서 ExternalInterface가 호출되지 않습니다.


Opera 브라우저에서의 ExternalInterface


Opera 브라우저에서의 ExternalInterface 호출

ActionScript 레퍼런스에서는 ExternalInterface의 오페라 브라우저 지원에 대해 공식적인 언급을 하고 있지 않지만, Flash Player의 콘텐츠를 렌더링 하는 방식을 나타내는 wmode값에 따라 부분적으로 ExternalInterface는 오페라 브라우저를 지원하고 있습니다.


Opera 브라우저에서 ExternalInterface의 호출 성공 조건

ExternalInterface Method wmode User Interaction 유무 호출 성공 여부
ExternalInterface.call window Interaction 있음 성공
  window Interaction 없음 성공
  transparent Interaction 있음 실패
  transparent Interaction 없음 성공
  opaque Interaction 있음 실패
  opaque Interaction 없음 성공
ExternalInterface.addCallback window 해당 없음 성공
  transparent 해당 없음 성공
  opaque 해당 없음 성공



표에서의 User Interaction 이란 마우스로 버튼을 클릭하는 것과 같은 행위를 말합니다.

오페라 브라우저에서 ExternalInterface 클래스 중 call 메서드는 Flash Player의 wmode 값이 transparentopaque 일 때, 마우스 클릭과 같은 인터렉션을 통해 실행을 하게 되면 호출 실패를 하게 됩니다. wmode가 window 일 때에는 정상적으로 호출을 하였고, addCallback 메서드는 wmode의 값과는 무관하게 실행 되었습니다.

예제를 통한 Opera 브라우저에서 ExternalInterface.call 메서드 실행 결과

wmode가 winodw 일 경우에는 ExternalInterface.call 메서드가 실행이 되므로 wmode의 값이 transparentopaque 일 때에만 테스트 하였습니다.

1. HTML 안의 JavaScript 함수// javascript function
function jsFunc(str){
    alert(str);
}


2. wmode는 transparent 또는 opaque이며, 마우스를 클릭하여 ExternalInterface.call()을 실행 할 때import flash.events.MouseEvent;
import flash.external.ExternalInterface;
myBucodeon.addEventListener(MouseEvent.CLICK, onBucodeonClick);
function onBucodeonClick(event:MouseEvent):void{
   trace("hello");                                                    // 실행
    ExternalInterface.call("jsFunc", "hello world");                   // 실패
    trace("hello");                                                   
// 실행
}


3. wmode는 transparent 또는 opaque이며, 인터렉션 없이 ExternalInterface.call()을 실행할 때import flash.external.ExternalInterface;
ExternalInterface.call("jsFunc", "hello world");                // 실행



wmode를 window로 사용할 수 없나?



wmode의 값을 window로만 쓴다면 Flash UI상에서 문제가 발생할 일은 없으나, 네이버가 서비스하는 웹 페이지에 영향을 줄 수 있습니다. 네이버가 서비스하고 있는 페이지들 중에는 화면을 덮는 방식으로 렌더링 하는 플래시 광고 배너도 있고 플래시로 개발된 UI를 덮는 HTML기반의 컴포넌트 UI들이 있기 때문에 window값을 모두 사용하기란 불가능합니다.

웹페이지 내에서 플래시 UI 위로 플로팅 되는 다른 UI들의 예
 

해결 방법?

Opera 브라우저에서도 ExternalInterface를?

오페라 브라우저 또는 Adobe에서 근본적으로 이 문제를 해결하지 않는 한 자유롭게 ExternalInterface 를 사용하는 방법은 불가능 할 것입니다.
근본적인 해결은 될 수 없지만 오페라 브라우저에서 발생하는 오류를 피해갈 수 있는 방법을 제안해 봅니다.
절대적인 솔루션이라고는 보증할 순 없고 상황별로 여러 케이스가 있기 때문에 100% 완벽하다고 할 순 없습니다. 때문에 개발자 분들이 스스로 판단하여 적용해보면 어떨까 합니다.

브라우저를 구분하여 처리

JavaScript의 navigator.appName 속성을 이용하면 현재 사용하고 있는 브라우저의 이름을 알아 올 수 있습니다.

navigator.appName 으로 리턴되는 값
브라우저 navigator.appName
Microsoft Internet Explorer Microsoft Internet Explorer
Netscape Navigator Netscape
FireFox Netscape
Safari Netscape
Opera Opera


ActionScript에서 다음과 같이 스크립트를 작성하면 사용하고 있는 Flash Player내에서 직접 브라우저의 이름을 알아낼 수 있습니다.

AS로 브라우저 이름 알아내기
import flash.external.ExternalInterface;
var browserName:String = ExternalInterface.call("function(){return navigator.appName}");

ExternalInterface.call("function(){alert('"+browserName+"')}");


browserName 을 이용하여 Opera일 조건일 때 실행 코드를 별도로 표기하는 방법이 있습니다.
Opera일 경우에만 getURL 또는 NavigateToURL 을 사용하여 직접 자바스크립트를 호출하여 사용할 수 있습니다.

setTimeout 함수 이용

MouseEvent.CLICK 이벤트 리스너 함수가 ExternalInterface.call 을 실행하는 것이 아닌 setTimeout 을 호출하여 실제 실행할 코드를 간접적으로 호출하는 방식입니다.

setTimeout으로 간접적으로 ExternalInterface.call 실행import flash.external.ExternalInterface;
import flash.events.MouseEvent;

myButton.addEventListener(MouseEvent.CLICK, onButtonClick);

function onButtonClick(event:MouseEvent):void{
      // setTimeout 을 이용해 실행할 코드를 간접적으로 호출합니다.
    setTimeout(myFunction, 1, "hello world");
}

function myFunction():void{
    ExternalInterface.call("jsFunc", arguments[0]);
}



제시한 방법은 아직 완벽하다고 보증할 수 없습니다만, 어느 정도 효과는 있을 것 이라 생각이 됩니다. 하지만 좀더 시간을 가지고 다양한 케이스에 맞춘 검증 작업이 필요하다고 판단합니다. 첫 번째 안과 두 번째 안을 조합하여 사용하는 것이 좀 더 좋지 않을 까 라는 생각이 듭니다.


출처 : http://orochi77.egloos.com/2033569


if(ExternalInterface.available)
    ExternalInterface.call("aaa");
else
   getURL("javascript:aaa()");


Posted by 으니가저아
: