Adobe Air, packaged install fails with my trace routine... how come? - actionscript-3

I cobbled together some code from here and there for a trace I like... it generates an error to get a stack trace and picks out the traced routine name, I like that detail in the trace log.
Problem: it fails in an installed AIR file. I wonder why? I don't expect it to do anything as is... just, I'd prefer it not cause the program to fail!
tx
artie
enter code here
static public function XTRACE( ... traceArgs ):void {
try {
throw new Error(); // make a stack
} catch (e:Error) {
var stack:String = e.getStackTrace();
var frames:Array = stack.split("\n");
var myFrame:String = String(frames[2]);
myFrame = myFrame.replace("\t", "");
// "at " can be followed by some part of the package
// you don't want to see. E.g., if your code is all in
// com.foo.bar, you can put "at com.foo.bar." so as not
// to crowd the display
myFrame = myFrame.substr("at ".length);
myFrame = myFrame.substring(0, myFrame.indexOf("["));
var now:Date = new Date();
trace(new Date().toLocaleTimeString() + ":" + myFrame + ": " + traceArgs.join(" "));
}
}

In what way is your app failing?
1) Trace routines are for debugging, so your trace won't do anything in an installed app.
2) I'm not sure when you call this routine, but it seems weird that you have a routine that only throws an error. I think in this code the 'catch' is only going to get entered if there's an error throwing the error. Normally you would try to perform some useful action, and catch errors when something goes wrong.

Within the trace function your attempting to invoke the Date().toLocaleTimeString() statically before it becomes instantiated by the new keyword. Try the following instead:
trace((new Date()).toLocaleTimeString() + ":" + myFrame + ": " + traceArgs.join(" "));

