共有オブジェクト

Flash Player 9 以降、Adobe AIR 1.0 以降

「Flash cookie」とも呼ばれる共有オブジェクトは、アクセスしたサイトによってコンピューター上に作成されるデータファイルです。ほとんどの場合、共有オブジェクトは、ユーザーが頻繁にアクセスする Web サイトの外観をパーソナライズする場合など、Web ブラウジングの操作性を向上するために使用されます。

共有オブジェクトについて

共有オブジェクトは、ブラウザーの Cookie のように機能します。SharedObject クラスを使用して、ユーザーのローカルハードディスクにデータを格納し、同じセッションやその後のセッションで、格納したデータを呼び出します。アプリケーションは、SharedObject データが同じドメインで実行されている場合に限り、独自の SharedObject データのみにアクセスできます。データはサーバーに送信されず、他のドメインで実行中の他のアプリケーションがデータにアクセスすることもできません。ただし、同じドメインのアプリケーションがデータにアクセスできるようにすることは可能です。

共有オブジェクトと Cookie の比較

Cookie と共有オブジェクトは非常によく似ています。大多数の Web プログラマーは Cookie の機能に精通しているので、Cookie とローカル SharedObject を比較すると役立つ場合があります。

RFC 2109 標準に準拠する Cookie には通常、次のような特性があります。

  • 期限切れになることがあり、多くの場合、デフォルトではセッションの終了時に期限切れになります。

  • サイトごとにクライアントによって無効にすることができます。

  • 合計 300 Cookie、サイトごとに最大 20 Cookie の制限があります。

  • 通常は、それぞれ 4 KB までのサイズに制限されています。

  • セキュリティ脅威と認識されることがあるので、結果として、クライアントで無効にされることがあります。

  • クライアントブラウザーで指定された場所に格納されます。

  • HTTP を介してクライアントからサーバーに送信されます。

    一方、共有オブジェクトには次のような特性があります。

  • デフォルトでは期限切れになりません。

  • デフォルトでは、それぞれ 100 KB までのサイズに制限されています。

  • 単純なデータ型(String、Array、Date など)を格納できます。

  • アプリケーションで指定された場所(ユーザーのホームディレクトリ内)に格納されます。

  • クライアントとサーバーとの間で送信されることはありません。

SharedObject クラスについて

SharedObject クラスを使用して、共有オブジェクトを作成および削除したり、使用している SharedObject オブジェクトの現在のサイズを検出したりできます。

共有オブジェクトの作成

SharedObject オブジェクトを作成するには、SharedObject.getLocal() メソッドを使用します。このメソッドのシンタックスは次のとおりです。

SharedObject.getLocal("objectName" [, pathname]): SharedObject

次の例では、mySO という共有オブジェクトを作成します。

public var mySO:SharedObject; 
mySO = SharedObject.getLocal("preferences");

これによってクライアントのマシン上に preferences.sol というファイルが作成されます。

local という用語は、共有オブジェクトの場所を指します。この場合、Adobe® Flash® Player によって、クライアントのホームディレクトリ内に SharedObject ファイルがローカルに格納されます。

共有オブジェクトを作成すると、Flash Player によってアプリケーションおよびドメインに対してサンドボックス内に新規ディレクトリが作成されます。また、SharedObject データを格納する *.sol ファイルも作成されます。このファイルのデフォルトの場所は、ユーザーのホームディレクトリのサブディレクトリです。次の表に、このディレクトリのデフォルトの場所を示します。

オペレーティングシステム

場所

Windows 95/98/ME/2000/XP

c:/Documents and Settings/username/Application Data/Macromedia/Flash Player/#SharedObjects

Windows Vista/Windows 7

c:/Users/username/AppData/Roaming/Macromedia/Flash Player/#SharedObjects

Macintosh OS X

/Users/username/Library/Preferences/Macromedia/Flash Player/#SharedObjects/web_domain/path_to_application/application_name/object_name.sol

Linux/Unix

/home/username/.macromedia/Flash_Player/#SharedObjects/web_domain/path_to_application/application_name/object_name.sol

