與其他 Flash Player 和 AIR 實體進行通訊

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

LocalConnection 類別可讓 Adobe® AIR® 應用程式彼此通訊,以及讓瀏覽器中執行的 SWF 內容彼此通訊。您亦可使用 LocalConnection 類別,在 AIR 應用程式與瀏覽器中執行的 SWF 內容之間進行通訊。LocalConnection 可以讓您建立各種可以在多個 Flash Player 和 AIR 實體之間共享資料的多功能應用程式。

關於 LocalConnection 類別

LocalConnection 類別可以讓您開發不需要使用 fscommand() 方法或 JavaScript 就可以相互傳送指令的 SWF 檔。LocalConnection 物件只可以讓在相同用戶端電腦上執行的 SWF 檔間彼此通訊,但這些檔案可以在不同的應用程式中執行。例如,在瀏覽器中執行的 SWF 檔與在放映檔中執行的 SWF 檔可以共享資訊,放映檔會維護本機資訊,而在瀏覽器中執行的 SWF 檔則採用遠端連線的方式與其共享資訊 (放映檔是一種 SWF 檔,其儲存格式可允許做為獨立應用程式執行,也就是說,不需要先安裝 Flash Player 就可以執行,因為它已經內嵌於可執行檔內)。

不同的 ActionScript 版本可以使用 LocalConnection 物件在不同的 SWF 檔之間進行通訊:

  • ActionScript 3.0 的 LocalConnection 物件可以與 ActionScript 1.0 或 2.0 所建立的 LocalConnection 物件通訊。

  • ActionScript 1.0 或 2.0 的 LocalConnection 物件可以與 ActionScript 3.0 所建立的 LocalConnection 物件通訊。

Flash Player 會在不同版本的 LocalConnection 物件之間,自動處理這項通訊。

使用 LocalConnection 物件最簡單的方法就是只允許位於相同網域或相同 AIR 應用程式中的 LocalConnection 物件互相通訊。這樣一來,您就不用擔心安全性問題了。然而,如果您需要讓網域之間彼此通訊,則有幾種方式可用來執行安全性措施。如需詳細資訊,請參閱 適用於 Adobe Flash Platform 的 ActionScript 3.0 參考 中關於 send() 方法的 connectionName 參數討論,以及關於 LocalConnection 類別中的 allowDomain() domain 項目的討論。

您可以使用 LocalConnection 物件傳送及接收單一 SWF 檔中的資料,不過 Adobe 不建議您採用這種方式,請改用共用的物件。

有三種方式可將回呼方法加入 LocalConnection 物件:

  • 讓 LocalConnection 類別成為子類別,再加入方法。

  • LocalConnection.client 屬性設成實作這些方法的物件。

  • 建立會擴充 LocalConnection 的動態類別,再以動態方式加入方法。

第一種加入回呼方法的方式是擴充 LocalConnection 類別。您可以在自訂類別內定義這些方法,而不是以動態方式將它們加入 LocalConnection 實體。下列程式碼將示範這個做法:

package 
{ 
    import flash.net.LocalConnection; 
    public class CustomLocalConnection extends LocalConnection 
    { 
        public function CustomLocalConnection(connectionName:String) 
        { 
            try 
            { 
                connect(connectionName); 
            } 
            catch (error:ArgumentError) 
            { 
                // server already created/connected 
            } 
        } 
        public function onMethod(timeString:String):void 
        { 
            trace("onMethod called at: " + timeString); 
        } 
    } 
}

如果要建立 CustomLocalConnection 類別的新實體,您可以使用下列程式碼:

var serverLC:CustomLocalConnection; 
serverLC = new CustomLocalConnection("serverName");

第二種加入回呼方法的方式是使用 LocalConnection.client 屬性。這種做法會先建立一個自訂類別,並將新的實體指定給 client 屬性,如下列程式碼所示:

var lc:LocalConnection = new LocalConnection(); 
lc.client = new CustomClient();

LocalConnection.client 屬性指出應該叫用的物件回呼方法。在上一段程式碼中, client 屬性是設為自訂類別 CustomClient 的新實體。 client 屬性的預設值為目前的 LocalConnection 實體。當您有兩個資料處理常式是使用一組相同的方法但卻有不同的運作方式時 (例如,應用程式某個視窗中的一個按鈕會切換第二個視窗中的檢視狀態),請使用 client 屬性。

若要建立 CustomClient 類別,您可以使用下列程式碼:

package 
{ 
    public class CustomClient extends Object 
    { 
        public function onMethod(timeString:String):void 
        { 
            trace("onMethod called at: " + timeString); 
        } 
    } 
}

第三種加入回呼方法的方式是建立一個動態類別,再以動態方式加入這些方法。這種方式和在舊版 ActionScript 中使用 LocalConnection 類別的方式非常類似,如下列程式碼所示:

import flash.net.LocalConnection; 
dynamic class DynamicLocalConnection extends LocalConnection {}

您可以使用下列程式碼,以動態方式將回呼方法加入這個類別:

