使用 ExternalInterface 類別

Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本

ActionScript 與容器應用程式之間的通訊有兩種形式:ActionScript 可以呼叫在容器中定義的程式碼 (如 JavaScript 函數),或是容器中的程式碼可以呼叫已經指定為可以呼叫的 ActionScript 函數。不論是那一種通訊形式,都可以將資訊送達遭到呼叫的程式碼,而且可以將結果傳回給執行呼叫的程式碼。

ExternalInterface 類別中的兩個靜態屬性和兩個靜態方法可以讓通訊更加便利。這些屬性和方法是用來取得外部介面連線的相關資訊、透過 ActionScript 執行容器中的程式碼,以及讓容器可以呼叫 ActionScript 函數。

取得外部容器的相關資訊

ExternalInterface.available 屬性會指出目前的 Flash Player 是否在提供外部介面的容器內。如果可使用外部介面,則此屬性為 true ;否則為 false 。在使用 ExternalInterface 類別提供的其它功能之前,請務必檢查以確定目前的容器可支援外部介面通訊,如下所示:

if (ExternalInterface.available) 
{ 
    // Perform ExternalInterface method calls here. 
}
備註: ExternalInterface.available 屬性會回報目前的容器類型是否支援 ExternalInterface 連線,但不會告訴您目前的瀏覽器是否已啟用 JavaScript。

ExternalInterface.objectID 屬性可讓您判斷 Flash Player 實體的唯一識別名稱 (特別是 Internet Explorer 中 object 標籤的 id 特質,或使用 NPRuntime 介面之瀏覽器中 embed 標籤的 name 特質)。這個唯一 ID 表示瀏覽器中目前的 SWF 文件,而且可以用來建立 SWF 文件的參考,例如,在呼叫容器 HTML 網頁中的 JavaScript 函數時便可以使用。當 Flash Player 容器不是網頁瀏覽器時,此屬性則為 null

透過 ActionScript 呼叫外部程式碼

ExternalInterface.call() 方法可以執行容器應用程式內的程式碼。它至少需要使用一個字串參數,此字串包含容器應用程式內所要呼叫的函數名稱。傳遞給 ExternalInterface.call() 方法的任何其它參數也會一併傳遞給容器,做為函數呼叫的參數。

// calls the external function "addNumbers" 
// passing two parameters, and assigning that function's result 
// to the variable "result" 
var param1:uint = 3; 
var param2:uint = 7; 
var result:uint = ExternalInterface.call("addNumbers", param1, param2);

如果容器是 HTML 網頁,這個方法就會叫用具有指定名稱的 JavaScript 函數,這個名稱必須已經在此 HTML 容納網頁的 script 元素中加以定義。此 JavaScript 函數的傳回值將回傳給 ActionScript。

<script language="JavaScript"> 
    // adds two numbers, and sends the result back to ActionScript 
    function addNumbers(num1, num2) 
    { 
        return (num1 + num2); 
    } 
</script>

如果此容器是其它 ActiveX 容器,這個方法就會讓 Flash Player 的 ActiveX 控制項傳送它的 FlashCall 事件。指定的函數名稱以及任何參數都將由 Flash Player 序列化成一個 XML 字串。此容器可以存取事件物件之 request 屬性中的資訊,並用它來決定如何執行它自己的程式碼。因為要將值傳回 ActionScript,容器程式碼會呼叫 ActiveX 物件的 SetReturnValue() 方法,傳遞結果 (已序列化成 XML 字串) 做為這個方法的參數。如需有關這類通訊所使用之 XML 格式的詳細資訊,請參閱 外部 API 的 XML 格式

不論此容器是網頁瀏覽器或其它 ActiveX 容器,當呼叫失敗或容器方法沒有指定傳回值時,就會傳回 null 。如果容納環境屬於呼叫程式碼無法存取的系統安全執行程序, ExternalInterface.call() 方法也會擲回 SecurityError 例外。您只要在容納環境中為 allowScriptAccess 設定適當的值,就可以解決這個問題。例如,若要變更 HTML 網頁中 allowScriptAccess 的值,您可以編輯 object embed 標籤中的適當特質。

透過容器呼叫 ActionScript 程式碼

容器只能呼叫函數中的 ActionScript 程式碼,而不能呼叫其它的 ActionScript 程式碼。如果要透過容器應用程式呼叫 ActionScript 函數,您必須執行兩項作業:使用 ExternalInterface 類別註冊函數,然後透過容器的程式碼呼叫它。

首先,您必須註冊 ActionScript 函數以表示它已經可以供容器進行呼叫。使用 ExternalInterface.addCallback() 方法,如下所示:

function callMe(name:String):String 
{ 
    return "busy signal"; 
} 
ExternalInterface.addCallback("myFunction", callMe);

