badge.swfを使うよりもきめ細かい制御が可能なシームレスインストールを行う方法

  • AIRアプリケーションのシームレスインストールを行いたい場合、badge.swfを使う方法が一般的とされている。
    確かに、badge.swfはなかなか良くできており使い方も比較的簡単だが、ランタイムやアプリケーションのインストール状況に応じてボタンの見た目を変えるといった細かい制御を行うことができない。
  • badge.swfの代わりに、air.swfを使うとよりきめ細かい制御が可能なシームレスインストールを行うことができる。
    具体的には、以下のステータスを判別してそれに応じて動作を変えることができる。
    • AIRランタイム自体が使用不可能(AIRランタイムが提供されていないOSの場合)
    • AIRランタイムがまだインストールされていない
    • AIRランタイムはインストールされているが、対象のAIRアプリケーションがまだインストールされていない
    • AIRランタイム、対象のAIRアプリケーションが共にインストールされている
  • air.swfは「http://airdownload.adobe.com/air/browserapi/air.swf」で公開されている。
    ここで注意する必要があるのが、このファイルをダウンロードして自前のサーバーに置くと、うまく動作しない機能があるという点。
    そのため、必ずLoaderなどを使ってネットワーク経由で取得したオリジナルのファイルを使用すること。
  • インストール済みのAIRアプリケーションを起動するには、アプリケーションID(applicationID)と発行者ID(publisherID)を指定する必要がある。
    • アプリケーションIDは、アプリケーション記述ファイル(The application descriptor file - application.xml)の「id」に記述する値のことである。
    • 発行者IDは、AIRアプリケーションを署名する証明書を元にして作成されるIDのことである。
      ここで注意する必要があるのが、発行者IDはAIRファイル自体には含まれておらず、実際にAIRアプリケーションをインストールしたときに初めて作成されるという点。
      そのため、発行者IDを確認するためには、AIRアプリケーションのインストール先のディレクトリの「META-INF/AIR/publisherid」ファイルをテキストエディタで開くしかない。
  • AIRランタイムのインストールとAIRアプリケーションのインストールまでは特にアプリケーション側の設定は必要ないが、インストール済みのAIRアプリケーションを起動するには、アプリケーション記述ファイルの「allowBrowserInvocation?」の値をtrueにしておく必要がある。
  • このテクニックを応用すれば、FlexやFlashで作成したアプリケーションの一部にシームレスインストールを行うパーツを組み込んだりすることもできるので、ブラウザとAIRの連携がとりやすくなる。
  • ちなみに、フォーエスの以下のAIRアプリケーションの配布ページでも、このテクニックを使用している。
  • (注1)シームレスインストールを行うには、Flash Playerのバージョンが「9.0.65」以上でないといけないので注意。
  • (注2)シームレスインストールを行うswfのブラウザ上の表示サイズが、Flash Playerの設定ウインドウを表示するのに必要な最低サイズ(214 × 137*1)よりも小さい場合、AIRランタイムのインストールのためのダイアログが表示されないので注意。
     
  • サンプルプログラム - air.swfを使ったシームレスインストール (実行画面はこちら)
    このサンプルプログラムでは、汎用性を考慮して、呼び出し元のHTMLファイルから対象のAIRアプリケーションの情報をパラメーターとして渡すようにしているが、もちろんプログラム内に固定の値を埋め込んでも良い。
    また、今回はFlexで作成しているが、FlashやAIRで作成しても良い。
    デザイン面を重視するなら、ボタンの部分を画像にしたりしても良い。

    アプリケーション本体 - fileAirLauncherSample.mxml
    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
        layout="absolute"
        creationComplete="onCreationComplete()"
        >
        
        <mx:Script>
            <![CDATA[
                import net.AirInstallAndLauncher;
                
                //==========================================================
                //フィールド
                
                /**
                 * AIRアプリケーションのインストール、または起動を行うクラス
                 */
                private var installer :AirInstallAndLauncher = new AirInstallAndLauncher();
                
                
                //==========================================================
                //メソッド
                
                /**
                 * 初期化処理を行います。
                 * 
                 * @param event イベントオブジェクト
                 */
                private function onCreationComplete(event :Event = null) :void
                {
                    //==========================================================
                    //対象のAIRアプリケーションの情報を設定
                    
                    ////////////////////////////////////////////////////////////
                    //パラメーター(FlashVars)に指定されている値をAIRアプリケーションインストール・起動用クラスに設定する
                    
                    //パラメータ格納用のオブジェクトが存在する場合
                    //(存在しないことはないはずだが、念のためにチェック)
                    if(Application.application.parameters != null)
                    {
                        //AIRファイルのURL
                        if(Application.application.parameters["targetAirURL"] != undefined)
                        {
                            this.installer.targetAirURL = Application.application.parameters["targetAirURL"];
                        }
    
                        //AIRランタイムのバージョン
                        if(Application.application.parameters["runtimeVersion"] != undefined)
                        {
                            this.installer.runtimeVersion = Application.application.parameters["runtimeVersion"];
                        }
    
                        //アプリケーションID
                        if(Application.application.parameters["appicationID"] != undefined)
                        {
                            this.installer.appicationID = Application.application.parameters["appicationID"];
                        }
    
                        //パブリッシャーID
                        if(Application.application.parameters["publisherID"] != undefined)
                        {
                            this.installer.publisherID = Application.application.parameters["publisherID"];
                        }
    
                        //対象のAIRアプリケーションに渡す引数が指定されている場合
                        if(Application.application.parameters["arguments"] != undefined)
                        {
                            //「,」区切りで文字列配列に分割してから設定する
                            this.installer.arguments = (Application.application.parameters["arguments"] as String).split(",");
                        }
    
                    }
                    
                    //==========================================================
    
                    //AIRアプリケーションインストール・起動用クラスの初期化イベントのイベントリスナーを設定
                    this.installer.addEventListener(Event.INIT, installerOnInit);
                    
                    //AIRアプリケーションインストール・起動用クラスの初期化処理を行う
                    this.installer.init();
                }
                
                /**
                 * AIRアプリケーションインストール・起動用クラスの初期化時のイベント処理を行います。
                 * 
                 * @param event イベントオブジェクト
                 */
                private function installerOnInit(event :Event) :void
                {
                    //==========================================================
                    //インストーラーのステータスに応じてボタンの状態を切り替える
                    
                    //AIRアプリケーションインストール済みの場合
                    if(this.installer.status == AirInstallAndLauncher.STATUS_APPLICATION_INSTALLED)
                    {
                        //インストールボタンのラベルを切り替える
                        this.installButton.label = "インストール済みのAIRアプリケーションを起動";
                        
                        //インストールボタンを有効にする
                        this.installButton.enabled = true;
                    }
                    //AIRアプリケーション未インストールの場合
                    else if(this.installer.status == AirInstallAndLauncher.STATUS_APPLICATION_NOT_INSTALL)
                    {
                        //インストールボタンの画像を「ダウンロード」に切り替える
                        this.installButton.label = "AIRアプリケーションをインストール";
    
                        //インストールボタンを有効にする
                        this.installButton.enabled = true;
                    }
                    //AIRランタイム未インストールの場合
                    else if(this.installer.status == AirInstallAndLauncher.STATUS_RUNTIME_NOT_INSTALL)
                    {
                        //インストールボタンの画像を「ダウンロード」に切り替える
                        this.installButton.label = "AIRランタイムも含めてインストール";
    
                        //インストールボタンを有効にする
                        this.installButton.enabled = true;
                    }
                    //AIRランタイム使用不可能の場合
                    else if(this.installer.status == AirInstallAndLauncher.STATUS_RUNTIME_UNAVAILABLE)
                    {
                        //インストールボタンのラベルを切り替える
                        this.installButton.label = "AIRをインストールできない環境です";
                    }
                    //air.swfの読み込み中に入出力エラーが発生した場合
                    else if(this.installer.status == AirInstallAndLauncher.STATUS_AIR_SWF_IO_ERROR)
                    {
                        //インストールボタンのラベルを切り替える
                        this.installButton.label = "入出力エラーが発生しました";
                    }
                }
                
                /**
                 * インストールボタンがクリックされた場合のイベント処理を行います。
                 * 
                 * @param event イベントオブジェクト
                 */
                private function installButtonOnClick(event :Event = null) :void
                {
                    //==========================================================
                    //インストーラーのステータスに応じて処理を切り替える
                    
                    //AIRアプリケーションインストール済みの場合
                    if(this.installer.status == AirInstallAndLauncher.STATUS_APPLICATION_INSTALLED)
                    {
                        //インストールされているAIRアプリケーションを起動する
                        this.installer.launchApplication();
                    }
                    //AIRアプリケーション未インストールの場合
                    else if((this.installer.status == AirInstallAndLauncher.STATUS_APPLICATION_NOT_INSTALL))
                    {
                        //対象のAIRアプリケーションをインストールする
                        this.installer.installApplication();
                    }
                    //AIRランタイム未インストールの場合
                    else if(this.installer.status == AirInstallAndLauncher.STATUS_RUNTIME_NOT_INSTALL)
                    {
                        //対象のAIRアプリケーションをインストールする
                        this.installer.installApplication();
                    }
                    //それ以外の場合
                    else
                    {
                        //ここに到達することはないはずなので例外を投げる
                        throw new Error("このステータスではボタンが押せないはず。status=" + this.installer.status);
                    }
                }
                
            ]]>
        </mx:Script>
        
        <mx:Button id="installButton" 
            label="初期化中・・・"
            enabled="false"
            click="installButtonOnClick()"
            />
    </mx:Application>
     
    AIRアプリケーションのインストール、または起動を行うクラス - filenet.AirInstallAndLauncher.as
    package net
    {
        import flash.display.Loader;
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.HTTPStatusEvent;
        import flash.events.IOErrorEvent;
        import flash.net.URLRequest;
        
        /**
         * 初期化処理終了時のイベント
         *
         * @eventType flash.events.Event.INIT
         */
        [Event(name="init", type="flash.events.Event")]
        
        
        /**
         * AIRアプリケーションのインストール、または起動を行うクラス。
         */
        public class AirInstallAndLauncher extends EventDispatcher
        {
            //==========================================================
            //定数
            
            /**
             * air.swfのURL
             */
            public static const AIR_SWF_URL :String = "http://airdownload.adobe.com/air/browserapi/air.swf";
            
            /**
             * AIRランタイムのバージョンのデフォルト値
             */
            public static const DEFAULT_RUNTIME_VERSION :String = "1.1";
            
            /**
             * ステータス: 初期化前
             */
            public static const STATUS_BEFORE_INIT :String = "0";
            
            /**
             * ステータス: AIRアプリケーションインストール済み
             */
            public static const STATUS_APPLICATION_INSTALLED :String = "1";
            
            /**
             * ステータス: AIRアプリケーション未インストール
             */
            public static const STATUS_APPLICATION_NOT_INSTALL :String = "2";
            
            /**
             * ステータス: AIRランタイム未インストール
             */
            public static const STATUS_RUNTIME_NOT_INSTALL :String = "3";
            
            /**
             * ステータス: AIRランタイム使用不可能
             */
            public static const STATUS_RUNTIME_UNAVAILABLE :String = "4";
            
            /**
             * ステータス: air.swfの読み込み中に入出力エラーが発生
             */
            public static const STATUS_AIR_SWF_IO_ERROR :String = "5";
            
            
            //==========================================================
            //フィールド
            
            /**
             * インストール対象のAIRアプリケーションのAIRファイルのURL
             */
            public var targetAirURL :String = null; 
            
            /**
             * AIRランタイムのバージョン
             */
            public var runtimeVersion :String = DEFAULT_RUNTIME_VERSION; 
            
            /**
             * インストール対象のAIRアプリケーションのアプリケーションID
             * (application.xml内に記述されている)
             */
            public var appicationID :String = null; 
            
            /**
             * インストール対象のAIRアプリケーションの発行者ID
             * (AIRのインストール先のMETA-INF/AIR/publisheridに記述されている)
             */
            public var publisherID :String = null; 
            
            /**
             * 対象のAIRアプリケーションに渡す引数の配列
             * (通常は必要ない)
             */
            public var arguments :Array = new Array();
    
     
            /**
             * air.swfのオブジェクトを保持する変数
             */
            protected var airSwf :Object;
            
            /**
             * air.swfを読み込むためのローダー
             */
            protected var airSwfLoader :Loader = null;
            
            /**
             * ステータス
             */
            protected var _status :String = STATUS_BEFORE_INIT;
            
            
            //==========================================================
            //メソッド
            
            /**
             * 初期化処理を行います。
             */
            public function init() :void
            {
                //インストール対象のAIRアプリケーションのAIRファイルのURLが指定されていない場合
                if((this.targetAirURL == null) || (this.targetAirURL == ""))
                {
                    //例外を投げる
                    throw new Error("インストール対象のAIRアプリケーションのAIRファイルのURLが指定されていません");
                }
                
                //インストール対象のAIRアプリケーションのアプリケーションIDが指定されていない場合
                if((this.appicationID == null) || (this.appicationID == ""))
                {
                    //例外を投げる
                    throw new Error("インストール対象のAIRアプリケーションのアプリケーションIDが指定されていません");
                }
                
                //インストール対象のAIRアプリケーションのパブリッシャーIDが指定されていない場合
                if((this.publisherID == null) || (this.publisherID == ""))
                {
                    //例外を投げる
                    throw new Error("インストール対象のAIRアプリケーションのパブリッシャーIDが指定されていません");
                }
                
                //air.swfを読み込むためのローダーのインスタンスを設定
                this.airSwfLoader = new Loader();
    
                //air.swfのイベントリスナーを設定する
                //(プロパティとメソッドにアクセスできるようになれば良いので、completeイベントではなくinitイベントを使う)
                this.airSwfLoader.contentLoaderInfo.addEventListener(Event.INIT, onAirSwfLoaderInit);
                this.airSwfLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onAirSwfLoaderErrorHandler);
                this.airSwfLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, onAirSwfLoaderHttpStatus);
                
                //air.swfの読み込み実行
                airSwfLoader.load(new URLRequest(AIR_SWF_URL));
            }
    
            /**
             * 対象のAIRアプリケーションをインストールします。
             * AIRのランタイム自体がまだイントールされていない場合は、ランタイムからインストールします。
             */
            public function installApplication() :void
            {
                //ステータスが「AIRアプリケーション未インストール」、「AIRランタイム未インストール」以外の場合
                if((this._status != STATUS_APPLICATION_NOT_INSTALL) && (this._status != STATUS_RUNTIME_NOT_INSTALL))
                {
                    //例外を投げる
                    throw new Error("ステータスが不正です:" + this._status);
                }
                    
                //air.swfに処理を委譲する
                this.airSwf.installApplication(this.targetAirURL, this.runtimeVersion, this.arguments); 
            }
            
            /**
             * インストールされているAIRアプリケーションを起動します。
             */
            public function launchApplication() :void
            {
                //ステータスが「AIRアプリケーションインストール済み」以外の場合
                if(this._status != STATUS_APPLICATION_INSTALLED)
                {
                    //例外を投げる
                    throw new Error("ステータスが不正です:" + this._status);
                }
                    
                //air.swfに処理を委譲する
                this.airSwf.launchApplication(this.appicationID, this.publisherID, this.arguments);
            }
            
            /**
             * ステータスの値を取得します。
             * (読み取り専用)
             * 
             * @return ステータス
             */
            public function get status() :String
            {
                //フィールドの値をそのまま返す
                return this._status;
            }
            
            
            //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
            //内部処理用
            
            /**
             * air.swfの読み込み完了時のイベント処理を行います。
             *
             * @param event イベントオブジェクト
             */
            protected function onAirSwfLoaderInit(event :Event) :void
            {
                //読み込みが完了したair.swfのオブジェクトを取得
                this.airSwf = event.target.content;
                
                //AIRランタイム自体のインストール状況を取得
                var runtimeStatus :String = this.airSwf.getStatus();
                
                //AIRランタイムがすでにインストールされている場合
                if(runtimeStatus == "installed")
                {
                    //対象のAIRアプリケーションのバージョン取得を行い、結果に応じてインストールまたは起動させる
                    this.airSwf.getApplicationVersion(this.appicationID, this.publisherID, versionDetectCallback);
                }
                //AIRランタイムがまだインストールされていないが、インストールできる環境の場合
                else if(runtimeStatus == "available")
                {
                    //ステータスを「AIRランタイム未インストール」に変更する
                    this._status = STATUS_RUNTIME_NOT_INSTALL;
                    
                    //初期化イベントを投げる
                    super.dispatchEvent(new Event(Event.INIT));
                }
                //AIRランタイムがインストールできない環境の場合
                else
                {
                    //ステータスを「AIRランタイム使用不可能」に変更する
                    this._status = STATUS_RUNTIME_UNAVAILABLE;
                    
                    //初期化イベントを投げる
                    super.dispatchEvent(new Event(Event.INIT));
                }
            }
            
            /**
             * air.swfのエラー系のイベント処理を行います。
             *
             * @param event イベントオブジェクト
             */
            protected function onAirSwfLoaderErrorHandler(event :Event) :void
            {
                //ステータスを「air.swfの読み込み中に入出力エラーが発生」に変更する
                this._status = STATUS_AIR_SWF_IO_ERROR;
                
                //初期化イベントを投げる
                super.dispatchEvent(new Event(Event.INIT));
            }
            
            /**
             * air.swfのHTTPステータス変更時のイベント処理を行います。
             *
             * @param event イベントオブジェクト
             */
            protected function onAirSwfLoaderHttpStatus(event :HTTPStatusEvent) :void
            {
                //HTTPステータスが「404(Not Found)」の場合
                if(event.status == 404)
                {
                    //エラー発生時と同じ処理を行う
                    onAirSwfLoaderErrorHandler(event);
                }
            }
            
            /**
             * 対象のAIRアプリケーションのバージョン取得処理のコールバック関数です。
             *
             * @param version バージョン
             */
            protected function versionDetectCallback(version :String) :void 
            {
                //バージョンが取得できなかった場合
                //(対象のAIRアプリケーションがインストールされていない場合)
                if(version == null) 
                {
                    //ステータスを「AIRアプリケーション未インストール」に変更する
                    this._status = STATUS_APPLICATION_NOT_INSTALL;
                }
                //対象のAIRアプリケーションがインストールされている場合
                else
                {
                    //ステータスを「AIRアプリケーションインストール済み」に変更する
                    this._status = STATUS_APPLICATION_INSTALLED;
                }
    
                //初期化イベントを投げる
                super.dispatchEvent(new Event(Event.INIT));
            }
            
        }
     
    swfをラッピングするHTMLファイル (このサンプルではQRMaker.airを対象に指定している) - fileAirLauncherSample.html
    <!-- saved from url=(0014)about:internet -->
    <html lang="en">
    
    <!-- 
    Smart developers always View Source. 
    
    This application was built using Adobe Flex, an open source framework
    for building rich Internet applications that get delivered via the
    Flash Player or to desktops via Adobe AIR. 
    
    Learn more about Flex at http://flex.org 
    // -->
    
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script src="AC_OETags.js" language="javascript"></script>
    <style>
    body { margin: 0px; overflow:hidden }
    </style>
    <script language="JavaScript" type="text/javascript">
    <!--
    // -----------------------------------------------------------------------------
    // Globals
    // Major version of Flash required
    var requiredMajorVersion = 9;
    // Minor version of Flash required
    var requiredMinorVersion = 0;
    // Minor version of Flash required
    var requiredRevision = 65;
    // -----------------------------------------------------------------------------
    // -->
    </script>
    </head>
    
    <body scroll="no">
    <script language="JavaScript" type="text/javascript">
    <!--
    // Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)
    var hasProductInstall = DetectFlashVer(6, 0, 65);
    
    // Version check based upon the values defined in globals
    var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
    
     
    // Check to see if a player with Flash Product Install is available and the version does not meet the requirements for playback
    if ( hasProductInstall && !hasRequestedVersion ) {
        // MMdoctitle is the stored document.title value used by the installation process to close the window that started the process
        // This is necessary in order to close browser windows that are still utilizing the older version of the player after installation has completed
        // DO NOT MODIFY THE FOLLOWING FOUR LINES
        // Location visited after installation is complete if installation is required
        var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
        var MMredirectURL = window.location;
        document.title = document.title.slice(0, 47) + " - Flash Player Installation";
        var MMdoctitle = document.title;
    
        AC_FL_RunContent(
            "src", "playerProductInstall",
            "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
            "width", "100%",
            "height", "100%",
            "align", "middle",
            "id", "AirLauncherSample",
            "quality", "high",
            "bgcolor", "#869ca7",
            "name", "AirLauncherSample",
            "allowScriptAccess","sameDomain",
            "type", "application/x-shockwave-flash",
            "pluginspage", "http://www.adobe.com/go/getflashplayer"
        );
    } else if (hasRequestedVersion) {
        // if we've detected an acceptable version
        // embed the Flash Content SWF when all tests are passed
        AC_FL_RunContent(
                "src", "AirLauncherSample",
                "width", "100%",
                "height", "100%",
                "align", "middle",
                "id", "AirLauncherSample",
                "quality", "high",
                "bgcolor", "#869ca7",
                "name", "AirLauncherSample",
                "allowScriptAccess","sameDomain",
                "type", "application/x-shockwave-flash",
                "pluginspage", "http://www.adobe.com/go/getflashplayer",
                //==========================================================
                //FlashVarsで対象のAIRアプリケーションの情報を指定する
                //(このサンプルではQRMaker.airを対象に指定している)
                "FlashVars", 
                    "targetAirURL=http://www.fores.jp/labs/air/QRMaker.air" + 
                    "&runtimeVersion=1.1" +
                    "&appicationID=jp.fores.QRMaker" +
                    "&publisherID=4E9A24867EE94C89961E0F37E0F210A4218F36C0.1"
                //==========================================================
        );
      } else {  // flash is too old or we can't detect the plugin
        var alternateContent = 'Alternate HTML content should be placed here. '
          + 'This content requires the Adobe Flash Player. '
           + '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
        document.write(alternateContent);  // insert non-flash content
      }
    // -->
    </script>
    <noscript>
          <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
                id="AirLauncherSample" width="100%" height="100%"
                codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
                <param name="movie" value="AirLauncherSample.swf" />
                <param name="quality" value="high" />
                <param name="bgcolor" value="#869ca7" />
                <param name="allowScriptAccess" value="sameDomain" />
                <embed src="AirLauncherSample.swf" quality="high" bgcolor="#869ca7"
                    width="100%" height="100%" name="AirLauncherSample" align="middle"
                    play="true"
                    loop="false"
                    quality="high"
                    allowScriptAccess="sameDomain"
                    type="application/x-shockwave-flash"
                    pluginspage="http://www.adobe.com/go/getflashplayer">
                </embed>
        </object>
    </noscript>
    </body>
    </html>

AIR関連の技術情報に戻る


*1 日本語版のIE 7とFirefox 3.0.1で確認

添付ファイル: fileAirLauncherSample.html 449件 [詳細] fileAirInstallAndLauncher.as 428件 [詳細] fileAirLauncherSample.mxml 458件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-07-31 (木) 16:17:40 (764d)