読者です 読者をやめる 読者になる 読者になる

pblog

pplog.net を作っている @ppworks こと越川直人(Koshikawa Naoto)のブログ

flashでmixiアプリ作るためのポイントを調査

mixiアプリ OpenSocial FLASH

まずはAPI周り。

JavaScript API vs Restful Protocol

Gadget XMLに埋め込んだswfからOpenSocial APIへアクセスするにはどうしたら良いのか考えます。

mixi Developer Centerより」
mixiアプリは、OpenSocialJavaScript APIをつかってSNSmixi』の情報を操作します。

むむ、Restful Protocolは対応してないのかな?ちょっとまだ調べきれていないのでJavaScript APIを使ってみようと思います。

埋め込み方法

mixi Developer CenterにあるようなOpenSocilaの仕様に合わせてflash featureをRequireしてあげて、gadgets.flash.embedFlashを使う方法が標準的な方法です。他にはContents要素にobjectタグを記述したり、SWFObjectを利用したりでも良いかなと思います。でも出来ることならOpenSocialで用意されているfeatureを使いたいところです。

SWF埋め込み時のポイント1

f:id:naoto5959:20090418030816p:image
OpenSocialJavaScript APIを使うということは、swfのcontainerに定義されたJavaScriptを実行ということになります。よって、swfからswfのcontainerへのアクセス(swfからcontainerに定義されているjavascriptを実行する)ためには、containerとswfのdomainは通常別domainとなりますので、swfを埋め込むタグのパラメータにallowScriptAccess = 'always'を追加する必要があります。

SWF埋め込み時のポイント2

f:id:naoto5959:20090418030815p:image
逆にcontainerからswfにアクセスする(containerに定義されたJavaScriptから、swfに定義された関数やクロージャを実行する)には、下記の準備が必要です。

  • swfからcontainerへ公開する関数名の登録
ExternalInterface.addCallback("公開名", 実際のクロージャ);
  • containerの所属するdomainからのアクセスを許可する
Security.allowDomain("許可するドメイン");

または、container側に

function getHostname() {
  return location.hostname;
}

と定義して、

Security.allowDomain(ExternalInterface.call("getHostname"));

追記ココから
または、ExternalInterface.callに無名関数を渡してあげることが出来ます。

Security.allowDomain(ExternalInterface.call("function() { return location.hostname }"));

こうすると絞った気になれますが、気休めですね。

追記ココまで

OpenSocialの仕様に合わせた記述(gadgets.flash.embedFlashを利用)

そういうわけでFLASHのfeatureを利用する場合のGadget.xmlは以下のような感じになります。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="flash feature flash版" author="naoto koshikawa">
    <Require feature="flash"/>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[
    <script src="<PathTo>prototype.js"></script>
    <script src="<PathTo>swfobject.js"></script>
    <div id="externalContainer">
      <p>Alternative content</p>
    </div>
    <script type="text/javascript">
      function init() {
        gadgets.flash.embedFlash(
          "<PathToSWF>", "externalContainer", "9.0.0",
          {
            id : "externalswf", // 一部のIE向けにexternalを接頭子にする
            width : 200,
            height : 200,
            quality : 'high',
            wmode : 'transparent',
            allowScriptAccess : 'always' // swfからcontainer(ここ)へのaccessを許可
          }
        );
      }
      gadgets.util.registerOnLoadHandler(init);
    </script>
  ]]>
  </Content>
</Module>

ポイントとなる箇所にはコメントが入れてあります。
そして、この埋め込み方法で確認した不都合は下記の通りです。

gadgets.flash.embedFlashを使用した際の不都合
  1. Internet Explorer (確認したversion 7.0.5730.13)において、初回アクセス時に「サンドボックス違反」が出ます。但し、Flash Debug playerの場合のみ。traceログに吐き出されるが特に支障はなさそうです。原因は今の所不明です。
  2. Firefox version 3.0.8において、TextFieldに日本語入力ができない。有名なwmodeの問題でもなさそうです。wmodeをかえてもダメでした。

featureを無視してSWFObjectを利用する記述

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="flash SWFObject版" author="naoto koshikawa">
  </ModulePrefs>
  <Content type="html">
  <![CDATA[
    <script src="<URLTo>prototype.js"></script>
    <script src="<URLTo>swfobject.js"></script>
    <div id="externalContainer">
      <p>Alternative content</p>
    </div>
    <script type="text/javascript">
      function init() {
        swfobject.embedSWF(
          "<URLToSWF>", "externalContainer", "200", "200", "9.0.0",
          undefined, // 最新版FlashPlayerを取得する際に表示したいswf
          {}, // flashvars(flashに渡す外部パラメータ)
          {
            quality : 'high',
            wmode : 'transparent',
            allowScriptAccess : 'always' // swfからcontainer(ここ)へのaccessを許可
          }, // params
          {
            id : "externalswf" // 一部のIE向けにexternalを接頭子にする
          } // attributes
        );
      }
      gadgets.util.registerOnLoadHandler(init);
    </script>
  ]]>
  </Content>
</Module>

こちらの方法では、今の所不都合らしい動作は見られません。前述のgadgets.flash.embedFlashとの違いは、firefoxやsafariなどにおいて、SWFObjectではタグを吐き出さないことに気づきました。SWFObjectソースを読んでちょっと勉強してみます。

まとめ

mixiアプリを作成する際には

  • allowScriptAccess = 'always'忘れない
  • ExternalInterfaceでswf <-> containerの受け口を作る
  • SWFObject使う

次はJavaScriptAPIを抽象化したAPIを作りたい所。