10 Replies Latest reply on Sep 1, 2009 7:12 PM by seaneyefi

    FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation

    seaneyefi Level 1

      Hi all,

       

      I'm trying to use the FABridge in my HTML-based AIR app to communicate between a swf file and my JavaScript code. Browsing through the forums, it appears that ExternalInterface is not advisable in AIR, so I turned to FABridge instead. Can anyone on this forum advise me on whether FABridge is the correct route to take if I want to communicate betweeen flex and javascript.

       

      If FABridge is the recommended protocol, can someone please advise on how to include the FABridge.as file as part of a amxmlc compiler option. I've tried the following:

       

      seanosheas-macbook-pro:bin seanoshea$ ./amxmlc -sp+=${FLEX_3_HOME}/frameworks/javascript/fabridge/src/bridge ${PROJECT_HOME}/GMapsController.mxml

       

      but I keep getting this error:

       

      Error: Could not resolve <fab:FABridge> to a component implementation.

       

      Looking at Mike Chambers' blog post here: http://www.mikechambers.com/blog/2005/12/22/compiling-actionscript-3-and-mxml-on-mac-and-l inux/, it looks like the air-config.xml file could be modified to include the FABridge.as file. I've tried modifying the air-config.xml file to point at the fabridge/src/bridge directory, but no luck.

       

      Sean

        • 1. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
          seaneyefi Level 1

          I even tried adding the ASCLASSPATH to my .profile file, but no luck

           

          102:bin seanoshea$ ./amxmlc -library-path+=/Users/seanoshea/eyefi/svn/manager/air/build/gmaps/lib/map_flex_1_16.swc /Users/seanoshea/eyefi/svn/manager/air/htdocs/flex/GMapsController.mxml
          Loading configuration file /Users/seanoshea/dev/flex3/frameworks/air-config.xml
          /Users/seanoshea/eyefi/svn/manager/air/htdocs/flex/GMapsController.mxml: Error: Could not resolve <fab:FABridge> to a component implementation.

           

          102:bin seanoshea$ echo $ASCLASSPATH
          /Users/seanoshea/dev/flex3/frameworks/javascript/fabridge/src/bridge
          102:bin seanoshea$

           

          Any ideas, or could you recommend a different way of communicating between flex and javascript in an AIR app?

          • 2. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
            seaneyefi Level 1

            Looking at the flex documentation for FABridge (http://livedocs.adobe.com/flex/3/html/help.html?content=ajaxbridge_1.html), this is what I see:

             

            "If you are compiling from the command line, add the src folder to your application by specifying the --actionscript-classpath compiler option"

             

            I tried finding the help for the --actionscript-classpath compiler option, but no luck with amxmlc or xmxmlc:

             

            102:bin seanoshea$ ./amxmlc -help -actionscript-classpath
            Adobe Flex Compiler (mxmlc)
            Version 3.3.0 build 4852
            Copyright (c) 2004-2007 Adobe Systems, Inc. All rights reserved.

             

            no keywords matched.

             

            102:bin seanoshea$ ./mxmlc -help -actionscript-classpath
            Adobe Flex Compiler (mxmlc)
            Version 3.3.0 build 4852
            Copyright (c) 2004-2007 Adobe Systems, Inc. All rights reserved.

             

            no keywords matched.

             

            102:bin seanoshea$

             

            Just after writing that, it looks like I was adding the incorrect folder to my amxmlc command. This appears to work ok:

             

            ./amxmlc -sp+=${FLEX_3_HOME}/frameworks/javascript/fabridge/src/ ${PROJECT_HOME}/GMapsController.mxml

             

            Still curious to know whether FABridge is the recommended protocol to use for communicating between flex and javascript in an AIR application.

            • 3. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
              seaneyefi Level 1

              Tried loading the .swf I compiled into an AIR application, but the .swf doesn't run. Checked the .swf in a regular browser application and it works fine. This leads me to believe that FABridge is not the solution for communcating between flex and JavaScript in an AIR application. I took a quick peek at the FABridge.as file and it looks like it makes references to ExternalInterface which I understand is not supported/advisiable in AIR applications (see the bottom of this page for more info: http://livedocs.adobe.com/labs/air/1/aslr/flash/external/ExternalInterface.html).

               

              This brings me back to my original question - whats the recommended protocol to use for communicating between JavaScript and Flex in an AIR application? A quick Google search brings up this: http://arguments.callee.info/2009/03/19/adobe-air-calling-javascript-from-a-swf/, but I'm not convinced its an optimal solution.

              • 4. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
                adobe_paul Adobe Employee

                If you're trying to use a SWF file as a code library in your HTML-based AIR app, then I believe this is what you're looking for:

                 

                Using ActionScript libraries within an HTML page (AIR developers' guide)

                 

                 

                The Flex-Ajax bridge (FABridge) is designed for controlling parts of a visual SWF file (e.g. a user interface built in Flex) from JavaScript in the container application (e.g. a web page that includes the SWF file). As you noted, the FABridge is really just a wrapper on top of the ActionScript ExternalInterface class.

                • 5. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
                  seaneyefi Level 1

                  Hi Paul,

                   

                  Thanks for the reply. I was drawn to the FABridge because the documentation said it's useful if:

                   

                  "You want to use a rich Flex component in an Ajax application but do not want to write a lot of Flex code. If you wrap the component in a FABridge-enabled stub application, you can script it entirely from JavaScript, including using JavaScript generated remotely by the server."

                   

                  The rich Flex component I'm trying to control in my Ajax application is a Google Maps swf. The swf is pretty simple ... it just looks like this:

                   

                  <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
                      <maps:Map xmlns:maps="com.google.maps.*" id="map" mapevent_mapready="onMapReady(event)" width="100%" height="100%"
                          url="http://code.google.com/apis/maps/" key="ABQIAAAAirgZjEoCu9a3euq95spKkBR_S1ecsaBoILwOJWQZL62AsG_vrBT---yI8NYfu5nSGRvZPcpZobSH zA"/>
                      <mx:Script>
                          <![CDATA[
                        
                              import com.google.maps.LatLng;
                              import com.google.maps.Map;
                              import com.google.maps.MapEvent;
                              import com.google.maps.MapType;
                         
                              private function onMapReady(event:Event):void {
                                  this.map.setCenter(new LatLng(40.736072,-73.992062), 14, MapType.NORMAL_MAP_TYPE);
                              }
                             
                              public function setLocation(lat:Number, long:Number):void {
                                 
                              }
                             
                          ]]>
                      </mx:Script>
                  </mx:Application>

                   

                  I'm including the .swf file with an embed tag as outlined in the Google Maps for Flash API documentation:

                   

                      <div id="map_canvas">
                          <object
                            classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
                            codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"
                            width="800px"
                            height="600px">
                                <!-- <param name="movie" value="app:/flex/GMapsController.swf">  -->
                                <!-- <param name="movie" value="app:/GMapsController.swf">   -->
                                <param name="movie" value="http://mysite.eye.fi/GMapsController.swf">
                                <param name="quality" value="high">
                                <param name="flashVars" value="key=ABQIAAAAirgZjEoCu9f3eua95spKkBR_S1ecsaBoILwOJWQZL62AsG_vrBT---yI8NYfu5nSGRvZPc pZobSHzA">
                                <embed
                                  width="800px"
                                  height="600px"
                                  quality="high"
                                  flashVars="key=ABQIAAAAirgZjEoCu9f3euq95spKkBR_S1ecsaBoILwOaWQZL62AsG_vrBT---yI8NYfu5nSGR vZPcpZobSHzA"
                                  pluginspage="http://www.macromedia.com/go/getflashplayer"
                                  type="application/x-shockwave-flash">
                          </object>
                       </div>

                   

                  I'm not sure I can include it as a library of classes as you describe in your post.

                   

                  It would be really sweet if I could attach an id attribute to the embed tag and be able to call the functionality within the swf file in JavaScript.

                   

                  Do you know whether this is possible or not? I'm pretty new to flex (if you guys havent already guessed), so I could be missing something pretty simple.

                   

                  Any help is greatly appreciated

                   

                  Cheers


                  Sean

                  • 6. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
                    seaneyefi Level 1

                    Paul,

                     

                    I'm new to Flex, so please bear with me when I ask these questions:

                     

                    1. If I was to create a ActionScript class to control the Google Maps map, I'm guessing I'd compile the .swf file using amxmlc and reference the ActionScript class in the .swf?

                     

                    2. Would you advise me to create a .swc file which just contains my ActionScript class (http://livedocs.adobe.com/flex/3/html/help.html?content=CommandLineTools_3.html lists the output of the acompc compiler as a .swc file). And then, when compiling the Google Maps .swf file, reference the .swc file?

                     

                    3. If I was to create the ActionScript class in my JavaScript code using the following syntax:

                     

                    var libraryObject = new window.runtime.MyActionScripClass();

                    How would my library access the Google Map object?

                    Sean
                    • 7. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
                      adobe_paul Adobe Employee

                      Rats. My long reply got deleted.

                       

                      I'll try to summarize:

                       

                      - For what you're trying to do, using a SWF as a library isn't really the appropriate solution. (It's more for the case where you want to use some non-visual ActionScript code, like a library that opens ZIP files, within a JS AIR app.) Sorry to lead you down the wrong path.

                       

                      - I don't really know much about implementing Google Maps (or any other maps) in Flex. So I'm afraid I can't offer much specific advice there.

                       

                      - I also don't know why ExternalInterface wouldn't work in AIR, although it sounds like you've heard reports that it doesn't. I'll try to play around with it a bit and see if I can make it work, or find out if there are specific known issues.

                       

                      Sorry I don't have any more useful suggestions right at the moment!

                      • 8. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
                        seaneyefi Level 1

                        Just bumping this forum posting ... curious to know whether anyone can offer advice on this posting.

                         

                        At this stage, I'm starting to think Flash/Flex is not the correct decision to tackle the problem I'm trying to solve. I know that there are regular JavaScript implementations for implementing Google Maps in AIR (see the RoadFinder demo), but I wanted to try the Flash APIs for Google Maps as it offers some features above and beyond the normal JavaScript APIs - I also wanted to take a stab at getting to know Flash/Flex a little better too.

                         

                        I'm not even sure this particular posting is directly related to Google Maps in AIR anymore. Its more related to figure out whether its possible to communicate between a .swf loaded from a remote domain and JavaScript. I can't imagine this being impossible, but at the same time, I can't find the solutions.

                         

                        Any help would be greatly appreciated.

                         

                        Sean

                        • 9. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
                          Joe ... Ward Level 4

                          It is possible for Javascript to communicat with a remotely loaded SWF. However, since this opens  a potential attack vector against your users' computers, it has to be done in a particular way.

                           

                          To do this you have to map the Javascript in your application that needs to interact with the remote SWF into the same remote domain. This can be done with an iframe. AIR adds a sandboxRoot and a documentRoot property to the iframe object. You set the sandboxRoot to a "virtual" directory on the remote domain, and the documentRoot to the local directory in your app where content in the virtual directory will be loaded from.

                           

                          For example, in:

                          <iframe 
                              src="http://www.example.com/local/ui.html" 
                              sandboxRoot="http://www.example.com/local/" 
                              documentRoot="app:/sandbox/">
                          </iframe>

                           

                          The file ui.html will be loaded from the app:/sandbox/ directory, but it will have the security privileges of a file loaded from

                          http://www.example.com/local/.

                          For information see: http://help.adobe.com/en_US/AIR/1.5/devappshtml/WS5b3ccc516d4fbf351e63e3d118666ade46-7f08. html.

                          Note that the remotely mapped Javascript will no longer be able to communicate with other parts of your application directly and it will not have access to those APIs restricted to the application sandbox (like reading and writing local files without user interaction). To allow this, you must set up a "sandbox bridge." This is also described at the above link.

                          • 10. Re: FABridge in AIR: Could not resolve <fab:FABridge> to a component implementation
                            seaneyefi Level 1

                            Thanks Joe for your help - I think I have a workaround working now.

                             

                            Sean