var connection:DynamicLocalConnection = new DynamicLocalConnection(); 
connection.onMethod = this.onMethod; 
// Add your code here. 
public function onMethod(timeString:String):void 
{ 
    trace("onMethod called at: " + timeString); 
}

上一種加入回呼方法的做法並不是理想的處理方式,因為這種程式碼不容易移植,不建議使用。此外,使用這種建立本機連線的方法同時也會產生效能方面的問題,因為存取動態屬性的速度遠遠不及存取密封屬性的速度。

isPerUser 屬性

isPerUser 屬性已新增至 Flash Player (10.0.32) 和 AIR (1.5.2),以解決當一個以上的使用者登入 Mac 電腦時所產生的衝突。 在其他作業系統上,本機連線一律僅限個別使用者使用,因此會忽略此屬性。 isPerUser 屬性應該在新程式碼中設為 true 。但是,預設值目前為 false 以提供舊版相容性。預設值可能會在未來發行的執行階段版本中進行變更。

在兩個應用程式之間傳送訊息

您可以使用 LocalConnection 類別在不同的 AIR 應用程式之間進行通訊,以及在瀏覽器中執行的不同 Adobe® Flash® Player (SWF) 應用程式之間進行通訊。您亦可使用 LocalConnection 類別,在 AIR 應用程式與瀏覽器中執行的 SWF 應用程式之間進行通訊。

例如,網頁上可以有多個 Flash Player 實體,或是讓某個 Flash Player 實體從彈出式視窗中的 Flash Player 實體擷取資料。

下列程式碼會定義做為伺服器運作的 LocalConnection 物件,並接受從其它應用程式傳入的 LocalConnection 呼叫:
package 
{ 
    import flash.net.LocalConnection; 
    import flash.display.Sprite; 
    public class ServerLC extends Sprite 
    { 
        public function ServerLC() 
        { 
            var lc:LocalConnection = new LocalConnection(); 
            lc.client = new CustomClient1(); 
            try 
            { 
                lc.connect("conn1"); 
            } 
            catch (error:Error) 
            { 
                trace("error:: already connected"); 
            } 
        } 
    } 
}

這段程式碼會先建立名為 lc 的 LocalConnection 物件,然後將 client 屬性設定為物件 clientObject 。當其它應用程式呼叫這個 LocalConnection 實體中的方法時,執行階段就會在 clientObject 物件中尋找該方法。

如果已經使用指定的名稱完成連線,便會擲回引數錯誤例外,指出連線嘗試失敗,因為該物件已經連線。

每當 Flash Player 實體連線至這個 SWF 檔,並嘗試為指定的本機連線叫用方法時,這項要求就會傳送至 client 屬性指定的類別 (已設定為 CustomClient1 類別):

package 
{ 
    import flash.events.*; 
    import flash.system.fscommand; 
    import flash.utils.Timer; 
    public class CustomClient1 extends Object 
    { 
        public function doMessage(value:String = ""):void 
        { 
            trace(value); 
        } 
        public function doQuit():void 
        { 
            trace("quitting in 5 seconds"); 
            this.close(); 
            var quitTimer:Timer = new Timer(5000, 1); 
            quitTimer.addEventListener(TimerEvent.TIMER, closeHandler); 
        } 
        public function closeHandler(event:TimerEvent):void 
        { 
            fscommand("quit"); 
        } 
    } 
}

若要建立 LocalConnection 伺服器,請呼叫 LocalConnection.connect() 方法並提供唯一的連線名稱。如果已經使用指定的名稱完成連線,便會產生 ArgumentError 錯誤,指出連線嘗試失敗,因為該物件已經連線。

下列程式碼片段將示範如何建立名為 conn1 的 LocalConnection:
try 
{ 
    connection.connect("conn1"); 
} 
catch (error:ArgumentError) 
{ 
    trace("Error! Server already exists\n"); 
}
如果要從次要應用程式連線至主要應用程式,您必須先在傳送端 LocalConnection 物件中建立 LocalConnection 物件,然後呼叫 LocalConnection.send() 方法,並指定連線名稱和方法名稱以便執行。例如,若要將 doQuit 方法傳送到您先前建立的 LocalConnection 物件,請使用下列程式碼:
sendingConnection.send("conn1", "doQuit");

這段程式碼會使用連線名稱 conn1 連線到現有的 LocalConnection 物件,並叫用遠端應用程式中的 doMessage() 方法。如果想將參數傳送至遠端應用程式,請在 send() 方法中的方法名稱之後指定其它引數,如下列程式碼片段所示:

sendingConnection.send("conn1", "doMessage", "Hello world");

連線至不同網域和 AIR 應用程式中的內容

如果只想允許從特定網域中進行通訊,您可以呼叫 LocalConnection 類別的 allowDomain() allowInsecureDomain() 方法,並傳遞一個或多個可以存取這個 LocalConnection 物件的網域清單,傳遞一個或多個要允許的網域名稱。

在舊版 ActionScript 中, LocalConnection.allowDomain() LocalConnection.allowInsecureDomain() 都是回呼方法,必須由開發人員實作並且必須傳回 Boolean 值;而在 ActionScript 3.0 中, LocalConnection.allowDomain() LocalConnection.allowInsecureDomain() 都是內建的方法,就和 Security.allowDomain() Security.allowInsecureDomain() 一樣,開發人員可以呼叫並傳遞一個或多個要允許的網域名稱。

