External hosting of secondary SWFs for AIR apps on iOS

Starting with AIR 3.7, application developers will be able to host their secondary SWFs on an external server and load them on demand as per their application logic.

Till AIR 3.5, loading of only assets such as images, videos and SWFs without actionscript code, commonly referred as Actionscript Byte Code(ABC Code), from external server was supported. The workflow for the application developer for loading such assets from server resembles the diagram below :

 AIR 3.5 Workflow

With AIR 3.6, the feature for loading of locally packaged secondary SWFs containing ABC code was introduced. The detailed description about this feature and its usage can be found at this blog – “Packaging and loading of multiple SWFs for AIR apps on iOS“. The workflow for the application developer using this feature is described in the diagram below:

 AIR 3.6 Workflow

With AIR 3.7, the feature for external hosting of secondary SWFs has been introduced. The workflow for the application developers who want to use this feature would change slightly from AIR 3.6 and is shown below :

 AIR 3.7 Workflow

The developer needs to provide the url of the secondary stripped SWF in the URLRequest. The stripped SWF is obtained after the ADT packaging as described later in the blog post. A sample URL request for using this feature is :

private var externalSwfUrl:String= "http://www.xyz.com/ExternalSwf.swf";
private var urlRequest:URLRequest = new URLRequest(externalSwfUrl);

To use this feature, developer needs to specify a text file containing details of the SWF files to be stripped & externally hosted. This text file contains line separated paths of SWFs, which are to be externally hosted. A sample text file describing 3 SWFs to be externally hosted  would look like :

assets/Level1.swf
assets/Level2.swf
assets/Level3/asset/Level3.swf

The name of the text file needs to be mentioned in the <externalSwfs> tag within the <iPhone> tag in the application descriptor as shown below :

<iPhone>
       .
       .
       <externalSwfs>assets/SampleSWFInfoFile.txt</externalSwfs>
       .
       .
</iPhone>

During command line packaging using AIR Developer Tool(ADT), the developer needs to specify the text file  just like an asset along with the set of SWF’s mentioned in the text file. A sample ADT  command for using this feature is:

~/bin/adt -package -target ipa-app-store -provisioning-profile <Provisioning Profile> -storetype pkcs12 -keystore <Certificate> -storepass <Password> ResultantIPA.ipa SampleMainSwf-app.xml SampleMainSwf.swf assets/SampleSWFInfoFile.txt assets/Level1.swf assets/Level2.swf assets/Level3/asset/Level3.swf

Or another variation of the above command is where all the SWFs to be externally hosted and the text file are present in the assets folder is as follows :

~/bin/adt -package -target ipa-app-store -provisioning-profile <Provisioning Profile> -storetype pkcs12 -keystore <Certificate> -storepass <Password> ResultantIPA.ipa SampleMainSwf-app.xml SampleMainSwf.swf assets

During IPA packaging,  ADT extracts the ABC code from all child SWFs, adds it to the final executable and generates stripped SWFs in the “externalStrippedSwfs” folder created in the current working directory. The directory structure within the “externalStrippedSwfs” folder remains the same as specified within the text file. The generated stripped SWF’s should then be externally hosted on a web server of developer’s choice.

NOTE: The “externalStrippedSwfs” folder is not generated in the currently available release of Flash Builder 4.7/ Flash CS6. To enable generation of Stripped SWFs for external hosting, command line ADT packaging should be used.

A sample actionscript code which loads a secondary SWF  from an external server is described below :

package
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;

	public class SampleMainSwf extends Sprite
	{	
		private var externalLoader:Loader;
		private var url:String= "http://www.xyz.com/Level1.swf";
		private var urlRequest:URLRequest = new URLRequest(url);
		private var ldrContext:LoaderContext;

		public function SampleMainSwf()
		{	
			externalLoader = new Loader();
			externalLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
			externalLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
			ldrContext=new LoaderContext(false,ApplicationDomain.currentDomain,null);

			try
			{
				externalLoader.load(urlRequest, ldrContext);	
			}
			catch(e:Error)
			{
				trace("Error ID : "+e.errorID+"\nError Message : "+e.message);
			}
		}

		private function completeHandler(e:Event):void
		{	
			addChild(externalLoader);	
		}

		private function errorHandler(e:IOErrorEvent):void
		{
			trace("In IO ErrorEvent Handler");
		}

	}
}

POINTS TO NOTE :