thanks for your input Fergal. The XTRACE function works fine running with the debug player, and fails only when running with the release player. So I assume the code line I use must associate values in the right order... I settled on using a function I didn't know about before:
enter code here
static public function XTRACE( ... traceArgs ):void {
if ( Capabilities.isDebugger ) {
With that, XTRACE does nothing unless it is executing in a debug environment. So it works around the issue. I'll still use your brackets though, I like to make order of association obvious too ;-)

I realize you've probably grown old and forgot what flash is since you asked this question. But, you're getting an NPE because e.getStackTrace() returns null in the release player.
A couple other things:
You don't need to throw the error to get a stack trace; new Error().getStackTrace() works fine.
Since this is debug code, and the calling code probably isn't expecting errors, you should wrap the whole thing in a try catch.
The compiler won't resolve 'at '.length, so it will be called every time at runtime. Unless you're really paranoid, you can just hard code it to 3.
Both the substrs can be combined into 1
The now variable isn't used.

Related

Split is not a function?

I have this code I was testing with:
var test:String="Hello there; im zane"
var parts:Array=test.split(";");
trace(parts)
trace(parts[0])
var randomnum:Number=0;
stage.addEventListener(Event.ENTER_FRAME, code)
function code(c:Event):void{
if(parts[randomnum] != undefined && parts[randomnum] != null){
parts[randomnum]=parts[randomnum].split(" ");
randomnum+=1
trace(parts[randomnum])
}
else{
randomnum=0
}
}
And there is an error with this parts[randomnum]=parts[randomnum].split(" ");. Flash says that split is not a function (
TypeError: Error #1006: split is not a function.
at Untitled_fla::MainTimeline/code()
)
Earlier in this project, I used the split function with a different part of the variable, and I also tried parts[0]=parts[0].split(" ") out of the event and it worked fine.
What I'm trying to find out is, why does a split command not work in this scenario? Am I doing something wrong?
I also tried parts[0]=parts[0].split(" ") out of the event and it worked fine.
Even outside of the event, this line doesn't make much sense, because it assigns the return value of split() to the same variable that the method was invoked on. As the ENTER_FRAME is repeatedly executed, this fails on the second time it happens, because split() returns an Array which has no such method itself, which is what the error is basically saying.

ActionScript 3.0 Error #1010 - preloader function

I am a Flash and ActionScript newbie. I am trying to follow a video tutorial to make a preloader and I'm having a problem that the video didn't seem to address. I believe I have entered in all of the code correctly from the video. This is it:
stop();
addEventListener(Event.ENTER_FRAME, loaderF);
function loaderF(e:Event):void{
var toLoad:Number = loaderInfo.bytesTotal;
var loaded:Number = loaderInfo.bytesLoaded;
var total:Number = loaded/toLoad;
if( loaded == toLoad ){
removeEventListener(Event.ENTER_FRAME, loaderF);
gotoAndStop(2);
} else {
preloader_mc.preloaderFill_mc.scaleX = total;
preloader_mc.percent_txt.text = Math.floor( total * 100 ) + "%";
preloader_mc.ofBytes_txt.text = loaded + "bytes";
preloader_mc.totalBytes_txt.text = toLoad + "bytes";
}
}
What I typed in doesn't generate a compiler error, but the output tells me:
TypeError: Error #1010: A term is undefined and has no properties.
at preloader_fla::MainTimeline/loaderF()
And since I really don't have any experience outside of what I'm learning from this tutorial series, I don't know what to do to fix this.
I don't use Flash CS5, but you should be able to get the line # for where the error is occurring, I believe, by executing the SWF by pressing CTRL+SHIFT+ENTER.
Once you get the line number, you should see that something on that line is null or not defined. The error says it occurs in the function loaderF(), and looking at that code the only place such an error could occur is in the else block:
} else {
preloader_mc.preloaderFill_mc.scaleX = total;
preloader_mc.percent_txt.text = Math.floor( total * 100 ) + "%";
preloader_mc.ofBytes_txt.text = loaded + "bytes";
preloader_mc.totalBytes_txt.text = toLoad + "bytes";
}
In the above code block, one of these things is not defined:
preloader_mc.preloaderFill_mc,
preloader_mc.percent_txt,
preloader_mc.ofBytes_txt,
preloader_mc.totalBytes_txt
Maybe your preloader movie clip is missing one of these objects...
First, you'll want to turn on debugging found under (File > Publish Settings > Flash (.swf) > Permit Debugging). This will provide line numbers and allow additional debugging to help track down errors.
Secondly, in the code sample you've provided, you haven't declared a loader, so when you call on loaderInfo, it makes sense that flash complains about "a term is undefined". Although, technically, the loaderInfo object is a child of the event object. Thus, loaderInfo.bytesTotal would become e.loaderInfo.bytesTotal, assuming you added the event listener to the loader object; currently yours is added to the timeline.
Bookmark Adobe's Actionscript 3.0 Reference. Use it. As you begin your journey in Flash, this will be your indispensable handbook to speaking AS3. Specifically, you'll want to refer to the Loader class.
Here's what you're likely missing in your code:
var myLoader:Loader = new Loader();
myLoader.load(new URLRequest("path/to/my/file"));
Your function loaderF is being called during every frame update to the screen (likely every .034 seconds). You'd probably be happier with ProgressEvent.PROGRESS instead of Event.ENTER_FRAME. If so, you'll also want to catch the complete event, and that'd look like this:
myLoader.addEventListener(Event.COMPLETE, loadComplete);
myLoader.addEventListener(ProgressEvent.PROGRESS, loadProgress);
function loadComplete(e:Event):void {
// Stuff to do when the file finishes loading.
}
function loadProgress(e:Event):void {
var current:int = e.bytesLoaded;
var total:int = e.bytesTotal;
var percent:Number = current/total;
// Update the readout of your loading progress.
}
Hopefully that points you in the right direction. :)

Adobe Cirrus Error on Direct Connect"Property startTransmit not found on flash.net.NetStream"