addCallback() 方法會採用兩個參數。第一個參數是類型為 String 的函數名稱,讓容器知道這個函數的名稱。第二個參數是實際的 ActionScript 函數,會在容器呼叫已定義的函數名稱時執行。因為這些名稱很容易分辨,即使實際的 ActionScript 函數具有不同的名稱,您也可以指定將由容器使用的函數名稱。這個功能在不知道函數名稱時 (例如指定匿名函數,或者要呼叫的函數是在執行階段才會決定) 特別有用。

在使用 ExternalInterface 類別註冊 ActionScript 函數後,容器實際上就可以呼叫這個函數。執行這項作業的方式依容器的類型而定。例如,在網頁瀏覽器的 JavaScript 程式碼中,會將註冊的函數名稱當做是 Flash Player 瀏覽器物件的方法來呼叫 ActionScript 函數 (也就是說,做為 JavaScript 物件的方法,用來表示 object embed 標籤)。換句話說,就像呼叫本機函數一樣地傳遞參數及傳回結果。

<script language="JavaScript"> 
    // callResult gets the value "busy signal" 
    var callResult = flashObject.myFunction("my name"); 
</script> 
... 
<object id="flashObject"...> 
    ... 
    <embed name="flashObject".../> 
</object>

此外,在呼叫執行於桌面應用程式之 SWF 檔中的 ActionScript 函數時,註冊的函數名稱和任何參數也必須序列化成 XML 格式化字串。之後實際的呼叫作業是使用 XML 字串做為參數,由 ActiveX 控制項的 CallFunction() 方法執行呼叫。如需有關這類通訊所使用之 XML 格式的詳細資訊,請參閱 外部 API 的 XML 格式

不論是使用那一種方式,ActionScript 函數的傳回值都會回傳給容器程式碼。如果呼叫者是瀏覽器中的 JavaScript 程式碼,就會直接傳回值;如果呼叫者是 ActiveX 容器,則將值序列化成 XML 格式化字串。

外部 API 的 XML 格式

ActionScript 與裝載 Shockwave Flash ActiveX 控制項的應用程式之間的通訊是使用特殊的 XML 格式將函數呼叫和值進行編碼。外部 API 使用的 XML 格式分為兩個部分。其中一部分的格式是用來表示函數呼叫,另一部分格式則是用來表示個別的值,這個格式是用於函數中的參數以及函數傳回值。這些函數呼叫的 XML 格式是供 ActionScript 所傳送及接收的呼叫使用。對於來自 ActionScript 的函數呼叫,Flash Player 會將 XML 傳遞給容器;而對於來自容器的呼叫,Flash Player 也會預期容器應用程式將會以這種格式來傳遞 XML 字串。下列 XML 片段將顯示經過 XML 格式化的函數呼叫範例:

<invoke name="functionName" returntype="xml"> 
    <arguments> 
        ... (individual argument values) 
    </arguments> 
</invoke>

根節點是 invoke 節點。它具有兩個特質: name 表示要呼叫的函數名稱,而 returntype 則永遠為 xml 。如果函數呼叫中含有參數, invoke 節點便具有子 arguments 節點,它的子節點會是使用個別值格式 (接下來將會說明) 加以格式化的參數值。

個別值 (包括函數參數和函數傳回值) 會使用包括實際值以外之資料類型資訊的格式化配置。下表將列出 ActionScript 類別以及用來針對該資料類型值進行編碼的 XML 格式:

ActionScript 類別/值

C# 類別/值

格式

註解

null

null

<null/>

Boolean true

bool true

<true/>

Boolean false

bool false

<false/>

String

string

<string>字串值</string>

Number、int、uint

single、double、int、uint

<number>27.5</number> 
<number>-12</number>

Array (可包含各種元素類型)

可包含各種元素類型 (例如 ArrayList 或 object[]) 的集合。

<array> 
    <property id="0"> 
        <number>27.5</number> 
    </property> 
    <property id="1"> 
        <string>Hello there!</string> 
    </property> 
    ... 
</array>

property 節點會定義個別元素,而 id 特質則是從零開始的數值索引。

Object

包含字串索引鍵和物件值的字典,例如包含字串索引鍵的 HashTable

<object> 
    <property id="name"> 
        <string>John Doe</string> 
    </property> 
    <property id="age"> 
        <string>33</string> 
    </property> 
    ... 
</object>

property 節點會定義個別屬性,而 id 特質則是屬性名稱 (字串)。

其它內建或自訂類別

<null/> or  
<object></object>

ActionScript 會將其它物件編碼成 null 或是空白物件。不論是那種方式,都將遺失所有的屬性值。

備註: 本表藉由範例說明與 ActionScript 類別具備同等功能的 C# 類別;然而,可用來與其它程式設計語言進行通訊的外部 API 或是支援 ActiveX 控制項的執行階段,卻不限於 C# 應用程式。

當您使用包含 ActiveX 容器應用程式的外部 API 來建立自己的應用程式時,可能會發現直接撰寫一個 Proxy 以便將原生函數呼叫轉換為序列化 XML 格式會很方便。如需以 C# 撰寫的 Proxy 類別範例,請參閱透視 ExternalInterfaceProxy 類別。