#SharedObjects ディレクトリの下は、ランダムに名前が付けられたディレクトリになります。その下はホスト名に一致するディレクトリ、次にアプリケーションへのパス、最後に *.sol ファイルとなります。

例えば、ローカルホスト上で /sos という名前のサブディレクトリ内に MyApp.swf という名前のアプリケーションを要求した場合、Flash Player によって Windows XP の次の場所に *.sol ファイルが格納されます。

c:/Documents and Settings/fred/Application Data/Macromedia/Flash Player/#SharedObjects/KROKWXRK/#localhost/sos/MyApp.swf/data.sol
注意: SharedObject.getLocal() メソッドに名前を指定しない場合は、Flash Player によってファイルに undefined.sol という名前が付けられます。

デフォルトでは、Flash によってドメインごとに最大 100 KB の永続的な SharedObject オブジェクトをローカルに保存できます。この値はユーザーが設定可能です。アプリケーションが共有オブジェクトにデータを保存しようとし、その共有オブジェクトが 100 KB を超えるサイズになる場合には、Flash Player によってローカル記憶領域ダイアログボックスが表示されます。ユーザーはこのダイアログボックスを使用すると、アクセスを要求しているドメインに対してより多くのローカル記憶領域を許可または拒否することができます。

パスの指定

オプションの pathname パラメーターを使用して、SharedObject ファイルの場所を指定できます。このファイルは、そのドメインの SharedObject ディレクトリのサブディレクトリである必要があります。例えば、ローカルホスト上でアプリケーションを要求し、次のように指定した場合、

mySO = SharedObject.getLocal("myObjectFile","/");

Flash Player によって SharedObject ファイルが /#localhost ディレクトリ(アプリケーションがオフラインの場合は /localhost)に書き込まれます。これは、クライアント上の複数のアプリケーションが同じ共有オブジェクトにアクセスできるようにする必要がある場合に役立ちます。この場合、クライアントは、ドメインのルートである共有オブジェクトへのパスを指定する 2 つの Flex アプリケーションを実行可能です。クライアントは両方のアプリケーションから同じ共有オブジェクトにアクセスできるようになります。永続性のない複数のアプリケーション間でデータを共有するには、LocalConnection オブジェクトを使用できます。

存在しないディレクトリを指定した場合、Flash Player によって SharedObject ファイルは作成されません。

共有オブジェクトへのデータの追加

SharedObject オブジェクトの data プロパティを使用して、SharedObject の *.sol ファイルにデータを追加します。共有オブジェクトに新規データを追加するには、次のシンタックスを使用します。

sharedObject_name.data.variable = value;

次の例では、userNameitemNumbers および adminPrivileges プロパティとその値を SharedObject に追加します。

public var currentUserName:String = "Reiner"; 
public var itemsArray:Array = new Array(101,346,483); 
public var currentUserIsAdmin:Boolean = true; 
mySO.data.userName = currentUserName; 
mySO.data.itemNumbers = itemsArray; 
mySO.data.adminPrivileges = currentUserIsAdmin;

data プロパティに値を割り当てた後、これらの値を SharedObject のファイルに書き込むように Flash Player に指示する必要があります。Flash Player によって強制的に SharedObject のファイルに値を書き込むには、次のように SharedObject.flush() メソッドを使用します。

mySO.flush();

SharedObject.flush() メソッドを呼び出さない場合は、アプリケーションの終了時に Flash Player によって値がファイルに書き込まれます。ただし、データがデフォルト設定を超える場合に、Flash Player でそのデータの格納に使用可能なスペースを増やす機会はユーザーに与えられません。したがって、SharedObject.flush() を呼び出すことをお勧めします。

flush() メソッドを使用してユーザーのハードディスクに共有オブジェクトを書き込む場合は、次の例に示すように、Flash Player の設定マネージャー(www.macromedia.com/support/documentation/jp/flashplayer/help/settings_manager07.html)を使用してローカル記憶領域を明示的に無効にしてあるかどうかを慎重に確認する必要があります。

var so:SharedObject = SharedObject.getLocal("test"); 
trace("Current SharedObject size is " + so.size + " bytes."); 
so.flush();

共有オブジェクトへのオブジェクトの格納

Array や String などの単純なオブジェクトは、SharedObject の data プロパティに格納できます。

