lfs.dir on Android

Hi, I have a problem with lfs. I need “parse” some path and return the array of titles of files.

I use this code:

Spath = system.pathForFile("images/sockets/sockets/") for file in lfs.dir(Spath) do if file ~= "." and file ~= ".." then table.insert(socketArray, file) end end

socketArray returns something like:

a1.png
a2.png
a3.png
and so on…

And this works perfectly fine on emulator. However, on actual Android device it thows me an error, that there is no such directory:

Sure there are no such directory, because this is a path for emulator, but why it is not working properly, I dont know

But just simple Corona function somehow sees that directory rightly and works perfectly.

play\_b = widget.newButton( { x = display.contentCenterX, y = display.contentHeight/10\*5, id = "play\_b", onEvent = handleButtonEvent, defaultFile = "images/ui/play\_button/play\_button.png", overFile = "images/ui/play\_button/play\_button\_pressed.png" } )

Code above works fine, and uses big-button png, nevermind that it is stored inside of apk.

Hi @tolstyak0777,

Are you using the file(s) from the LFS pull within a widget.newButton()? If so, can you post that code here please?

Thanks,

Brent

No, I use LFS pull pics just for display.newImage(). I wrote code with newButton just for proof, that Corona itself can reach pngs at directory, but lfs doesn’t.

This is all that uses it:

 Spath = system.pathForFile("images/sockets/sockets/") for file in lfs.dir(Spath) do if file ~= "." and file ~= ".." then table.insert(socketArray, file) end end for k, v in pairs(socketArray) do local cacheImage = display.newImage('/images/sockets/sockets/'.. v, 0, k\*100) end

Thx

This line of code:

local cacheImage = display.newImage('/images/sockets/sockets/'.. v, 0, k\*100)

should not have the leading “/”. That tells the operating system to start at the root of the device and look for a folder named “images” which doesn’t exist and you wouldn’t have access to the folder anyway.  Taking the first slash off makes it relative to your sandbox which should work.

Rob

Thanks for the answer, but you’re missing the point. I have trouble in this:

 for file in lfs.dir(Spath) do if file ~= "." and file ~= ".." then table.insert(socketArray, file) end end

There is just no such directory for lfs.dir().

You may be running into the fact that system.ResourceDirectory isn’t a real thing on Android. See:

https://docs.coronalabs.com/api/library/system/pathForFile.html

And read the “Android File Restrictions” section.

Rob

I could be wrong because I’ve never done it the way you’re doing, but I don’t think you can use “system.pathForFile()” with an arbitrary folder as the target. I think it expects an actual file, which you haven’t specified in your “Spath” assignment.

Brent

But somehow widget.newButton() can use files, which contains in another directory, but still inside system.ResourceDirectory. Is widget image uploader works by another way, or I’m doing something wrong with lfs?

I think you’re wrong, because Corona documentation (https://docs.coronalabs.com/api/library/system/pathForFile.html) says, that it can be file, or path to directory, so my solution is fine. I guess so, at least.

Hmmmm… all indications so far seem to point to Rob’s advice about the Android file restrictions in the Resource directory, especially since it appears that you’re looking for PNG files and “.png” is one of the restricted types.

Probably the easiest way to confirm this is to drop a text file like “test.txt” into that folder and then call this in an actual Android build:

[lua]

Spath = system.pathForFile(“images/sockets/sockets/test.txt”)

print( Spath )

[/lua]

If that works, then try it with a PNG file which also exists in the folder, for example:

[lua]

Spath = system.pathForFile(“images/sockets/sockets/a1.png”)

print( Spath )

[/lua]

If the first case works and the second doesn’t, it’s likely a file type issue on Android specifically in the Resource directory when using file/IO-based calls like “system.pathForFile()”, since .txt is not a restricted type but .png is.

Best regards,

Brent

Tested out. BOTH WORKS! It finds and prints on screen path to txt and png. But lfs doesn’t see it! I’m clearly confused and still think, that problem is in lfs.

Thx

Do you have a simple test I can try? Like the most basic possible code sample you can create? I can try it on an Android device to see what happens. Email is brent (at) coronalabs (dot) com.

Brent

I did sent you yesterday simple test, what do you say?

I haven’t tested it yet. Can you actually send me the Lua code and not the built .apk? Thanks.

Sent.

Thx

OK, I tested it and I’m getting the same basic results. This is what Rob and I suspected: an issue with Android not having a technical “Resources” directory and thus there’s limited file I/O access on Android with the file types listed in the docs. Corona display.* APIs gain access to these (it’s a pretty fundamental need) but trying to use LFS has limits on Android when trying to traverse the Resources directory.

Fortunately, there are potential solutions:

  1. When the app starts, you could copy all of the image files from the Resources directory to the Documents directory. There’s an example of how to do that here. But, I can’t highly recommend that because you’ll end up duplicating potentially many image files and the app size will grow. That leads me to idea #2

  2. Maintain a simple SQLite database or JSON file with the image files you’re bundling inside your “sockets” directory. Since you’ll be shipping those images with the app, you’ll always have a predictable list which you can maintain, and since Resources is read-only, it will never change after the app is built/installed. With that SQLite/JSON, forget using LFS entirely and just loop through or search the list for the names and then display them using “display.newImage()” or whatever.

I know it’s not ideal, but hopefully this helps somewhat.

Brent

Big thanks for your time, I probably will use your second solution with JSON file, but can you explain to me, why there simply isn’t such a function which will parse folders, in case you have API permission?

Great thanks

You can also store the list of file names in a lua table inside the module where you need it. It will save you a little more overhead of not having to open a file and read the data in.

As far as why there isn’t a simple function, because Google made Android APK’s a zip file and they don’t unzip it to the file system, rather they expect the app to extract the files that it needs on the fly. I guess its their way of keeping the app size a bit smaller. LFS needs a file system to work on and there simply isn’t one for the APK’s resources.

Rob

Hi @tolstyak0777,

Are you using the file(s) from the LFS pull within a widget.newButton()? If so, can you post that code here please?

Thanks,

Brent

No, I use LFS pull pics just for display.newImage(). I wrote code with newButton just for proof, that Corona itself can reach pngs at directory, but lfs doesn’t.

This is all that uses it:

 Spath = system.pathForFile("images/sockets/sockets/") for file in lfs.dir(Spath) do if file ~= "." and file ~= ".." then table.insert(socketArray, file) end end for k, v in pairs(socketArray) do local cacheImage = display.newImage('/images/sockets/sockets/'.. v, 0, k\*100) end

Thx

This line of code:

local cacheImage = display.newImage('/images/sockets/sockets/'.. v, 0, k\*100)

should not have the leading “/”. That tells the operating system to start at the root of the device and look for a folder named “images” which doesn’t exist and you wouldn’t have access to the folder anyway.  Taking the first slash off makes it relative to your sandbox which should work.

Rob