The error:
ReferenceError: Error #1069: Property startTransmit not found on flash.net.NetStream and there is no default value.
I've played around with cirrus plenty of times before and have yet to see this error before. But now I cant get it to go away.
My p2p Direct connect works great just fine. But every single time i see this error pop up. It throws an exception. I can't figure out where it's exactly happening.
Has anyone encountered this before? Any ideas where I should look?
Every client object needs to have the following functions defined.
client.stopTransmit=function($p1:*,$p2:*):void{
trace("stopTransmit called",$p1,$p2);
}
client.startTransmit=function():void{
trace("startTransmit called");
}
For example, set these in the onPeerConnect function:
sendStream.client = new Object();
sendStreamClient.onPeerConnect = function(subscriber:NetStream): Boolean{
var client:Object=new Object();
client.stopTransmit=function($p1:*,$p2:*):void{
trace("stopTransmit called",$p1,$p2);
}
client.startTransmit=function():void{
trace("startTransmit called");
}
subscriber.client=farStreamClient;
}
Additionally these need to be set on your sendStreamClient's client property:
sendStreamClient.client.stopTransmit=function($p1:*,$p2:*):void{
trace("stopTransmit called",$p1,$p2);
}
sendStreamClient.client.startTransmit=function():void{
trace("startTransmit called");
}
And they need to be set on your recieveStreamClient's client property.
On the server side script, you probably (or somebody else) have set up the application, so that it calls back a function -this time it is startTransmit-, and it isn't handled on the client side.
Remove the code from the server, or add a default value, or add a function to your code.
In my similar program, i had to add the function to my code (in my case it was not 'startTransmit') :
if ("NetConnection.Connect.Success" == e.info.code) {
netConnection.client=new Object();
netConnection.client.startTransmit=startTransmit; //no columns!
}
where startTransmit is
private function startTransmit():Boolean{
return true;
}
Are you sending h264 videos? I think it is to do with that...
If you add
public function startTransmit($p1:*,$p2:*):void{
}
public function stopTransmit():void{
}
where you have your media server connection it should work fine, at least it does for me :)
There is another netstream other than receiveStream and sendStream. You should set startTransmit and stopTransmit functions on the callerns netstream, something like this:
sendStreamClient.onPeerConnect = function(callerns:NetStream): Boolean{
var farStreamClient:Object=new Object();
farStreamClient.stopTransmit=function($p1:*,$p2:*):void{
trace("-------------farStream stopTransmit called!",$p1,$p2);
}
farStreamClient.startTransmit=function():void{
trace("-------------farStream startTransmit called!");
}
callerns.client=farStreamClient;
}
The problem is not on AMS or Red5 server. Even transmitting a video on P2P from an Android device triggers the same error.
The solution worked.
Actually the stopTransmit() sends a Boolean and an integer.
It would be amazing to know what they mean.
I have opened a bug on adobe bugbase in order to have it documented or removed.
Please vote:
https://bugbase.adobe.com/index.cfm?event=bug&id=3844856

Trying to connect to AMFPHP - NetConnection.connect() returns TypeError: Error #1009

UPDATE: Now I've moved the AMFConnection var declaration to outside the functions in Main, and commented out some trace() commands, and now it gives new errors:
Error #2044: Unhandled NetStatusEvent:. level=error, code=NetConnection.Call.BadVersion
at AMFConnection/init()[/Users/Jan/Downloads/amfphp1/AMFConnection.as:32]
at AMFConnection()[/Users/Jan/Downloads/amfphp1/AMFConnection.as:23]
at Main/testConnection()[/Users/Jan/Downloads/amfphp1/Main.as:14]
at Main()[/Users/Jan/Downloads/amfphp1/Main.as:10]
All of these essentially point to AMFConnection's NetConnection initialisation: _netConnection = new NetConnection(); (where _netConnection is declared at the beginning of the class)
I'm trying to connect to AMFPHP on a server (with Flash AS3), and the swf borks when it reaches the .connect() stage. To make things easier (?) and more reusable (?), I've put all the NetConnection mechanics into a separate class, AMFConnection, which I call from the Main document class like this (details changed):
public function testConnection(e:*=null):void {
var conn:AMFConnection = new AMFConnection();
conn.table = "some_table";
conn.selections = "*";
conn.conditionals = "WHERE something = 'something'";
conn.service = "QueryAMF";
conn.method = "makeQuery";
conn.displayText = txt;
conn.gogogo("http://www.someplace.com/Amfphp");
}
AMFConnection actually starts the connection and calls the AMFPHP service with the function gogogo(), and here's where the connect() NetConnection function just won't work. Here's the main section of the AMFConncection class
private var _netConnection:NetConnection;
private var _responder:Responder;
function AMFConnection()
{
init();
}
private function init(e:* = null)
{
_netConnection = new NetConnection();
_responder = new Responder(uponResult);
}
public function gogogo(url:String):void {
trace(url);
_netConnection.connect(url);
_netConnection.call(String(service+"/"+method), new Responder(onResult, null), table, selections, conditionals);
}
A quick debug session reveals the below errors:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at AMFConnection/gogogo()[AMFConnection.as:44]
at Main/testConnection()[Main.as:20]
at Main()[Main.as:8]
Where: Main.as:20 = conn.gogogo(...), and AMFConnection.as:44 = _netConnection.connect(url);
It also fails to display the stage, instead showing the loading dots. Now, eventually I'm going to move this application to the same server as the AMFPHP service, but even when I try it there with a relative url, instead of an absolute one, it still breaks down at connect(). I've tried changing the publish settings from local only to network only, to no avail.
Any clues? Know a better way to connect to AMFPHP locally?
Cheers in advance!
JB
P.S. Post updated, see top of page.
first, i prefer to use a php file which contains my sql and params. but hey...
The most obvious reason why you might get this error would be a fault in the url i guess. I believe that the standaard gateway.php is written without a capital G. and does not situate itself in the core folder but in the amfphp folder. but then again I don't know what you have altered.
Your _netConnection must be null, and you call connect() method on null reference, so you finish with NullPointerException. Show us how you initialize _netConnnection :).
Ok, I basically remade the thing, and after a couple of hours, it decided to work. I'm not sure how, but... eh.
Thanks all for your help