次の例に、共有オブジェクトとの対話を制御するメソッドを定義する ActionScript クラスを示します。これらのメソッドを使用すると、ユーザーは共有オブジェクトにオブジェクトを追加したり、共有オブジェクトからオブジェクトを削除したりすることができます。このクラスには、単純なオブジェクトを含む ArrayCollection が格納されます。

package { 
    import mx.collections.ArrayCollection; 
    import flash.net.SharedObject; 
 
    public class LSOHandler { 
 
        private var mySO:SharedObject; 
        private var ac:ArrayCollection; 
        private var lsoType:String; 
 
        // The parameter is "feeds" or "sites". 
        public function LSOHandler(s:String) { 
            init(s); 
        } 
 
        private function init(s:String):void { 
            ac = new ArrayCollection(); 
            lsoType = s; 
            mySO = SharedObject.getLocal(lsoType); 
            if (getObjects()) { 
                ac = getObjects(); 
            } 
        } 
 
        public function getObjects():ArrayCollection { 
            return mySO.data[lsoType]; 
        } 
 
        public function addObject(o:Object):void { 
            ac.addItem(o); 
            updateSharedObjects(); 
        } 
 
        private function updateSharedObjects():void { 
            mySO.data[lsoType] = ac; 
            mySO.flush(); 
        } 
    } 
 
}

次の Flex アプリケーションでは、必要な共有オブジェクトのタイプごとに、ActionScript クラスのインスタンスが作成されます。その後、ユーザーがブログまたはサイト URL を追加または削除するときに、そのクラスでメソッドが呼び出されます。

<?xml version="1.0"?> 
<!-- lsos/BlogAggregator.mxml --> 
<mx:Application 
    xmlns:local="*" 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    creationComplete="initApp()" 
    backgroundColor="#ffffff" 
> 
    <mx:Script> 
        <![CDATA[ 
        import mx.collections.ArrayCollection; 
        import mx.utils.ObjectUtil; 
        import flash.net.SharedObject; 
 
        [Bindable] 
        public var welcomeMessage:String; 
        
        [Bindable] 
        public var localFeeds:ArrayCollection = new ArrayCollection(); 
 
        [Bindable] 
        public var localSites:ArrayCollection = new ArrayCollection(); 
 
        public var lsofeeds:LSOHandler; 
        public var lsosites:LSOHandler; 
 
        private function initApp():void { 
            lsofeeds = new LSOHandler("feeds"); 
            lsosites = new LSOHandler("sites"); 
            
            if (lsofeeds.getObjects()) { 
                localFeeds = lsofeeds.getObjects(); 
            } 
            if (lsosites.getObjects()) { 
                localSites = lsosites.getObjects(); 
            } 
        } 
        
        // Adds a new feed to the feeds DataGrid. 
        private function addFeed():void { 
            // Construct an object you want to store in the 
            // LSO. This object can contain any number of fields. 
            var o:Object = {name:ti1.text, url:ti2.text, date:new Date()}; 
            lsofeeds.addObject(o); 
    
            // Because the DataGrid's dataProvider property is 
            // bound to the ArrayCollection, Flex updates the 
            // DataGrid when you call this method. 
            localFeeds = lsofeeds.getObjects(); 
            
            // Clear the text fields. 
            ti1.text = '';        
            ti2.text = ''; 
        } 
        
        // Removes feeds from the feeds DataGrid. 
        private function removeFeed():void { 
            // Use a method of ArrayCollection to remove a feed. 
            // Because the DataGrid's dataProvider property is 
            // bound to the ArrayCollection, Flex updates the 
            // DataGrid when you call this method. You do not need 
            // to update it manually. 
            if (myFeedsGrid.selectedIndex > -1) { 
            
localFeeds.removeItemAt(myFeedsGrid.selectedIndex); 
             } 
        } 
        
        private function addSite():void { 
            var o:Object = {name:ti3.text, date:new Date()}; 
            lsosites.addObject(o); 
            localSites = lsosites.getObjects(); 
            ti3.text = '';                
        } 
        
        private function removeSite():void { 
            if (mySitesGrid.selectedIndex > -1) { 
            
localSites.removeItemAt(mySitesGrid.selectedIndex); 
            }       
        } 
 
        ]]> 
    </mx:Script> 
        
    <mx:Label text="Blog aggregator" fontSize="28"/> 
    
    <mx:Panel title="Blogs"> 
        <mx:Form id="blogForm"> 
            <mx:HBox> 
                <mx:FormItem label="Name:"> 
                    <mx:TextInput id="ti1" width="100"/> 
                </mx:FormItem> 
                <mx:FormItem label="Location:"> 
                    <mx:TextInput id="ti2" width="300"/> 
                </mx:FormItem> 
                <mx:Button id="b1" label="Add Feed" click="addFeed()"/> 
            </mx:HBox> 
 
            <mx:FormItem label="Existing Feeds:"> 
                <mx:DataGrid 
                    id="myFeedsGrid" 
                    dataProvider="{localFeeds}" 
                    width="400" 
                /> 
            </mx:FormItem> 
            <mx:Button id="b2" label="Remove Feed" click="removeFeed()"/> 
        </mx:Form> 
    </mx:Panel> 
    
    <mx:Panel title="Sites"> 
        <mx:Form id="siteForm"> 
            <mx:HBox> 
                <mx:FormItem label="Site:"> 
                    <mx:TextInput id="ti3" width="400"/> 
                </mx:FormItem> 
                <mx:Button id="b3" label="Add Site" click="addSite()"/> 
            </mx:HBox> 
 
            <mx:FormItem label="Existing Sites:"> 
                <mx:DataGrid 
                    id="mySitesGrid" 
                    dataProvider="{localSites}" 
                    width="400" 
                /> 
            </mx:FormItem> 
            <mx:Button id="b4" label="Remove Site" click="removeSite()"/> 
        </mx:Form> 
    </mx:Panel> 
    