1. Conflicting symbols (classes and global functions) in all the packaged SWFs should be avoided, they might result into undesired behaviour.

2. The stripped SWFs generated using this feature are different from pure asset SWFs. It must be noted that while pure asset SWFs are valid SWFs, the stripped SWFs are invalid SWFs.

3. The SWF version of the ROOT.SWF must be >= 20 to use this feature. If the SWF version is set to <20, the stripped SWFs won’t be generated in the “externalStrippedSwfs” folder even if the SWF files have been specified in the text file.

4. It is recommended that this feature should not be used as a means for updating and displaying content in a dynamic manner. The externally hosted SWFs should not be replaced by any other stripped SWFs except the ones generated during IPA packaging. Any change in the secondary SWF requires a corresponding updation of stripped SWFs on external server.

5. All the SWFs specified in the text file should be passed during the ADT packaging as well.

KNOWN ISSUES :

1. External hosting of Flex SWF does not work and might cause the application to crash.

30 Responses to External hosting of secondary SWFs for AIR apps on iOS

  1. Colin Holgate says:

    The article doesn’t answer the main question that people have asked:
    When the externally hosted swf is loaded, does it run as if it had its original code, or is it just artwork assets?
    A couple of other questions:
    Although it’s not recommended to use the mechanism as a way to update a swf, would that work?
    Can the externally hosted swfs be located in the app’s document folder, on the device?

  2. Abhinav says:

    Hi Colin

    Below are the answers to your queries.
    1. The external SWF will work same as if it had the code in it. The only difference in the entire workflow is that the ABC code from all the secondary SWFs will be added in the final executable & just the assets part of the SWF remains in the stripped SWF after the packaging.
    2. It might work & might not work, please try it at your own risk.
    3. This would be same as the locally packaged multiple swf feature done in AIR 3.6. However, a point to note here is that if you try to load secondary SWF which has been specified in the text file for external hosting from the documents directory, then that file would be stripped and saved in the externalStrippedSwf folder and will not be present in the final executable file.

    • Colin Holgate says:

      For number 3, my usage case was that you could perhaps move an online swf to the documents folder for offline use later. Like say you have a music player feature and you want the user to choose which large swf to load, the user would have to be online and do that large download every time the app is opened. If the swf could be cached in the documents folder it would only have to be downloaded once.

      • Abhinav says:

        Hi Colin

        For such a use case you could write an application logic wherein you would first check the existence of the SWF in the application’s local storage, if it’s present there then you could load it from there itself.
        However if it doesn’t exist then you would download the SWF into the application & store a local copy of that SWF within the application for future use & then load it from the local storage itself. This way you will be able to use the external SWF hosting as well as reduce the users’ network usage as well.

  3. CraigMurray says:

    Why is it not recommended to use this to dynamically update assets on the server and display them in an older version of the app? In Points to Note you state that but without any explanation as to why that is “not recommended”.

    • Abhinav says:

      Hi CraigMurray

      The reason for the recommendation is that your application might or might not work after the assets have been dynamically updated with newer assets. Hence, if you want to update the assets in the secondary swf(s), it is recommended to recompile the IPA with new secondary swf(s), replace the stripped swf(s) on server and then try to run the newly packaged IPA.

      • CraigMurray says:

        Ok thank you for the response. There is a big difference between “it’s dangerous, you might break your app if you’re not careful ” and “Apple might not like it”.

        • Abhinav says:

          In this case the former point is relevant. The behavior and working of the application after the updation of external SWFs cannot be defined.

    • Sergi says:

      I was wondering myself : how’s loading updated and code stripped SWF is any different from loading new version of image from remote server. Does every SWF carry some kind of unique hashtag or something? So when you compile your app, all swfs hashtags are encoded in the main swf and checked during remote SWF loading ?

      • Abhinav says:

        Hi Sergi

        Basically for every secondary SWF, during the IPA packaging the ABC code part of the SWF is moved to the final executable and assets part remain in the stripped SWF. However, when we try to load a secondary SWF which has been updated and then stripped in an IPA which just had the code part of the earlier version of SWF, if their is any difference from the code appended during the initial IPA packaging then the application won’t work. Even if it works, there is no guarantee that it would work seamlessly in the future.

  4. This is my question: I have a symbol in the assets.swf library and the symbol has a linkage name “symbolname” and its base class is a custom class “CustomClass1″. When I download the stripped assets.swf from the server, will I be able to access the library symbol by calling:
    getDefinitionByName (“symbolname”)?

    OR is there another way to access symbols from the library of the assets.swf?

    • Abhinav says:

      Hi Viviana

      Yes, you can use getDefinitionByName(“symbolname”) to access the library symbol.

  5. Leon says:

    Thank you. After 4 hours of tweaking, it worked!

  6. cyberprodigy says:

    Generated SWF files are much bigger then non-stripped and when opened throws error VerifyError: Error #1042: Not an ABC file. major_version=0 minor_version=0.
    Any Ideas what might be causing it? I’m using AIR SDK 3.7

    • Abhinav says:

      The reason for the bigger stripped SWFs is the uncompression of secondary SWFs during the packaging process.

      As far as Error # 1042 is concerned, it is because the stripped SWFs are not a valid SWF files as the Actionscript Byte Code (ABC Code) is removed from these SWFs during ADT packaging. Hence these SWFs cannot be opened as it is in Flash Player. They would work fine when you try to load these SWFs within the iOS Application for which they are generated.

      • cyberprodigy says:

        Thank you for explaining, Abhinav.
        Just to make it clear – should assets load fine in debuging mode, i.e. when passing -target ipa-debug to ADT?
        Do you also happen to know if it is needed also to compile swf file using 3.7, or only the packaging with 3.7 is what’s needed to load external swfs with this method?
        Regards.

        • Abhinav says:

          Yes, the assets should load fine in ipa-debug target.
          While the assets swf compilation is not restricted to any particular AIRSDK version, the Root SWF must have swf-version 20 for which you will need to use AIRSDK 3.7. Also, IPA needs to be packaged using AIRSDK 3.7 or later.

  7. Nathan says:

    Can someone post a real example? Everything I have tried does not work on an ios device.

    • Abhinav says:

      Hi Nathan

      The sample code written in blog post is a fully working AS3 code. Just create a new project using this code, update the URL of URLRequest to the one where you would be actually hosting the secondary stripped SWFs, package the IPA using the method described above, host the stripped SWF to the server which you mentioned earlier in your application and this feature should work fine.

      However, if you are still facing issues with making this feature, please feel free to clear out the issues which you are facing with this feature ?

  8. bigger butt secrets says:

    I have read so many articles or reviews concerning the blogger
    lovers however this paragraph is actually a good piece
    of writing, keep it up.

  9. Shay Pierce says:

    Does this solve the “Reloading a SWF is not supported on this operating system” error when attempting to reload a SWF on iOS?
    I need to be able to load in remote SWFs (which I can generate using this “stripping” method), but I also need to be able to reload them.

    • Abhinav says:

      Reloading of SWFs is still not supported on iOS and the same error would be visible when you try to load remotely hosted SWFs as well.

  10. Kenneth says:

    I would like to build an app using this type of packaging, but I would like to develop it for both iOS and Android. Does this work for android apps as well? Or is it even an issue for Android apps? Can Android apps load external SWFs with ABC?

    • Abhinav says:

      Hi Kenneth
      This feature is for iOS only. As far as Android apps are concerned, the loading of SWFs with ABC is supported for locally as well as externally. Hence you can simply load your secondary SWFs with ABC directly from external server, without any required stripping of SWFs.

  11. Maximus says:

    Can i call methods from loaded stripped SWF? For example I need pass init params to loaded SWF, that has public method initParams

  12. dan matei says:

    useless for me

    I want to load swf with code from server, and when I update the code on server to reflect in application, which probably will never work because of apple :((

  13. Greg says:

    Hi
    In the sample text file you provided there are 3 swf’s – levels of a game. In the game I am working on right now I have 40 levels, each with quite lot of graphics in it, and code ofcourse. I need to load the swf when it is needed and then unload (free the memory , GC) and load the next one. If user come back to the previous screen, the previous swf should be loaded again and the current one unloaded. It’s the common scenario in most games I have ever made :)
    Is it possible with AIR 3.8 on iOS?

    • Abhinav says:

      Hi Greg

      In your case you could code your game logic such that you save the stripped swfs locally on user’s device once they have been downloaded. So, if the user moves back from one level back to previous level, you can check if the file is available locally or not. If yes, then you can simply load that swf locally without downloading the same swf again which will help in saving both time and network bandwidth.

  14. daniel says:

    Top publish. I look forward to reading a lot more. Cheers