views:

336

answers:

5

Hey all,

I'm looking for a way to play flash animated content once ( even as the user navigates to different HTML pages with similar flash content) and expire after a set amount of time or after the browser is closed.

I'm aware I could use a shared object for this but can't seem to find info about how to clear them at browser session end.

I am open to using javascript or PHP to assist .

your help is appreciated - thanks -MW

+2  A: 

Instead of using a SharedObject, you could create two simple server-side services: one that maintains the session, and one that exposes the session through a generated XML file that your flash application could use.

The first service would set some session variables and should be called whenever the video is played. It could look like this:

<?php
// start-video.php
session_start();
$_SESSION['hasWatchedVideo'] = true;
$_SESSION['watchedVideoAt'] = time();
?>

The second service is the one that generates the XML response based on the session. It might look like this:

<?php
// flash-config.php
session_start();

// set expiration to 5 min
define(VIDEO_TIMEOUT, 300);

$playVideo = "true";
if($_SESSION['hasWatchedVideo']
    && (time() - $_SESSION['watchedVideoAt']) < VIDEO_TIMEOUT) {
    $playVideo = "false";
}

header("Content-Type: text/xml");

echo "<config><playVideo>{$playVideo}</playVideo></config>";

?>

Then from your Flash application, you could do this:

/**
 * Called whenever the app is loaded.
 */
protected function init():void {
    var u:URLLoader = new URLLoader();
    u.addEventListener(Event.COMPLETE, onComplete);
    u.load(new URLRequest("http://example.com/flash-config.php"));
}

/**
 * Determines whether or not the video should play based on the
 * config service response.
 */
protected function onComplete(e:Event):void {
    var x:XML = new XML(e.target.data);
    if(x.playVideo == 'true') {
        playVideo();
    }
}

/**
 * Should be called either when the video starts playing. I just tied
 * it to a user click here.
 */
protected function playVideo():void {
    // call the service to update the session
    var u:URLLoader = new URLLoader();
    u.load(new URLRequest("http://example.com/start-video.php"));
    // ... play video code ...
}

I think this approach gives you a bit more flexibility than using a SharedObject. Hope that helps.

UPDATE:

You could use a session cookie in the browser as well. Basically set the expiry date to '0' and the cookie will expire when the user closes the browser. (Note: when I tested this in Firefox, closing the tab was not enough to kill the cookie. The entire browser had to be closed.)

You can use ExternalInterface, or a utility library like this. Using the library, you could have code like this in your flash application:

function playVideo():void {
    if(!CookieUtil.getCookie('playvideo')) {
        CookieUtil.setCookie('playvideo', 'true', 0);
        // ... play video code ...
    }
}

Whenever the user closes the browser, the cookie will be cleared. Next time they visit your site, the video will play again. Not sure if this is more inline with what you're look for, but hope it helps.

RJ Regenold
A: 

thanks -- RJ !!

just tested that out on a local network and it works great.

A timed cookie is more inline with what I was after and should work pretty good.

The ultimate solution for me would have it possible to kill the cookie when the ( session ends / browser closes ), though I'm not sure how this would be achieved.

thanks again - MW

MW
I updated my answer (check the bottom) with a way to use a session based cookie in the browser. Maybe that is more of what you're looking for?
RJ Regenold
A: 

I modified your code a tad so it will be killed on sesion end ...

the PHP ...

<?php
//          flash_php_session_cookie.php

$cookie= "false";

if (isset($_COOKIE["cookie"]))
  $cookie= "true";
else
 setcookie("cookie", "true", 0);

echo "<config><cookie>{$cookie}</cookie></config>";

?>

the FLASH ...

// the folowing functions handle call coresponding PHP files to handle cookies ...    

// re-configure these to the location of the swf ... 
var flashConfigURL:String ="flash_php_session_cookie.php";

//Called whenever the app is loaded ...
function initCookieFunc():void {
    var u:URLLoader = new URLLoader();
    u.addEventListener(Event.COMPLETE, onComplete);
    u.load(new URLRequest(flashConfigURL));
}

// Determines whether or not the cookie exists / (assumes theres a text field named T on the stage) ... 
function onComplete(e:Event):void {
    var x:XML = new XML(e.target.data);
    if (x.cookie == 'false') {
        T.appendText("cookie doesn't exist yet");
    } else {
        // cookie exists ... 
        T.appendText("cookie exists");
    }
}

initCookieFunc();

I am going to keep a loose version of the "TIMEOUT" version as well. It's great to have an answer to this

Thanks again RJ for the invaluable code

-MW

MW
A: 

You'll just have to expire the SharedObject yourself. It's not complicated. This way your .swf will be completely self contained, not relying on anything external which IMO is a good thing.

package {

 import flash.display.Sprite;
 import flash.net.SharedObject;
 import flash.net.SharedObjectFlushStatus;

 public class SharedObjectExample extends Sprite {

  private var _so:SharedObject;
  private var _now:Date;
  private var _last_played:Number;
  private static const EXPIRE_TIME:Number = 1000 * 60 * 60 * 24; // 24hrs in msec

  public function SharedObjectExample() {
   // create a new date for the current time to compare against
   _now = new Date;

   // create a new shared object
   _so = SharedObject.getLocal("application-name", "/");

   // try read from the shared object
   if (_so.data.last_played) _last_played = _now;

   // if no value is set we play the video and set the current time
   if (!_last_played) {
    // play video here
    _last_played = _now.time;

   // check if the "cookie" has expired and it's time to play again
   } else if ( _now.time - _last_played > EXPIRE_TIME) {
    // play video here
    _last_played = _now.time;
   } else {
    // do nothing
   }

   // and finally, save
   saveValue();
  }

  private function saveValue(event:MouseEvent):void {
   // i've removed the code that asks the user for permission if the request for storage is denied
   _so.data.last_played = _last_played;
   var flushStatus:String = null;
   try {
    flushStatus = _so.flush(1000);
   } catch (error:Error) {
    trace("Could not write SharedObject to disk");
   }
  }
 }
}
grapefrukt
also, note that you need to use Number instead of int because of the large numbers involved which will overflow int
grapefrukt
A: 

thanks grapefrukt -

after a bit of tweeking, I found that method to work pretty well, and it's good to keep it all self contained. The big disadvantage is that this technique does not remove the cookie after each browser session ( rather it relies on a timed method ),

I'm still looking to see if it's possible with a shared cookie - I suspect it's not .

-thanks MW

MW