</mx:Application>

共有オブジェクトへの型指定オブジェクトの格納

型指定された ActionScript インスタンスを共有オブジェクトに格納できます。これを行うには、flash.net.registerClassAlias() メソッドを呼び出してクラスを登録します。クラスのインスタンスを作成し、それを共有オブジェクトのデータメンバーに格納して、後にオブジェクトを読み出す場合は、型指定されたインスタンスを取得します。デフォルトでは、SharedObject の objectEncoding プロパティでは AMF3 エンコーディングがサポートされており、SharedObject オブジェクトから格納されたインスタンスがアンパックされます。格納されたインスタンスでは、ユーザーが registerClassAlias() メソッドを呼び出したときに指定したものと同じ型が保持されます。

(iOS のみ)ローカル共有オブジェクトがクラウドでバックアップされないようにする

SharedObject.preventBackup プロパティを設定して、ローカル共有オブジェクトを iOS のクラウドバックアップサービスでバックアップするかどうかを制御できます。これは、再生成や再ダウンロードが可能なものの、オフライン使用時にアプリケーションが適切に機能するために必要なコンテンツに関して、Apple が必須としている設定です。

複数の共有オブジェクトの作成

同じ Flex アプリケーションに対して複数の共有オブジェクトを作成できます。これを行うには、次の例に示すように、共有オブジェクトのそれぞれに異なるインスタンス名を割り当てます。

public var mySO:SharedObject = SharedObject.getLocal("preferences"); 
public var mySO2:SharedObject = SharedObject.getLocal("history");

これによって preferences.sol ファイルおよび history.sol ファイルが Flex アプリケーションのローカルディレクトリに作成されます。

セキュアな SharedObject の作成

getLocal() または getRemote() でローカルまたはリモートの SharedObject を作成する際にオプションの secure というパラメーターを指定すると、その共有オブジェクトについて、HTTPS 経由で配信される SWF ファイルのみにアクセスを制限するかどうかを定義できます。HTTPS 経由で配信される SWF ファイルにおいて、このパラメーターを true に設定すると、セキュアな共有オブジェクトが新しく作成されるか、既存のセキュアな共有オブジェクトに対する参照が取得されます。このセキュアな共有オブジェクトに対する読み取りまたは書き込みは、HTTPS で配信された SWF ファイルによってのみ行えます。このとき SWF ファイルは SharedObject.getLocal() を、secure パラメーターを true に設定して呼び出します。HTTPS 経由で配信される SWF ファイルにおいて、このパラメーターを false に設定すると、共有オブジェクトが新しく作成されるか、既存の共有オブジェクトに対する参照が取得されます。

