mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-14 20:19:38 +00:00
Fix up Android asset directory scan
This commit is contained in:
@@ -1,14 +1,19 @@
|
|||||||
#define _LARGEFILE64_SOURCE
|
#define _LARGEFILE64_SOURCE
|
||||||
#include "GpFileSystem_Android.h"
|
#include "GpFileSystem_Android.h"
|
||||||
#include "GpIOStream.h"
|
#include "GpIOStream.h"
|
||||||
|
#include "HostDirectoryCursor.h"
|
||||||
#include "VirtualDirectory.h"
|
#include "VirtualDirectory.h"
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
#include "SDL_rwops.h"
|
#include "SDL_rwops.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include "UTF8.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -242,37 +247,73 @@ void GpFileStream_Android_File::Flush()
|
|||||||
fflush(m_f);
|
fflush(m_f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, std::string &resolution, bool &isAsset)
|
static bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset)
|
||||||
{
|
{
|
||||||
isAsset = false;
|
isAsset = false;
|
||||||
switch (virtualDirectory)
|
switch (virtualDirectory)
|
||||||
{
|
{
|
||||||
case PortabilityLayer::VirtualDirectories::kApplicationData:
|
case PortabilityLayer::VirtualDirectories::kApplicationData:
|
||||||
resolution = std::string("Packaged/") + path;
|
resolution = std::string("Packaged") ;
|
||||||
isAsset = true;
|
isAsset = true;
|
||||||
return true;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kGameData:
|
case PortabilityLayer::VirtualDirectories::kGameData:
|
||||||
resolution = std::string("Packaged/Houses/") + path;
|
resolution = std::string("Packaged/Houses");
|
||||||
isAsset = true;
|
isAsset = true;
|
||||||
return true;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kFonts:
|
case PortabilityLayer::VirtualDirectories::kFonts:
|
||||||
resolution = std::string("Resources/") + path;
|
resolution = std::string("Resources");
|
||||||
isAsset = true;
|
isAsset = true;
|
||||||
return true;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numPaths; i++)
|
||||||
|
{
|
||||||
|
resolution += "/";
|
||||||
|
resolution += paths[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpFileSystem_Android::GpFileSystem_Android()
|
GpFileSystem_Android::GpFileSystem_Android()
|
||||||
|
: m_activity(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GpFileSystem_Android::~GpFileSystem_Android()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpFileSystem_Android::InitJNI()
|
||||||
|
{
|
||||||
|
JNIEnv *jni = static_cast<JNIEnv *>(SDL_AndroidGetJNIEnv());
|
||||||
|
|
||||||
|
jobject activityLR = static_cast<jobject>(SDL_AndroidGetActivity());
|
||||||
|
jclass activityClassLR = static_cast<jclass>(jni->GetObjectClass(activityLR));
|
||||||
|
|
||||||
|
m_scanAssetDirectoryMID = jni->GetMethodID(activityClassLR, "scanAssetDirectory", "(Ljava/lang/String;)[Ljava/lang/String;");
|
||||||
|
|
||||||
|
m_activity = jni->NewGlobalRef(activityLR);
|
||||||
|
|
||||||
|
jni->DeleteLocalRef(activityLR);
|
||||||
|
jni->DeleteLocalRef(activityClassLR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpFileSystem_Android::ShutdownJNI()
|
||||||
|
{
|
||||||
|
JNIEnv *jni = static_cast<JNIEnv *>(SDL_AndroidGetJNIEnv());
|
||||||
|
|
||||||
|
jni->DeleteGlobalRef(m_activity);
|
||||||
|
m_activity = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Android::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path)
|
bool GpFileSystem_Android::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path)
|
||||||
{
|
{
|
||||||
std::string resolvedPath;
|
std::string resolvedPath;
|
||||||
bool isAsset;
|
bool isAsset;
|
||||||
if (!ResolvePath(virtualDirectory, path, resolvedPath, isAsset))
|
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath, isAsset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (isAsset)
|
if (isAsset)
|
||||||
@@ -281,6 +322,7 @@ bool GpFileSystem_Android::FileExists(PortabilityLayer::VirtualDirectory_t virtu
|
|||||||
if (!rw)
|
if (!rw)
|
||||||
return false;
|
return false;
|
||||||
SDL_RWclose(rw);
|
SDL_RWclose(rw);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat s;
|
struct stat s;
|
||||||
@@ -291,21 +333,26 @@ bool GpFileSystem_Android::FileLocked(PortabilityLayer::VirtualDirectory_t virtu
|
|||||||
{
|
{
|
||||||
std::string resolvedPath;
|
std::string resolvedPath;
|
||||||
bool isAsset;
|
bool isAsset;
|
||||||
if (!ResolvePath(virtualDirectory, path, resolvedPath, isAsset))
|
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath, isAsset))
|
||||||
{
|
{
|
||||||
*exists = false;
|
if (exists)
|
||||||
|
*exists = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAsset)
|
if (isAsset)
|
||||||
|
{
|
||||||
|
if (exists)
|
||||||
|
*exists = this->FileExists(virtualDirectory, path);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int permissions = access(resolvedPath.c_str(), W_OK | F_OK);
|
int permissions = access(resolvedPath.c_str(), W_OK | F_OK);
|
||||||
*exists = ((permissions & F_OK) != 0);
|
*exists = ((permissions & F_OK) != 0);
|
||||||
return ((permissions & W_OK) != 0);
|
return ((permissions & W_OK) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GpIOStream *GpFileSystem_Android::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition)
|
GpIOStream *GpFileSystem_Android::OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition)
|
||||||
{
|
{
|
||||||
const char *mode = nullptr;
|
const char *mode = nullptr;
|
||||||
bool canWrite = false;
|
bool canWrite = false;
|
||||||
@@ -332,7 +379,7 @@ GpIOStream *GpFileSystem_Android::OpenFile(PortabilityLayer::VirtualDirectory_t
|
|||||||
|
|
||||||
std::string resolvedPath;
|
std::string resolvedPath;
|
||||||
bool isAsset;
|
bool isAsset;
|
||||||
if (!ResolvePath(virtualDirectory, path, resolvedPath, isAsset))
|
if (!ResolvePath(virtualDirectory, subPaths, numSubPaths, resolvedPath, isAsset))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (isAsset)
|
if (isAsset)
|
||||||
@@ -386,7 +433,7 @@ bool GpFileSystem_Android::DeleteFile(PortabilityLayer::VirtualDirectory_t virtu
|
|||||||
{
|
{
|
||||||
std::string resolvedPath;
|
std::string resolvedPath;
|
||||||
bool isAsset;
|
bool isAsset;
|
||||||
if (!ResolvePath(virtualDirectory, path, resolvedPath, isAsset))
|
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath, isAsset))
|
||||||
{
|
{
|
||||||
existed = false;
|
existed = false;
|
||||||
return false;
|
return false;
|
||||||
@@ -404,8 +451,11 @@ bool GpFileSystem_Android::DeleteFile(PortabilityLayer::VirtualDirectory_t virtu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory)
|
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
|
||||||
{
|
{
|
||||||
|
if (IsVirtualDirectoryLooseResources(virtualDirectory))
|
||||||
|
return ScanAssetDirectory(virtualDirectory, paths, numPaths);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +505,85 @@ bool GpFileSystem_Android::ValidateFilePathUnicodeChar(uint32_t c) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GpFileSystem_Android::IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const
|
||||||
|
{
|
||||||
|
return virtualDir == PortabilityLayer::VirtualDirectories::kApplicationData || virtualDir == PortabilityLayer::VirtualDirectories::kGameData;
|
||||||
|
}
|
||||||
|
|
||||||
GpFileSystem_Android *GpFileSystem_Android::GetInstance()
|
GpFileSystem_Android *GpFileSystem_Android::GetInstance()
|
||||||
{
|
{
|
||||||
return &ms_instance;
|
return &ms_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GpDirectoryCursor_StringList final : public PortabilityLayer::HostDirectoryCursor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GpDirectoryCursor_StringList(std::vector<std::string> &paths);
|
||||||
|
~GpDirectoryCursor_StringList();
|
||||||
|
|
||||||
|
bool GetNext(const char *&outFileName) override;
|
||||||
|
void Destroy() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> m_paths;
|
||||||
|
size_t m_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
GpDirectoryCursor_StringList::GpDirectoryCursor_StringList(std::vector<std::string> &paths)
|
||||||
|
: m_index(0)
|
||||||
|
{
|
||||||
|
std::swap(paths, m_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
GpDirectoryCursor_StringList::~GpDirectoryCursor_StringList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpDirectoryCursor_StringList::GetNext(const char *&outFileName)
|
||||||
|
{
|
||||||
|
if (m_index == m_paths.size())
|
||||||
|
return false;
|
||||||
|
outFileName = m_paths[m_index].c_str();
|
||||||
|
m_index++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpDirectoryCursor_StringList::Destroy()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
||||||
|
{
|
||||||
|
std::string resolvedPath;
|
||||||
|
std::vector<std::string> subPaths;
|
||||||
|
bool isAsset = true;
|
||||||
|
if (!ResolvePath(virtualDirectory, paths, numPaths, resolvedPath, isAsset))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
JNIEnv *jni = static_cast<JNIEnv *>(SDL_AndroidGetJNIEnv());
|
||||||
|
|
||||||
|
jstring directory = jni->NewStringUTF(resolvedPath.c_str());
|
||||||
|
|
||||||
|
jobjectArray resultArray = static_cast<jobjectArray>(jni->CallObjectMethod(m_activity, m_scanAssetDirectoryMID, directory));
|
||||||
|
jni->DeleteLocalRef(directory);
|
||||||
|
|
||||||
|
size_t arrayLength = jni->GetArrayLength(resultArray);
|
||||||
|
subPaths.reserve(arrayLength);
|
||||||
|
for (size_t i = 0; i < arrayLength; i++)
|
||||||
|
{
|
||||||
|
jstring pathJStr = static_cast<jstring>(jni->GetObjectArrayElement(resultArray, i));
|
||||||
|
const char *pathStrChars = jni->GetStringUTFChars(pathJStr, nullptr);
|
||||||
|
|
||||||
|
subPaths.push_back(std::string(pathStrChars, static_cast<size_t>(jni->GetStringUTFLength(pathJStr))));
|
||||||
|
|
||||||
|
jni->ReleaseStringUTFChars(pathJStr, pathStrChars);
|
||||||
|
jni->DeleteLocalRef(pathJStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
jni->DeleteLocalRef(resultArray);
|
||||||
|
|
||||||
|
return new GpDirectoryCursor_StringList(subPaths);
|
||||||
|
}
|
||||||
|
|
||||||
GpFileSystem_Android GpFileSystem_Android::ms_instance;
|
GpFileSystem_Android GpFileSystem_Android::ms_instance;
|
||||||
|
|||||||
@@ -4,22 +4,35 @@
|
|||||||
|
|
||||||
#include "GpCoreDefs.h"
|
#include "GpCoreDefs.h"
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
class GpFileSystem_Android final : public PortabilityLayer::HostFileSystem
|
class GpFileSystem_Android final : public PortabilityLayer::HostFileSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpFileSystem_Android();
|
GpFileSystem_Android();
|
||||||
|
~GpFileSystem_Android();
|
||||||
|
|
||||||
|
void InitJNI();
|
||||||
|
void ShutdownJNI();
|
||||||
|
|
||||||
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
||||||
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
|
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
|
||||||
GpIOStream *OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
|
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
|
||||||
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
|
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
|
||||||
PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) override;
|
PortabilityLayer::HostDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
|
||||||
|
|
||||||
bool ValidateFilePath(const char *path, size_t sz) const override;
|
bool ValidateFilePath(const char *path, size_t pathLen) const override;
|
||||||
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
||||||
|
|
||||||
|
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
|
||||||
|
|
||||||
static GpFileSystem_Android *GetInstance();
|
static GpFileSystem_Android *GetInstance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PortabilityLayer::HostDirectoryCursor *ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
|
||||||
|
|
||||||
|
jobject m_activity;
|
||||||
|
jmethodID m_scanAssetDirectoryMID;
|
||||||
|
|
||||||
static GpFileSystem_Android ms_instance;
|
static GpFileSystem_Android ms_instance;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ int main(int argc, char* argv[])
|
|||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
SDL_GL_LoadLibrary("libGLESv2.so");
|
//SDL_GL_LoadLibrary("libGLESv2.so");
|
||||||
|
|
||||||
|
GpFileSystem_Android::GetInstance()->InitJNI();
|
||||||
|
|
||||||
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Android::GetInstance());
|
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Android::GetInstance());
|
||||||
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Android::GetInstance());
|
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Android::GetInstance());
|
||||||
@@ -57,6 +59,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
int returnCode = GpMain::Run();
|
int returnCode = GpMain::Run();
|
||||||
|
|
||||||
|
GpFileSystem_Android::GetInstance()->ShutdownJNI();
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
// This doesn't even actually exit, but it does stop this stupid brain-damaged OS from
|
// This doesn't even actually exit, but it does stop this stupid brain-damaged OS from
|
||||||
|
|||||||
@@ -1,7 +1,30 @@
|
|||||||
package org.glideport.game;
|
package org.glideport.game;
|
||||||
|
|
||||||
import org.libsdl.app.SDLActivity;
|
import org.libsdl.app.SDLActivity;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
public class GpActivity extends SDLActivity
|
public class GpActivity extends SDLActivity
|
||||||
{
|
{
|
||||||
|
private AssetManager assetManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
assetManager = getAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] scanAssetDirectory(String directory)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return this.assetManager.list(directory);
|
||||||
|
}
|
||||||
|
catch (java.io.IOException ex)
|
||||||
|
{
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user