Page 1 of 2
Android File System
Posted: Mon May 16, 2016 6:06 am
by LunaRebirth
I've created a game that runs all *.lua files in a directory.
I'm porting this game to Android, and it should read all file names in a directory and run all *.lua files.
Unfortunately I'm having a ton of problems reading all files in a directory on Android.
If I load a texture like so
Code: Select all
IGUIImage* startIMG = Game::guienv->addImage(rect<s32>(0,0,640,480),0,0);
startIMG->setImage(Game::driver->getTexture("media/blank.png"));
There are no issues loading the file on both, Android or Windows.
However if I use the file system and do
Code: Select all
bool check = device->getFileSystem()->existFile("media/blank.png");
check returns true on Windows, and false on Android.
I've also searched around on how to read all files with POSIX or on UNIX systems. Nothing seems to work.
I'm unsure why this problem is occurring, so I figured maybe it's my file permissions? In the Android Manifest I'm using permissions for
READ_EXTERNAL_STORAGE and READ_INTERNAL_STORAGE
Any suggestions?
Re: Android File System
Posted: Mon May 16, 2016 6:13 am
by LunaRebirth
When I try
Code: Select all
char c[255];
sprintf(c, "%s",(char*)Game::fs->getWorkingDirectory().c_str());
Game::logger->log(c);
on Android I get "" as the working directory.
Re: Android File System
Posted: Mon May 16, 2016 6:33 pm
by CuteAlien
You have to manually add the directory to the archive first. Check the android example - it has code for that (the part with "addDirectoryToFileList").
Re: Android File System
Posted: Tue May 17, 2016 2:56 am
by LunaRebirth
Ah okay that worked for existFile.
Here's what I'm doing to find all files in a directory:
Code: Select all
std::vector<std::string> allDirs(char* folder_name) {
std::vector<std::string> allFiles;
char c[255];
sprintf(c, "Looking for files...");
Game::logger->log(c);
//Game::fs is an IFileSystem
if(!Game::fs->changeWorkingDirectoryTo(folder_name))
return allFiles;
sprintf(c, "Creating file list...");
Game::logger->log(c);
io::IFileList* filelist = Game::fs->createFileList();
if(filelist == NULL)
return allFiles;
sprintf(c, "Getting count...");
Game::logger->log(c);
if(filelist->getFileCount() == 0) {
return allFiles;
} else {
sprintf(c, "Adding files...");
Game::logger->log(c);
for(int i = 2; i < filelist->getFileCount(); i++) {
std::string fullFile = filelist->getFileName(i).c_str();
allFiles.push_back((char*)((std::string)folder_name+fullFile).c_str());
sprintf(c, "File::%s!",(char*)allFiles[i-2].c_str());
Game::logger->log(c);
}
}
Game::fs->changeWorkingDirectoryTo("../");
filelist->drop();
return allFiles;
}
The code works and successfully outputs all found files on Windows.
But it fails on Android, last outputting "Looking for files..." (line 5 in code above).
I read that changeWorkingDirectoryTo could return a fail, and still change the directory, in a different forum post. So I tested without the if statement on line 5, and I got to output "Creating file list..." before the function returned.
I believe it isn't finding the folder for changeWorkingDirectoryTo, but I'm unsure why?
Calling "allDirs("Weapons/")" where the Weapons folder exists in Android assets.
allDirs("/sdcard/Weapons/"); doesn't work either
Re: Android File System
Posted: Thu May 19, 2016 5:34 am
by LunaRebirth
Cool, I found all the files:
Code: Select all
char c[255];
sprintf(c, "Getting archive count...");
Game::logger->log(c);
for ( u32 i=0; i < Game::fs->getFileArchiveCount(); ++i )
{
IFileArchive* archive = Game::fs->getFileArchive(i);
if ( archive->getType() == EFAT_ANDROID_ASSET )
{
bool inFolder = false;
for ( u32 y=0; y < archive->getFileList()->getFileCount(); ++y )
{
if (inFolder) {
std::string fullName = (std::string)folder_name + (std::string)archive->getFileList()->getFileName(y).c_str();
allFiles.push_back(fullName);
sprintf(c, "File Found::%s", (char*)fullName.c_str());
Game::logger->log(c);
}
if (archive->getFileList()->isDirectory(y)) {
std::string newName = folder_name;
newName = newName.substr(0,newName.length()-1);
if (archive->getFileList()->getFileName(y).c_str() == newName) {
inFolder = true;
} else {
inFolder = false;
}
}
}
}
}
return allFiles;
Now I'm trying to run these files with Lua using luaL_dofile, but of course because the file is in the assets, it won't run.
Whats the best way to run the Lua file?
I was thinking about maybe if I could take the file out of the assets folder and move it to the /sdcard location and doing luaL_dofile from there, but I don't see any way to access the file directly from Irrlicht. Possible better ideas or anything that might help?
Re: Android File System
Posted: Thu May 19, 2016 7:58 pm
by LunaRebirth
Solved
Re: Android File System
Posted: Fri May 20, 2016 8:08 am
by CuteAlien
LunaRebirth wrote:Solved
Nice. I wasn't sure what's going on myself. My suspicion was that it's somehow caused by the mix of real filesystem and archive filesystem somehow, but would have needed some time to debug.
If you can share the solution it might also help others in future :-)
Re: Android File System
Posted: Fri May 20, 2016 5:00 pm
by LunaRebirth
CuteAlien wrote:If you can share the solution it might also help others in future
Yeah,
I used the code mentioned above to find all the files, then I saved them as an IReadFile and read their contents line-by-line, storing the full file contents in a string and then doing luaL_dostring() directly from the file in the assets folder
Re: Android File System
Posted: Wed Aug 24, 2016 3:11 am
by LunaRebirth
I decided to post another question I had here rather than in a new post.
So I've made it so the server sends file contents to the client, in which the client receives to a file.
The server also sends whether it is only part of a file, or a while file (meaning the client saves the file, and, if it's another part of the file, it appends more data to the file rather than overwriting it)
I've got it working on Windows with
Code: Select all
IWriteFile* file = Game::fs->createAndWriteFile((char*)fileName.c_str(), overwrite);
if (file > 0) {
file->write(cont, len);
file->drop();
}
Doesn't seem to create a new file on Android, and I'd like it to.
So
THE QUESTION:
How do I write files on Android?
Re: Android File System
Posted: Wed Aug 24, 2016 4:00 am
by LunaRebirth
I'm using this code I found from
http://stackoverflow.com/questions/1129 ... -code-only
Code: Select all
#ifdef _IRR_ANDROID_PLATFORM_
ANativeActivity* nativeActivity = Game::state->activity;
const char* internalPath = nativeActivity->internalDataPath;
std::string dataPath(internalPath);
// internalDataPath points directly to the files/ directory
std::string configFile = dataPath + "/" + fileName;
// sometimes if this is the first time we run the app
// then we need to create the internal storage "files" directory
struct stat sb;
int32_t res = stat(dataPath.c_str(), &sb);
if (0 == res && sb.st_mode & S_IFDIR)
{
Game::log("'files/' dir already in app's internal data storage.");
}
else if (ENOENT == errno)
{
res = mkdir(dataPath.c_str(), 0770);
}
if (0 == res)
{
// test to see if the config file is already present
res = stat(configFile.c_str(), &sb);
if (0 == res && sb.st_mode & S_IFREG)
{
Game::log("Application config file already present");
}
else
{
Game::log("Application config file does not exist. Creating it ...");
// read our application config file from the assets inside the apk
// save the config file contents in the application's internal storage
Game::log("Reading config file using the asset manager.\n");
AAssetManager* assetManager = nativeActivity->assetManager;
AAsset* configFileAsset = AAssetManager_open(assetManager, (char*)fileName.c_str(), AASSET_MODE_BUFFER);
const void* configData = AAsset_getBuffer(configFileAsset);
const off_t configLen = AAsset_getLength(configFileAsset);
FILE* appConfigFile = std::fopen(configFile.c_str(), "w+");
if (NULL == appConfigFile)
{
Game::log("Could not create app configuration file.\n");
}
else
{
Game::log("App config file created successfully. Writing config data ...\n");
res = std::fwrite(configData, sizeof(char), configLen, appConfigFile);
if (configLen != res)
{
Game::log("Error generating app configuration file.\n");
}
}
std::fclose(appConfigFile);
AAsset_close(configFileAsset);
}
}
#endif // _IRR_ANDROID_PLATFORM_
but Irrlicht is crashing with output
Code: Select all
08-23 22:54:44.589 1710 1732 I Irrlicht: 'files/' dir already in app's internal data storage.
08-23 22:54:44.589 1710 1732 I Irrlicht: Application config file does not exist. Creating it ...
08-23 22:54:44.589 1710 1732 I Irrlicht: Reading config file using the asset manager.
08-23 22:54:44.589 1710 1732 I Irrlicht:
08-23 22:54:44.699 509 509 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
08-23 22:54:44.700 509 509 F DEBUG : Build fingerprint: 'motorola/kinzie_verizon/kinzie:6.0/MCK24.78-13.16/16:user/release-keys'
08-23 22:54:44.700 509 509 F DEBUG : Revision: 'p301'
08-23 22:54:44.701 509 509 F DEBUG : ABI: 'arm'
08-23 22:54:44.701 509 509 F DEBUG : pid: 1710, tid: 1732, name: Thread-21751 >>> com.app3D <<<
08-23 22:54:44.701 509 509 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
08-23 22:54:44.717 509 509 F DEBUG : r0 00000000 r1 00000000 r2 00000000 r3 00000002
08-23 22:54:44.717 509 509 F DEBUG : r4 ef749334 r5 ef749270 r6 00000000 r7 f543dd00
08-23 22:54:44.717 509 509 F DEBUG : r8 f766ab84 r9 f543ddf0 sl ef64b000 fp f400549d
08-23 22:54:44.717 509 509 F DEBUG : ip f409aaf4 sp ef749250 lr f3eac097 pc e9093dc6 cpsr 40070030
08-23 22:54:44.722 509 509 F DEBUG :
08-23 22:54:44.722 509 509 F DEBUG : backtrace:
08-23 22:54:44.722 509 509 F DEBUG : #00 pc 00008dc6 /system/lib/libandroid.so (AAsset_close+31)
08-23 22:54:44.722 509 509 F DEBUG : #01 pc 0013e093 /data/app/com.app3D-1/lib/arm/libapp3D.so (_Z11receiveFilev+826)
08-23 22:54:44.722 509 509 F DEBUG : #02 pc 0013e92f /data/app/com.app3D-1/lib/arm/libapp3D.so (_ZN6Server10ConnectionEv+446)
08-23 22:54:44.722 509 509 F DEBUG : #03 pc 0013368b /data/app/com.app3D-1/lib/arm/libapp3D.so (main+118)
08-23 22:54:44.722 509 509 F DEBUG : #04 pc 00135c7f /data/app/com.app3D-1/lib/arm/libapp3D.so (android_main+798)
08-23 22:54:44.722 509 509 F DEBUG : #05 pc 00297513 /data/app/com.app3D-1/lib/arm/libapp3D.so
08-23 22:54:44.722 509 509 F DEBUG : #06 pc 0003fc6b /system/lib/libc.so (_ZL15__pthread_startPv+30)
08-23 22:54:44.722 509 509 F DEBUG : #07 pc 0001a095 /system/lib/libc.so (__start_thread+6)
08-23 22:54:44.972 509 509 F DEBUG :
08-23 22:54:44.972 509 509 F DEBUG : Tombstone written to: /data/tombstones/tombstone_06
08-23 22:54:44.972 509 509 E DEBUG : AM write failed: Broken pipe
I've played around with some pieces of the code and can't determine how to fix the problem
Crash @ >> const void* configData = AAsset_getBuffer(configFileAsset);
Re: Android File System
Posted: Wed Aug 24, 2016 2:14 pm
by mongoose7
You didn't check the return from
AAsset* configFileAsset = AAssetManager_open(assetManager, (char*)fileName.c_str(), AASSET_MODE_BUFFER);
Re: Android File System
Posted: Wed Aug 24, 2016 3:51 pm
by LunaRebirth
mongoose7 wrote:You didn't check the return from
AAsset* configFileAsset = AAssetManager_open(assetManager, (char*)fileName.c_str(), AASSET_MODE_BUFFER);
Good point. Any ideas to why that line might be failing?
Re: Android File System
Posted: Thu Aug 25, 2016 2:01 am
by mongoose7
Print out fileName.c_str().
Re: Android File System
Posted: Thu Aug 25, 2016 2:43 am
by LunaRebirth
So if I create the file and build it into the APK, obviously it finds it, but if I want to write (save) a new .txt file on Android, it can't.
I've put the internal and external read/write rights in the manifest, and the correct permissions are visible on App Info on my phone.
It won't create a new file?
I've searched all over the internet for this and there is little to no information
Re: Android File System
Posted: Thu Aug 25, 2016 2:57 am
by LunaRebirth
Fails if the file doesn't already exist (can't create file):
Printed out --
Code: Select all
08-24 21:54:30.131 14168 14205 I Irrlicht: dataPath: /data/user/0/com.myapp/files
08-24 21:54:30.131 14168 14205 I Irrlicht: configFile: /data/user/0/com.myapp/files/myfile.txt
08-24 21:54:30.131 14168 14205 I Irrlicht: 'files/' dir already in app's internal data storage.
08-24 21:54:30.131 14168 14205 I Irrlicht: Application config file does not exist. Creating it ...
08-24 21:54:30.131 14168 14205 I Irrlicht: Reading config file using the asset manager.
08-24 21:54:30.131 14168 14205 I Irrlicht: configFileAsset failed.