Reading JPG into BitmapData in ActionScript 3 (JPG

2019-05-14 20:31发布

问题:

I'm using Adobe AIR to make APK file for my Android phone. Inside the APK package there is a SWF file and in the same folder as the SWF file there is a subfolder named "images", which contains image.jpg.

I'm trying to read that image.jpg into the program at runtime but can't get the location of it (the program doesn't seem to find it.

Here's what I'm trying:

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("images/image.jpg"));
while (bitmapData==null) {}  //wait until loaded
return bitmapData;

The onComplete-function puts sets the bitmapData field. However, the COMPLETE event never happens so the while loop never exists.

I have also tried:

loader.load(new URLRequest("/images/image.jpg"));
loader.load(new URLRequest("app:/images/image.jpg"));
loader.load(new URLRequest("app-storage:/images/image.jpg"));
loader.load(new URLRequest("file:/images/image.jpg"));

None of it works.

I can't get this to work even when trying without the APK file, when only running the SWF file that is generated (the images subfolder is in the same folder as the SWF file).

I can't embed the JPG into the SWF file itself because I need to have a lot of image files and Flash CS6 runs out of memory when making such a big SWF file (reading the images externally would also mean a whole lot less compilation time).

Any ideas? How can I get put the external JPG file into BitmapData? Remember that the image is not outside of the APK file, it is packaged inside it.

Note: I'll also export the thing into a iOS ipa package later so it have to work there as well.


Edit because I can't self-answer due to my reputation.

Strille made me realize that the ActionScript Virtual Machine is single-threaded.

So it's impossible to make a thread sleep (wait) for an image being loaded. Instead I have to sigh rewrite a lot of code so that things are halted and continues when the onComplete function is called.

This thing that I tried before actually works but couldn't complete due to the while loop:

loader.load(new URLRequest("app:/images/image.jpg"));

回答1:

If I remember correctly, you should be able to do it like this:

loader.load(new URLRequest(new File("app:/images/image.jpg").url));

Since we're using the File class, the above will not run in the Flash Player, just on iOS or Android.



回答2:

From my experience there are two practical methods to load assets from a running Android APP using AIR

  1. using URLLoader and .url property of the File instance
  2. using FileStream (which receives a File instance)

Adding to project

You can package the files inside the APK using the same technique as packaging ICONS, inside the .xml descriptor file for your app.

And make sure you add those to your IDE in the Android section (applies to IntelliJ and Flash Builder) "Files and folders to package" - add the path to your wanted assets folder, and give it a relative name alias.

Elaboration

The assets themselves are placed (when the APP is installed), inside the ''applicationDirectory'' which is available for AIR,

Yet since newer Android OS's, and Flash player security issues, it is not possible to access those assets via the nativePath, only the 'url' property of the File instance.

Best Practice

Use URLLoader and .url property of the File instance, as it is also Asynchronous by nature and can resolve PNG / JPG files using native decoder instead of having to do this manually reading a FileStream (which returns a a ByteArray)

var f:File = File.applicationDirectory.resolvePath('images/myimage.png');
loader.load(new URLRequest(f.url));

and, If I'm missing more ways, please let know... )