Flash Player 8 在本機 SWF 檔上新增了安全性限制。允許存取網際網路的 SWF 檔無法同時存取本機檔案系統。如果您指定 localhost ,則任何本機 SWF 檔都可以存取這個 SWF 檔。如果 LocalConnection.send() 方法嘗試與安全執行程序中的 SWF 檔進行通訊,但是呼叫端程式碼卻無法存取此安全執行程序,則會傳送 securityError 事件 ( SecurityErrorEvent.SECURITY_ERROR )。若要排除這項錯誤,您可以在接收者的 LocalConnection.allowDomain() 方法中指定呼叫者的網域。

有兩個特殊值可以傳遞給 LocalConnection.allowDomain() LocalConnection.allowInsecureDomain() 方法: * localhost 。星號值 (*) 允許從所有網域存取。字串 localhost 允許從本機安裝但在應用程式資源目錄之外的內容,呼叫應用程式。

如果 LocalConnection.send() 方法嘗試與安全執行程序中的應用程式進行通訊,但是呼叫端程式碼卻無法存取此安全執行程序,則會傳送 securityError 事件 ( SecurityErrorEvent.SECURITY_ERROR )。若要排除這項錯誤,您可以在接收者的 LocalConnection.allowDomain() 方法中指定呼叫者的網域。

如果您只要在相同網域中的內容之間實作通訊,可以指定 connectionName 參數,這個參數不能以底線 ( _ ) 做為開頭,也不指定網域名稱 (例如, myDomain:connectionName )。請在 LocalConnection.connect(connectionName) 命令中使用相同的字串。

如果您要在不同網域的內容之間實作通訊,請指定以底線做為開頭的 connectionName 參數。指定底線可以讓具有接收端 LocalConnection 物件的內容更容易在不同的網域之間使用。此處列出兩種可能的案例:

  • 如果 connectionName 字串不以底線做為開頭,執行階段會加上具有父網域名稱和冒號 (例如, myDomain:connectionName ) 的前置詞。雖然這樣能確保您的連線不會與來自其它網域的相同名稱連線發生衝突,但是任何傳送端的 LocalConnection 物件仍然必須指定此父網域 (例如, myDomain:connectionName )。如果您將包含接收端 LocalConnection 物件的 HTML 或 SWF 檔移到其它網域,則執行階段會變更前置詞來反映新的父網域 (例如, anotherDomain:connectionName )。您必須手動編輯所有傳送端的 LocalConnection 物件,以指向新的父網域。

  • 如果 connectionName 的字串以底線為開頭 (例如, _connectionName ),執行階段就不會將前置詞加入此字串。也就是說,接收端與傳送端的 LocalConnection 物件將使用相同的 connectionName 字串。如果接收端物件使用 LocalConnection.allowDomain() 以指定接受來自任何網域的連線,您可以在不更動任何傳送端 LocalConnection 物件的情況下,將含有接收端 LocalConnection 物件的 SWF 檔移到其它網域。

    connectionName 中使用底線的缺點是可能會發生衝突,例如當兩個應用程式同時嘗試使用相同的 connectionName 連線時。第二個的缺點則與安全性相關。使用底線語法的連線名稱不會識別偵聽應用程式的網域。基於上述理由,一般偏好使用完整的網域名稱。

Adobe AIR

若要與 AIR 應用程式安全執行程序 (使用 AIR 應用程式安裝的內容) 中執行的內容進行通訊,必須在連線名稱加上識別 AIR 應用程式的父網域做為前置詞。父網域字串的開頭為 app# ,後面接著應用程式 ID 再加上點 (.) 字元,最後緊接發行者 ID (如果有定義的話)。 例如,在擁有應用程式 ID com.example.air.MyApp 且無發行者 ID 的應用程式中,其 connectionName 參數所使用的正確父網域為: "app#com.example.air.MyApp" 。因此,如果基礎連線名稱為 "appConnection",則 connectionName 參數所使用的完整字串為: "app#com.example.air.MyApp:appConnection" 。 如果應用程式具有發行者 ID,則該 ID 也必須包含在父網域字串中: "app#com.example.air.MyApp.B146A943FBD637B68C334022D304CEA226D129B4.1"

當您允許其它 AIR 應用程式透過本機連線與您的應用程式通訊時,必須呼叫 LocalConnection 物件的 allowDomain() ,傳入本機連線網域名稱。對於 AIR 應用程式來說,這個網域名稱是由應用程式和發行者 ID 所產生,與連線字串的方式相同。例如,如果傳送端 AIR 應用程式具有應用程式 ID com.example.air.FriendlyApp 和發行者 ID 214649436BD677B62C33D02233043EA236D13934.1 ,則您要用來允許這個應用程式連線的網域字串是: app#com.example.air.FriendlyApp.214649436BD677B62C33D02233043EA236D13934.1 。(從 AIR 1.5.3 開始,並非所有 AIR 應用程式都有發行者 ID。)