Red5 - Invoking client methods from application server doesn't work - apache-flex

how would you invoke a client flex method from application in red5-service-1.0.5-RELEASE appliocation .
and my jdk version is 1.8(64-bit).flex 4 ,as3
package org.red5.demos;
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.scope.IScope;
import org.red5.server.api.service.IServiceCapableConnection;
import org.red5.server.api.stream.IServerStream;
/**
* #author user
*
*/
public class Application extends ApplicationAdapter {
private IScope appScope;
private IServerStream serverStream;
#Override
public boolean appStart(IScope app){
super.appStart(app);
System.out.println("hello demo start");
appScope=app;
return true;
}
#Override
public boolean appConnect(IConnection conn,Object[]obj){
IScope appScope=conn.getScope();
System.out.println("appConnect");
callient(conn); //appConnect and calling client method
return super.appConnect(conn, obj);
}
private void callient(IConnection conn){
if(conn instanceof IServiceCapableConnection){
System.out.println("connect to flash side");
((IServiceCapableConnection) conn).invoke("yourFunctionInFlash"); // involing client side method ,but print "connect to flash side"
}
}
//disconnected
#Override
public void appDisconnect(IConnection conn){
if(appScope==conn.getScope() && serverStream!=null){
serverStream.close();
}
super.appDisconnect(conn);
}
}
and my flex side code,in my demo ,,after connect to red5 server application ,the netStatus info is success.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="windowedapplication1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.graphics.codec.JPEGEncoder;
private var cam:Camera;
private var netConnection:NetConnection;
private var netStream:NetStream;**strong text**
protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
{
netConnection=new NetConnection();
netConnection.client = { onBWDone: function():void{} };
netConnection.addEventListener(NetStatusEvent.NET_STATUS,connectionServerHandler);
netConnection.connect("rtmp://192.168.61.132/Hello","ssl");//connect to Hello App
}
public function sayHello(reponder:String):void{
trace(reponder+"from server side ");
}
public function yourFunctionInFlash():void{
trace("hello"); //get message from server side
}
private function connectionServerHandler(event:NetStatusEvent):void{
trace(event.info.code); //it work success
}
]]>
</fx:Script>
</s:WindowedApplication>
but now ,flex side yourFunctionInFlash()method doesn't work,and server side also print "connect to flash side"message?>>> is any other I have missed?
thank you a lot .

Method yourFunctionInFlash should be defined in netConnection.client object. In your case you should assign netConnection.client = this. Also call super.appConnect on back end before invoking client method.

Related

Can't figure out why I'm getting an "Access of undefined object" error in Flex 4.5

I'm very new to Flex 4.5 and I created a class (Project.as) with the following code in it:
package classes
{
public class Project
{
public var projectName:String;
public var description:String;
public var fileLoc:String;
public function Project()
{
// This is the constructor
}
public function SayHello() {
import mx.controls.Alert;
Alert.show('howdy!','Greeting');
}
}
}
In my main.mxml file, I have the following code:
<fx:Script>
<![CDATA[
import classes.Project;
import mx.controls.Alert;
public var aProject:Project = new Project;
aProject.SayHello();
]]>
</fx:Script>
And Flex Builder is saying this:
1120: Access of undefined property aProject.
Why is it telling me this, and how can I fix it? I don't see why it's not working.
Lots of issues here.
First, I have never seen anyone put import statements inside a method. Usually they are put between the package and class definition:
package classes
{
import mx.controls.Alert;
public class Project
{
public var projectName:String;
public var description:String;
public var fileLoc:String;
public function Project()
{
// This is the constructor
}
public function SayHello() {
Alert.show('howdy!','Greeting');
}
}
}
Second; the line of ActionSCript code that you write to call a method on your class instance should be placed inside a method; not "random". Like this:
<fx:Script>
<![CDATA[
import classes.Project;
import mx.controls.Alert;
public var aProject:Project = new Project;
protected function sayHello():void{
aProject.SayHello();
}
]]>
</fx:Script>
Some way you'll want to call that method. A commenter on the original post suggested using creationComplete, which would work. However, you should be cautious about using creationComplete for "constructor-style" code in an MXML Component. preinitialize is better, and the event will fire right after the actual constructor runs. If you need to access any MXML children, have your code in an initialize event handler which runs right after createChildren() runs.
creationComplete handlers execute right after the component finishes initializing; and people often do things in creationComplete that make the component go through it's Lifecycle again, updating the display list.