この場合の共有オブジェクトは HTTPS 以外の接続を経由して配信される SWF ファイルからも読み書きできます。 HTTPS 以外の接続を経由して配信される SWF ファイルにおいて、このパラメーターを true に設定しようとすると、新しい共有オブジェクトの作成(または既存のセキュアな共有オブジェクトへのアクセス)に失敗してエラーがスローされ、共有オブジェクトは null に設定されます。次のコードを、HTTPS 以外の接続を経由して配信される SWF ファイルで実行しようとすると、SharedObject.getLocal() メソッドでエラーがスローされます。

try 
{ 
    var so:SharedObject = SharedObject.getLocal("contactManager", null, true); 
} 
catch (error:Error) 
{ 
    trace("Unable to create SharedObject."); 
}

このパラメーターの値にかかわらず、作成された共有オブジェクトは、各ドメインに割り当てられた総ディスク容量の一部を使用します。

共有オブジェクトのコンテンツの表示

共有オブジェクトに保存する値は、data プロパティ内に格納されます。ループで共有オブジェクトインスタンス内の個々の値にアクセスするには、次のように for..in ループを使用します。

var so:SharedObject = SharedObject.getLocal("test"); 
so.data.hello = "world"; 
so.data.foo = "bar"; 
so.data.timezone = new Date().timezoneOffset; 
for (var i:String in so.data) 
{ 
    trace(i + ":\t" + so.data[i]); 
}

共有オブジェクトの破棄

クライアント上で SharedObject を破棄するには、SharedObject.clear() メソッドを使用します。これによってアプリケーションの共有オブジェクトに対するデフォルトパス内のディレクトリは破棄されません。

次の例では、クライアントから SharedObject ファイルが削除されます。

public function destroySharedObject():void { 
    mySO.clear(); 
}

SharedObject の例

次の例では、Date オブジェクトなどの単純なオブジェクトを手動で直列化または非直列化する必要なく、SharedObject オブジェクトに格納します。

次の例では、まず、ユーザーを初めての訪問者として歓迎します。「Log Out」をクリックすると、アプリケーションによって共有オブジェクトに現在の日付が格納されます。次にユーザーがこのアプリケーションを起動するかページを更新したとき、アプリケーションではユーザーのログアウト時間とともに再訪問歓迎のメッセージが表示されます。

アプリケーションの動作を確認するには、アプリケーションを起動し、「Log Out」をクリックしてから、ページを更新します。ユーザーが前回の訪問時に「Log Out」ボタンをクリックした日付と時間がアプリケーションに表示されます。「Delete LSO」ボタンをクリックすると、格納されている情報をいつでも削除できます。

<?xml version="1.0"?> 
<!-- lsos/WelcomeMessage.mxml --> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initApp()"> 
  <mx:Script><![CDATA[ 
  public var mySO:SharedObject; 
  [Bindable] 
  public var welcomeMessage:String; 
 
  public function initApp():void { 
     mySO = SharedObject.getLocal("mydata"); 
     if (mySO.data.visitDate==null) { 
        welcomeMessage = "Hello first-timer!" 
     } else { 
        welcomeMessage = "Welcome back. You last visited on " + 
           getVisitDate(); 
     } 
  } 
 
  private function getVisitDate():Date { 
     return mySO.data.visitDate; 
  } 
 
  private function storeDate():void { 
     mySO.data.visitDate = new Date(); 
     mySO.flush(); 
  } 
  
  private function deleteLSO():void { 
     // Deletes the SharedObject from the client machine. 
     // Next time they log in, they will be a 'first-timer'. 
     mySO.clear(); 
  } 
  
  ]]></mx:Script> 
  <mx:Label id="label1" text="{welcomeMessage}"/> 
  <mx:Button label="Log Out" click="storeDate()"/> 
  <mx:Button label="Delete LSO" click="deleteLSO()"/> 
</mx:Application>