Skip to main content
Participating Frequently
June 18, 2013
Question

File.copyTo (and copyToAsync) extremely slow on Android. e.g. 1/2 second per tiny XML file. Help?

  • June 18, 2013
  • 2 replies
  • 6516 views

On first launch, my app copies about 100 tiny XML files from application dir to storage dir. It takes about 35 seconds. That is clearly an issue. It takes about 1/100th of a second on any other platform. I've switched to copyToAsync() so that the user doesn't bail, but still this is like using a dial-up modem! Anyone have any thoughts?

This topic has been closed for replies.

2 replies

Abhinav_Dhandh
Adobe Employee
Adobe Employee
June 20, 2013

Hi Allan

I tried to reproduce this issue in which I have copied 100 XML's from application directory to applicationStorage directory in Android AIR app. The issue is not reproducible as the files were copied almost instantaneously within 1-2 seconds.

I have shared my sample project here :  https://dl.dropboxusercontent.com/u/184715790/Shared/FileCopyToTest.zip

Additionally, I have also attached the .apk : https://dl.dropboxusercontent.com/u/184715790/Shared/FileCopyToTest.apk

You could try it out and confirm if the issue is still visible.

Also could you inform about your device, OS version & AIR version which you are using ?

Regards,

Abhinav

Participating Frequently
June 21, 2013

Hi Abhinav -

I notice that my test is Flex. Your test is pure AS3. You are also using the beta 3.8 release, not an official public release?

I will get the 3.8 beta. Could you also build a 3.7.1 Flex test? Or test the one I sent via Gen?

Thanks,

Allan

New Participant
December 18, 2013

Here is a link to the src/bin of the Android ANE I whipped up to do zip expansion:

https://dl.dropboxusercontent.com/u/66764558/ZipExpand.zip

The src and ant build file are there if you want to recompile from src, updating build.properties to point to your SDKs,

or you can just use the single file build/ZipExpand.ane directly in your Android project

To use in code just do something like:

--------------------------------

import util.zip.expand.ZipExpand;

private static var zipExpander:ZipExpand;

...

// can reuse a static singleton instance of the class

if (zipExpander == null) zipExpander = new ZipExpand();

...

var destinationZip:File = File.applicationStorageDirectory.resolvePath("help.zip");

var expandToFolder:File = File.applicationStorageDirectory

zipExpander.expand( destinationZip.nativePath, expandToFolder.nativePath);

--------------------------------

expand() takes two arguments, a fullpath to the .zip and a fullpath to the directory you want the files extracted to (preserving the internal folder structure of the zip contents btw)

For example, based on my use case above, after I copied my help.zip to File.applicationStorageDirectory I just extract the contents directly there, ending up with a help/..  folder since the 'help/' prefix is contained in the zip entries.

I only implemented a simple synchronous expand() function but I'll leave it to others to play with adding an async version when an event callback if desired. The synchronous version was more than enough of an improvement in speed for me. The Java code should be the most efficient and fastest buffered io way of doing the expansion.

Enjoy and feel free to modify or reuse as needed. I compiled with swf-version="21" and tested only on android sdk versions 9 (Kindle Fire) and 18 (Google Nexus 7) so I can't guarantee no issues with any other devices.


Hi all,

I ran into the same problem on Android: File.copyToAsynch is terribly slow. For 200 files of about 42mb total, it took my Samsung Note 10.1  85 secs to copy from app dir to storage dir! (I have to copy the files to storage dir to be able to read modification date, which is not present in app dir, for an update scheme.)

The solution I ended up with is very simple:

Iterate recursively over folder that you want to copy.

For each file that is not a directory, open the file (using FileStream) , read the bytes, write the bytes to a file on the target directory and close the streams.

This took only 5 secs for the same 200 files / 42 mbs. As this happens only on first run of my app, this is very acceptable.

Here is my code :

------------------------------------------

var folder:String = "content/";//supply your folder here

var src:File = File.applicationDirectory.resolvePath(folder);

var goal:File = File.applicationStorageDirectory;

var bytes:ByteArray = new ByteArray();

var stream:FileStream = new FileStream();

var iterate:Function = function(dir:File, path:String):void

{

                                        var files:Array = dir.getDirectoryListing();

                                        for each(var file:File in files)

                                        {

                                                  if (file.isDirectory)

                                                  {

                                                            iterate(file, path + file.name + File.separator);

                                                  }

                                                  else

                                                  {

                                                            bytes.clear();

                                                            stream.open(file, FileMode.READ);

                                                            stream.readBytes(bytes);

                                                            stream.close();

                                                            var dest:File = goal.resolvePath(path+file.name);

                                                            stream.open(dest, FileMode.WRITE);

                                                            stream.writeBytes(bytes);

                                                            stream.close();

                                                  }

                                        }

}

iterate(src, folder);

------------------------------------------

This could easily be reworked to work asynch of course.

Hope this works for other people as well.

Reinier

Adobe Employee
June 19, 2013

One reason could be that the Android package is a zipped format, thus copying a folder, with multiple files, from app directory, requires extracting the zipped bytes for each file in the folder, unzipping it, and then copying it to the destination.

Though it would be great if you could file a bug with a sample application (with code) do that we could reproduce and analyze at our end.

Thanks,

Daman