Linking a webcam in a flex application

i am having a very strange problem while linking a webcam i xperience following error
ArgumentError: Error #2126: NetConnection object must be connected.
at flash.net::NetStream/ctor()
at flash.net::NetStream()
Following is my code in main.mxml
<fx:Script>
<![CDATA[
import flash.media.Camera;
import flash.media.Video;
import flash.net.NetConnection;
import mx.core.UIComponent;
import com.kahaf.plutay.* ;
private var inVideo:Video;
private var outVideo:Video;
private var inVideoWrapper:UIComponent;
private var camera:Camera;
private var mic:Microphone;
private var inStream:NetStream;
private var outStream:NetStream;
private function defaultVideoMode(): void
{
VideoPanel.width = 726;
VideoPanel.height = 494;
inVideo.width = 726;
inVideo.height = 494;
}
private function showInComingVideo():void
{
inVideo = new Video(VideoPanel.width,VideoPanel.height);
inVideo.attachNetStream(inStream);
inVideoWrapper = new UIComponent();
inVideoWrapper.addChild(inVideo);
VideoPanel.addElement(inVideoWrapper);
defaultVideoMode();
}
private function setupVideo(event:MouseEvent): void
{
camera = Camera.getCamera();
mic = Microphone.getMicrophone();
mic.setLoopBack(false);
mic.setUseEchoSuppression(true);
camera.setMode(640,480,20);
camera.setQuality(65536,90);
var conn:NetConnection = Connection.getConnection().conn;
inStream = new NetStream(conn);
inStream.play(conn);
showInComingVideo();
}
]]>
<s:Group x="283" y="330" width="234" height="149" id="VideoPanel" >
</s:Group>
<s:Button x="447" y="151" label="Click Me." click="setupVideo(event)"/>
here is the code of my connection class :
import flash.net.NetConnection;
public class Connection extends NetConnection
{
public static var conObj:Connection;
public var conn:NetConnection;
public var target:Object;
public var selector:Function;
public function Connection()
{
conn = new NetConnection;
target = null;
selector = null;
conn.client = this;
}
public static function getConnection():Connection
{
if(conObj == null)
{
conObj = new Connection();
}
return conObj;
}
}
This the correct order when handling NetConnection and NetStreams:
Create and establish the NetConnection (NetConnection.connect())
Wait for the NetConnection.Connect.Success event (NetStatusEvent.NET_STATUS)
Create your NetStream and attach the connected NetConnection to it
Publish/play your stream

Flex 4: Accessing public method in main application from component

