Copy link to clipboard
Copied
Hello everyone,
A major concern arises for me, and after several days of testing I can not find a solution.
I am currently developing a mobile application on Android to play a video locally.
For this I use the Adobe SimpleStageVideo class available on the website : http://www.adobe.com/devnet/flashplayer/articles/stage_video.html
At the launch all goes well , however when I switch to another application in full reading and then I go back to my video .
That passes over other elements of my interface (ie the navigation menu ) and especially it grows.
I tried to do a resize an event type activate ( to intercept the return on applicaiton )
I also tried to remove the container, and then reinject the video in my interface ( although this is costly in resources ... ) .
It did not work .
I think during my event "activate " the UIComponent has not yet been fully rebuilt, and thereby resize does not work on a good screen size used (since it does not blow conscidère menus ) .
To test my theory , I tested passing in debug mode. By running my code slower, the video goes back to the right size ...
So I tried to put timers, but again it was a futile attempt .
How is it possible when returning to my application that my video remains the right size , and not overlooking the rest of the menus?
Here follows the code in question :
// La Vue Permettant de Visionner la Vidéo
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:components="bouton.components.*"
xmlns:s="library://ns.adobe.com/flex/spark" title="viewVideo" activate="view1_activateHandler(event)" creationComplete="view1_creationCompleteHandler(event)" backgroundAlpha="0" actionBarVisible="false" tabBarVisible="false">
<fx:Script>
<![CDATA[
import flash.events.MouseEvent;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import valueObjects.SimpleStageVideo;
private var conn:SQLConnection;
private var createStmt:SQLStatement;
public var dbFile:File;
public var fichierCharge:File;
public var numeroBouton:int = 0;
private var test:SimpleStageVideo = new SimpleStageVideo();
private var container:UIComponent = new UIComponent();
protected function view1_creationCompleteHandler(event:FlexEvent):void
{
var chemin:File = new File(data.url);
test.setData(chemin);
//container.stage = this.stage;
container.height = stage.height;
container.width = stage.width;
container.addChildAt(test, 0);
addElementAt(container, 0);
trace(""+container.width+" : "+container.height+" : "+container.x+" : "+container.y);
}
protected function view1_activateHandler(event:Event):void
{
test.resize();
}
private function resizeF(event:Event):void
{
test.resize();
}
]]>
</fx:Script>
<s:HGroup id="barremenu" gap="0" horizontalAlign="left" styleName="header_style" verticalAlign="top" width="100%" contentBackgroundColor="#FFFFFF" contentBackgroundAlpha="1" paddingBottom="50" >
<s:Image scaleMode="letterbox" smooth="true" smoothingQuality="high"
source="assets/header_droi.jpg" />
<components:Boutton_Retour click="boutton_retour1_clickHandler(event)" enabled="true" height="100%" contentBackgroundColor="#FFFFFF" contentBackgroundAlpha="1"/>
<components:Boutton_Accueil_Retour click="boutton_accueil1_clickHandler(event)" enabled="true" height="100%" contentBackgroundColor="#FFFFFF" contentBackgroundAlpha="1" />
<s:Image scaleMode="stretch" smooth="true" smoothingQuality="high"
source="assets/header_milieu.jpg" fillMode="repeat" width="60%" height="99%" />
<s:Image scaleMode="stretch" smooth="true" smoothingQuality="high"
source="assets/ipad.jpg" />
</s:HGroup>
</s:View>
// Ma Classe SimpleStageVideo
package valueObjects
{
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.StageVideoAvailabilityEvent;
import flash.events.StageVideoEvent;
import flash.events.VideoEvent;
import flash.filesystem.File;
import flash.geom.Rectangle;
import flash.media.StageVideo;
import flash.media.StageVideoAvailability;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import mx.core.UIComponent;
import spark.components.Image;
import spark.components.NavigatorContent;
[SWF(frameRate="1", backgroundColor="#000000")]
public class SimpleStageVideo extends Sprite
{
public var chemin:File;
private var FILE_NAME:String = "";
private static const INTERVAL:Number = 500;
private static const BORDER:Number = 20;
private var legend:TextField = new TextField();
private var sv:StageVideo;
private var nc:NetConnection;
private var ns:NetStream;
private var rc:Rectangle;
private var video:Video;
private var thumb:Shape;
private var interactiveThumb:Sprite;
private var totalTime:Number;
private var videoWidth:int;
private var videoHeight:int;
private var outputBuffer:String = new String();
private var rect:Rectangle = new Rectangle(0, 0, 0, BORDER);
private var videoRect:Rectangle = new Rectangle(0, 0, 0, 0);
private var gotStage:Boolean;
private var stageVideoInUse:Boolean;
private var classicVideoInUse:Boolean;
private var accelerationType:String;
private var infos:String = new String();
private var available:Boolean;
private var inited:Boolean;
private var played:Boolean;
private var container:Sprite;
private var displayButtonPause:Boolean;
public var imagePause:UIComponent;
public var pLoad:Loader;
private var testResize:Boolean = false;
private var widthStage:int = 0;
/**
*
*
*/
public function SimpleStageVideo()
{
// Make sure the app is visible and stage available
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
//addEventListener(Event.ACTIVATE, onActivate);
}
private function onActivate(event:Event):void
{
video.addEventListener(Event.RENDER, functionResize);
}
private function functionResize(event:Event):void
{
resize();
}
/**
*
* @param event
*
*/
private function onAddedToStage(event:Event):void
{
// Scaling
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
widthStage = stage.width;
// Thumb seek Bar
thumb = new Shape();
interactiveThumb = new Sprite();
interactiveThumb.addChild(thumb);
addChild(interactiveThumb);
// Connections
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
ns.client = this;
// Screen
video = new Video();
video.smoothing = true;
// Video Events
// the StageVideoEvent.STAGE_VIDEO_STATE informs you if StageVideo is available or not
stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onStageVideoState);
// in case of fallback to Video, we listen to the VideoEvent.RENDER_STATE event to handle resize properly and know about the acceleration mode running
video.addEventListener(VideoEvent.RENDER_STATE, videoStateChange);
// Input Events
stage.addEventListener(MouseEvent.DOUBLE_CLICK, onKeyDown);
stage.addEventListener(Event.RESIZE, onResize);
stage.addEventListener(MouseEvent.CLICK, onClick);
}
/**
*
* @param event
*
*/
private function onNetStatus(event:NetStatusEvent):void
{
if ( event.info == "NetStream.Play.StreamNotFound" )
legend.text = "Video file passed, not available!";
}
public function setData(chem:File):void
{
chemin = chem;
FILE_NAME = chemin.url;
}
/**
*
* @param event
*
*/
private function onFrame(event:Event):void
{
var ratio:Number = (ns.time / totalTime) * (widthStage+470);
rect.width = ratio;
thumb.graphics.clear();
thumb.graphics.beginFill(0xFF0000);
thumb.graphics.drawRect(rect.x, rect.y+350, rect.width+120, rect.height);
//thumb.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
//testResize = true;
}
/**
*
* @param event
*
*/
private function onClick(event:MouseEvent):void
{
//ns.pause();
if ( event.stageY >= interactiveThumb.y - BORDER && event.stageX <= stage.stageWidth - BORDER )
{
var seekTime:Number = (stage.mouseX - BORDER) * ( totalTime / (stage.stageWidth - (BORDER << 1) ) );
ns.seek( seekTime );
}
}
/**
*
* @param event
*
*/
private function onKeyDown(event:MouseEvent):void
{
ns.togglePause();
// Affichage du bouton d'affichage de la mise en pause de la video
if(displayButtonPause == false)
{
pLoad = new Loader();
pLoad.load(new URLRequest("assets/pause.png"));
//imagePause = new UIComponent();
//imagePause.addChild(pLoad);
//imagePause.x = 200;
//imagePause.y = 200;
pLoad.x = (stage.width - (stage.width/3.5));
pLoad.y = (stage.height - (stage.height/3.5));
addChild(pLoad);
displayButtonPause = true;
pLoad.visible = true;
} else
{
displayButtonPause = false;
pLoad.visible = false;
removeChild(pLoad);
}
}
/**
* Permet l'arret de la video avant la supression de la vue
*/
public function arretVideo():void
{
//video.clear();
//sv.attachNetStream(null);
ns.close();
//video.attachNetStream(null);
/*var nce:NetConnection = new NetConnection();
nce.connect(null);
sv.attachNetStream(new NetStream(nce));
//sv.attachNetStream();*/
}
/**
*
* @param width
* @param height
* @return
*
*/
private function getVideoRect(width:uint, height:uint):Rectangle
{
trace("Width" + width);
trace("Stage Width" + stage.stageWidth);
trace("Height" + height);
trace("Stage height" + stage.stageHeight);
var videoWidth:uint = width;
var videoHeight:uint = height;
var scaling:Number = Math.min ( stage.stageWidth / videoWidth, stage.stageHeight / videoHeight );
videoWidth *= scaling, videoHeight *= scaling;
var posX:uint = stage.stageWidth - videoWidth >> 1;
var posY:uint = stage.stageHeight - videoHeight >> 1;
videoRect.x = posX;
videoRect.y = posY;
videoRect.width = videoWidth;
videoRect.height = videoHeight;
trace("Objet video width" + video.width);
trace("Objet video height" + video.height);
trace("Objet video rect width" + videoRect.width);
trace("Objet video rect height" + videoRect.height);
return videoRect;
}
/**
*
*
*/
public function resize ():void
{
if ( stageVideoInUse )
{
// Get the Viewport viewable rectangle
rc = getVideoRect(sv.videoWidth, sv.videoHeight);
// set the StageVideo size using the viewPort property
sv.viewPort = rc;
} else
{
// Get the Viewport viewable rectangle
rc = getVideoRect(video.videoWidth, video.videoHeight);
// Set the Video object size
video.width = rc.width;
video.height = rc.height;
video.x = rc.x, video.y = rc.y;
//trace(""+rc.width+" : "+rc.height+" : "+rc.x+" : "+rc.y);
testResize = true;
}
interactiveThumb.x = BORDER, interactiveThumb.y = stage.stageHeight - (BORDER << 1);
legend.text = infos;
}
/**
*
* @param evt
*
*/
public function onMetaData ( evt:Object ):void
{
totalTime = evt.duration;
stage.addEventListener(Event.ENTER_FRAME, onFrame);
}
/**
*
* @param event
*
*/
private function onStageVideoState(event:StageVideoAvailabilityEvent):void
{
// Detect if StageVideo is available and decide what to do in toggleStageVideo
toggleStageVideo(available = inited = (event.availability == StageVideoAvailability.AVAILABLE));
}
/**
*
* @param on
*
*/
private function toggleStageVideo(on:Boolean):void
{
infos = "StageVideo Running (Direct path) : " + on + "\n";
// If we choose StageVideo we attach the NetStream to StageVideo
if (on)
{
stageVideoInUse = true;
if ( sv == null )
{
sv = stage.stageVideos[0];
sv.addEventListener(StageVideoEvent.RENDER_STATE, stageVideoStateChange);
}
sv.attachNetStream(ns);
if (classicVideoInUse)
{
// If we use StageVideo, we just remove from the display list the Video object to avoid covering the StageVideo object (always in the background)
stage.removeChild ( video );
classicVideoInUse = false;
}
} else
{
// Otherwise we attach it to a Video object
if (stageVideoInUse)
stageVideoInUse = false;
classicVideoInUse = true;
video.attachNetStream(ns);
stage.addChildAt(video, 0);
}
if ( !played )
{
played = true;
ns.play(FILE_NAME);
}
}
/**
*
* @param event
*
*/
private function onResize(event:Event):void
{
resize();
}
/**
*
* @param event
*
*/
private function stageVideoStateChange(event:StageVideoEvent):void
{
infos += "StageVideoEvent received\n";
infos += "Render State : " + event.status + "\n";
trace(infos);
resize();
}
/**
*
* @param event
*
*/
private function videoStateChange(event:VideoEvent):void
{
infos += "VideoEvent received\n";
infos += "Render State : " + event.status + "\n";
trace(infos);
resize();
}
}
}
Copy link to clipboard
Copied
Anyone has an idea ?
Copy link to clipboard
Copied
Hi,
Don't know if this is an entirely valid answer as I write pure AS3 (no Flex).
I remember having problems about a year ago with the SimpleStageVideo when doing a video app that would work for both Apple and Android.
I couldn't get it to work as I wanted so I skipped SimpleStageVideo alltogether.
I ended up using this script to shift between StageVideo (iOS) and the usual videoPlayer (Android).
The stageVideo checks if a menu is open (on the left side) and draws the rect according to that.
The normal video gets it's size from the videoSprite which scales depending on the menu visibility.
Later when StageVideo became available for Android it still worked.
Hopefully it can help you get closer to a solution.
private function load_video():void{
if ( stage.stageVideos.length >= 1 ) {
stageVideo = stage.stageVideos[0];
try {
if(S.application.menu.toggleOpen == true){
stageVideo.viewPort = new Rectangle(S.device.scaledVideo.x, S.device.scaledVideo.y, S.device.scaledVideo.width, S.device.scaledVideo.height);
} else if(S.application.menu.toggleOpen == false){
stageVideo.viewPort = new Rectangle(S.device.video.x, S.device.video.y, S.device.video.width, S.device.video.height);
}
} catch(e:Error) {}
stageVideo.addEventListener(StageVideoEvent.RENDER_STATE, renderState);
stageVideo.attachNetStream(netStream);
} else {
try {
video = new Video(S.device.video.width, S.device.video.height);
video.smoothing = true
video.name = "video"
video.x = S.device.video.x
video.y = S.device.video.y
videoSprite.addChild(video);
video.attachNetStream(netStream);
} catch(e:Error) {}
}
netStream.play(S.path.video + S.application.xmlObjectArray[currentSlideIndex].video);
videoStarted = true
}