Can a Flex 3 method detect the calling object?

If I have a method such as:
private function testMethod(param:string):void
{
// Get the object that called this function
}
Inside the testMethod, can I work out what object called us? e.g.
class A
{
doSomething()
{
var b:B = new B();
b.fooBar();
}
}
class B
{
fooBar()
{
// Can I tell that the calling object is type of class A?
}
}
Sorry the answer is no (see edit below). Functions received a special property called arguments and in AS2 it used to have the property caller that would do roughly what you want. Although the arguments object is still available in AS3 the caller property was removed from AS3 (and therefore Flex 3) so there is no direct way you can do what you want. It is also recommeded that you use the [...rest parameter](http://livedocs.adobe.com/flex/3/langref/statements.html#..._(rest)_parameter) language feature instead of arguments.
Here is a reference on the matter (search for callee to find the relevant details).
Edit: Further investigation has shown that it is possible to get a stack trace for the current executing function so if you are lucky you can do something with that. See this blog entry and this forum post for more details.
The basic idea from the blog post is you throw an Error and then catch it immediately and then parse the stack trace. Ugly, but it may work for you.
code from the blog post:
var stackTrace:String;
try { throw new Error(); }
catch (e:Error) { stackTrace = e.getStackTrace(); }
var lines:Array = stackTrace.split("\n");
var isDebug:Boolean = (lines[1] as String).indexOf('[') != -1;
var path:String;
var line:int = -1;
if(isDebug)
{
var regex:RegExp = /at\x20(.+?)\[(.+?)\]/i;
var matches:Array = regex.exec(lines[2]);
path = matches[1];
//file:line = matches[2]
//windows == 2 because of drive:\
line = matches[2].split(':')[2];
}
else
{
path = (lines[2] as String).substring(4);
}
trace(path + (line != -1 ? '[' + line.toString() + ']' : ''));
Is important to know that stackTrace is only available on the debugger version of Flash Player. Sorry! :(
I'd second the idea of explicitly passing a "callingObject" parameter. Unless you're doing really tricky stuff, it should be better for the caller to be able to supply the target object, anyway. (Sorry if this seems obvious, I can't tell what you're trying to accomplish.)
To add to the somewhat ambiguous first paragraph of James: the arguments property is still available inside a Function object, but the caller property has been removed.
Here's a link to the docs: http://livedocs.adobe.com/flex/3/langref/arguments.html
This might help someone, I'm not sure... but if one is using an Event this is possible using the e.currentTarget as follows:
private function button_hover(e:Event):void
{
e.currentTarget.label="Hovering";
}