I need to be able to call a method from a component located under the main application in Flex 4. Can anyone tell me please how to do this without using FlexGlobals please?
Sample code is attached. Thanks in advance.
// TestApp.mxml (application)
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="initApp()">
<fx:Script>
<![CDATA[
import com.TestComp;
import mx.managers.PopUpManager;
public function myMethod():void
{
// do something
}
protected function initApp():void
{
var popUp:TestComp = new TestComp();
PopUpManager.addPopUp(popUp, this, true);
}
]]>
</fx:Script>
</s:WindowedApplication>
// TestComp.mxml (component)
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="400" height="300">
<fx:Script>
<![CDATA[
private function doSomething(event:MouseEvent):void
{
// call to myMethod() in TestApp.mxml
}
]]>
</fx:Script>
<s:Button click="doSomething(event)" label="Click Me"/>
</s:Group>
This is bad design. You should provide a callback function or an event listener.
// TestComp.mxml
<mx:Metadata>
[Event(name="doSomethingEvent", type="flash.events.Event")]
</mx:Metadata>
<mx:Script><![CDATA[
private function doSomething(event:MouseEvent):void
{
this.dispatchEvent(new Event("doSomethingEvent"));
}
]]></mx:Script>
// TestApp.mxml
protected function initApp():void
{
var popUp:TestComp = new TestComp();
popUp.addEventListener("doSomethingEvent", myMethod);
PopUpManager.addPopUp(popUp, this, true);
}
private function myMethod(event: Event): void
{
// do something
}
And this is a callback example:
// TestComp.mxml
public var doSomethingCallback: Function;
private function doSomething(event:MouseEvent):void
{
doSomethingCallback.call();
}
// TestApp.mxml
protected function initApp():void
{
var popUp:TestComp = new TestComp();
popUp.doSomethingCallback = myMethod;
PopUpManager.addPopUp(popUp, this, true);
}
private function myMethod(): void
{
// do something
}
Easiest option?
Take out the click handler from the button in TestComp.
In your main app, add a listener to TestComp (if it's a direct child of the main application) or itself (if TestComp is further down the display list) for MouseEvent.CLICK. In the handler, test to see if the event's target is the TestComp either through == if you've got a direct reference, or through "is" if not.
That's the least amount of effort from what you have just now, still relies on (bubbling) events, and is more "correct"
I do agree with splash that it's bad design, but the following should work
//in TestApp
protected function initApp():void
{
var popUp:TestComp = new TestComp(this);
PopUpManager.addPopUp(popUp, this, true);
}
//in TestComp
private var app:TestApp;
public function TestComp(app:TestApp)
{
this.app = app;
}
private function doSomething(event:MouseEvent):void
{
// call to myMethod() in TestApp.mxml
app.myMethod();
}
or you could do it this way
//in TestApp
protected function initApp():void
{
var popUp:TestComp = new TestComp(this);
popUp.addEventListener( 'test' , eventListener );
PopUpManager.addPopUp(popUp, this, true);
}
private function eventListener(event:Event):void
{
//in which case myMethod doesn't need to be public
myMethod();
}
//in TestComp
private function doSomething(event:MouseEvent):void
{
dispatchEvent( new Event('test') );
}

Why is my override protected function createChildren being ignored?

Here is the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at view::ScoreBoard/setChipCount()[C:\Flex Builder 3\StackOverflowQuestion\src\view\ScoreBoard.as:32]
at model::MainDeckScoreBoard()[C:\Flex Builder 3\StackOverflowQuestion\src\model\MainDeckScoreBoard.as:21]
at model::MainDeckScoreBoard$cinit()
at global$init()[C:\Flex Builder 3\StackOverflowQuestion\src\model\MainDeckScoreBoard.as:5]
at main()[C:\Flex Builder 3\StackOverflowQuestion\src\main.mxml:13]
at _main_mx_managers_SystemManager/create()
at mx.managers::SystemManager/initializeTopLevelWindow()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3188]
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::docFrameHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3064]
at mx.managers::SystemManager/docFrameListener()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2916]
Here is main.mxml:
<?xml version="1.0"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()"
>
<mx:Script>
<![CDATA[
import model.MainDeckScoreBoard;
public var _mainDeckScoreBoard:MainDeckScoreBoard = MainDeckScoreBoard.instance;
private function initApp():void {
this.addChild(_mainDeckScoreBoard);
}
]]>
</mx:Script>
</mx:Application>
Here is MainDeckScoreBoard.as:
package model {
import view.ScoreBoard;
[Bindable]
public dynamic class MainDeckScoreBoard extends ScoreBoard {
/** Storage for the singleton instance. */
private static const _instance:MainDeckScoreBoard = new MainDeckScoreBoard( SingletonLock );
/** Provides singleton access to the instance. */
public static function get instance():MainDeckScoreBoard {
return _instance;
}
public function MainDeckScoreBoard( lock:Class ) {
super();
// Verify that the lock is the correct class reference.
if ( lock != SingletonLock ) {
throw new Error( "Invalid Singleton access. Use MainDeckScoreBoard.instance." );
}
this.setChipCount("0");
}
} // end class
} // end package
class SingletonLock {
} // end class
Here is ScoreBoard.as:
package view {
import mx.containers.HBox;
import view.ScoreBoardLabel;
import view.ChipCountContainer;
import view.CardRankList;
public dynamic class ScoreBoard extends HBox {
/** The chip count. */
public var _chipCount:ChipCountContainer;
public function ScoreBoard() {
super();
this.width = 489;
this.height = 40;
this.setStyle("horizontalScrollPolicy", "off");
}
override protected function createChildren():void {
super.createChildren();
if(!_chipCount) {
_chipCount = new ChipCountContainer();
this.addChild(_chipCount);
}
}
public function setChipCount(labelText:String):void {
_chipCount._chipCountLabel.text = labelText;
invalidateDisplayList();
}
}
}
Here is ChipCountContainer.as:
package view {
import mx.containers.Canvas;
public dynamic class ChipCountContainer extends Canvas {
/** The label. */
public var _chipCountLabel:ChipCountLabel;
public function ChipCountContainer() {
super();
this.width = 20;
this.height = 20;
}
override protected function createChildren():void {
super.createChildren();
if(!_chipCountLabel) {
_chipCountLabel = new ChipCountLabel();
this.addChild(_chipCountLabel);
}
}
}
}
I've methodically moved things around and waved the invalidate Display List incense while performing a create Children dance but I've only succeeded in completely confusing myself. I've searched the Flex libraries for similar constructions, and it looks OK to me, but I guess I'm just not getting the concept.
I think you're confusing the order of instantiation. Namely, if you want to use setChipCount after the children of the component have been initialized, you should wait for the initialize event to fire, i.e.:
public dynamic class MainDeckScoreBoard extends ScoreBoard {
...
public function MainDeckScoreBoard( lock:Class ) {
super();
// Verify that the lock is the correct class reference.
if ( lock != SingletonLock ) {
throw new Error( "Invalid Singleton access. Use MainDeckScoreBoard.instance." );
}
// wait for the children to be created
addEventListener(FlexEvent.INITIALIZE, onInitialize);
}
// executes when the children of this component have been created
private function onInitialize(event:FlexEvent):void {
this.setChipCount("0");
}
} // end class
For a more detailed explanation of the component instantiation lifecycle, this adobe doc may be helpful:
http://livedocs.adobe.com/flex/3/html/help.html?content=components_06.html

How do I get rid of a null StyleProtoChain object reference?

Here is the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.styles::StyleProtoChain$/initProtoChainForUIComponentStyleName()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\styles\StyleProtoChain.as:72]
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::initProtoChain()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:7469]
at mx.core::UIComponent/regenerateStyleCache()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:7690]
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::addingChild()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5239]
at mx.core::UIComponent/addChild()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:4955]
at mx.controls.listClasses::ListBase/createChildren()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\listClasses\ListBase.as:3103]
at mx.core::UIComponent/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5370]
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5267]
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:3305]
at mx.core::Container/addChildAt()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2217]
at mx.core::Container/addChild()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2140]
at model::MessageBoard()[C:\Documents and Settings\dbabbitt\My Documents\Flex Builder 3\ListExample\src\model\MessageBoard.as:56]
at model::MessageBoard$cinit()
at global$init()[C:\Documents and Settings\dbabbitt\My Documents\Flex Builder 3\ListExample\src\model\MessageBoard.as:7]
at main()[C:\Documents and Settings\dbabbitt\My Documents\Flex Builder 3\ListExample\src\main.mxml:56]
at _main_mx_managers_SystemManager/create()
at mx.managers::SystemManager/initializeTopLevelWindow()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3188]
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::docFrameHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3064]
at mx.managers::SystemManager/docFrameListener()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2916]
Here is main.mxml:
<?xml version="1.0"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
>
<mx:Script>
<![CDATA[
import model.MessageBoard;
public var _messageBoard:MessageBoard = MessageBoard.instance;
]]>
</mx:Script>
</mx:Application>
Here is MessageBoard.as:
package model {
import mx.containers.VBox;
import mx.controls.Label;
[Bindable]
public class MessageBoard extends VBox {
/** The message list title. */
private var _messageTitle:Label;
/** The maximum message count. */
private var _maxMessageCount:int = 4;
/** Storage for the singleton instance. */
private static const _instance:MessageBoard = new MessageBoard( SingletonLock );
/** Provides singleton access to the instance. */
public static function get instance():MessageBoard {
return _instance;
}
/**
* Constructor
*
* #param lock The Singleton lock class to pevent outside instantiation.
*/
public function MessageBoard( lock:Class ) {
super();
// Verify that the lock is the correct class reference.
if ( lock != SingletonLock ) {
throw new Error( "Invalid Singleton access. Use MessageBoard.instance." );
}
_messageTitle = new Label();
_messageTitle.text = "Message Board";
this.addChild(_messageTitle);
}
} // end class
} // end package
class SingletonLock {
} // end class
Maybe you could school me in how to keep null object references out of complex Classes?
Thanx
Dave
It looks like the error may be coming from the call to the addChild() method in the constructor of your MessageBoard class. You may very well be invoking this method too early in the UIComponent lifecycle. I would recommend overriding the createChildren() method and adding your child element(s) there.
override protected function createChildren():void
{
super.createChildren();
_messageTitle = new Label();
_messageTitle.text = "Message Board";
this.addChildAt(_messageTitle, 0);
}

Resources