Skip to content

Commit

Permalink
Add ability to read and write to app internal dir and cache dir in An…
Browse files Browse the repository at this point in the history
…droid, getUserDataDirectory() and getUserHomeDirectory() are point to inernal storage.
  • Loading branch information
kynora committed Aug 25, 2016
1 parent d459e1b commit d9e9dc3
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 8 deletions.
@@ -1,6 +1,12 @@
package com.garagegames.torque2d;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Vector;

Expand Down Expand Up @@ -331,6 +337,29 @@ public static int GetFileSize(Context context, String file)
return ret;
}

public static String LoadInternalFile(Context context, String fileName)
{
try {
FileInputStream fis = new FileInputStream(new File(fileName));
DataInputStream in = new DataInputStream(fis);
BufferedReader inputReader = new BufferedReader(new InputStreamReader(in));
String inputString;
StringBuilder sb = new StringBuilder();
while ((inputString = inputReader.readLine()) != null) {
sb.append(inputString);
}
fis.close();
inputReader.close();
in.close();

return sb.toString();

} catch (IOException e) {
e.printStackTrace();
return "";
}
}

public static void OpenURL(Context context, String url)
{
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
Expand Down
53 changes: 45 additions & 8 deletions engine/source/platformAndroid/AndroidFileio.cpp
Expand Up @@ -46,6 +46,36 @@
//Cache handling functions
//-----------------------------------------------------------------------------
bool isCachePath(const char* path)
{
if (!path || !*path)
return false;

if (path[0] == '/')
{
if (strstr(path, Platform::osGetTemporaryDirectory()) != NULL)
{
return true;
}
else
{
return false;
}
}
else
{
const char* tmp = Platform::osGetTemporaryDirectory();
if (strstr(path, tmp+1) != NULL)
{
return true;
}
else
{
return false;
}
}
}

bool isUserDataPath(const char* path)
{
if (!path || !*path)
return false;
Expand Down Expand Up @@ -142,7 +172,7 @@ File::~File()
File::Status File::open(const char *filename, const AccessMode openMode)
{
//If its a cache path then we need to open it using C methods not AssetManager
if (isCachePath(filename))
if (isCachePath(filename) || isUserDataPath(filename))
{
if (dStrlen(filename) > MAX_MAC_PATH_LONG)
Con::warnf("File::open: Filename length is pretty long...");
Expand All @@ -155,7 +185,14 @@ File::Status File::open(const char *filename, const AccessMode openMode)
switch (openMode)
{
case Read:
handle = (void *)fopen(filename, "rb"); // read only
capability = FileRead;
filePointer = 0;
buffer = (U8*)_AndroidLoadInternalFile(filename, &size);
if (buffer == NULL)
currentStatus = UnknownError;
else
currentStatus = Ok;
return currentStatus;
break;
case Write:
handle = (void *)fopen(filename, "wb"); // write only
Expand Down Expand Up @@ -794,7 +831,7 @@ bool Platform::isFile(const char *path)
if (!path || !*path)
return false;

if (isCachePath(path))
if (isCachePath(path) || isUserDataPath(path))
{
// make sure we can stat the file
struct stat statData;
Expand Down Expand Up @@ -824,7 +861,7 @@ bool Platform::isDirectory(const char *path)
if (!path || !*path)
return false;

if (isCachePath(path))
if (isCachePath(path) || isUserDataPath(path))
{
// make sure we can stat the file
struct stat statData;
Expand All @@ -847,7 +884,7 @@ S32 Platform::getFileSize(const char* pFilePath)
if (!pFilePath || !*pFilePath)
return 0;

if (isCachePath(pFilePath))
if (isCachePath(pFilePath) || isUserDataPath(pFilePath))
{
struct stat statData;
if( stat(pFilePath, &statData) < 0 )
Expand Down Expand Up @@ -899,7 +936,7 @@ inline bool isGoodDirectoryCache(dirent* entry)
//-----------------------------------------------------------------------------
bool Platform::hasSubDirectory(const char *path)
{
if (isCachePath(path))
if (isCachePath(path) || isUserDataPath(path))
{
DIR *dir;
dirent *entry;
Expand Down Expand Up @@ -1091,7 +1128,7 @@ bool recurseDumpDirectoriesCache(const char *basePath, const char *path, Vector<
//-----------------------------------------------------------------------------
bool Platform::dumpDirectories(const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath)
{
if (isCachePath(path))
if (isCachePath(path) || isUserDataPath(path))
{
PROFILE_START(dumpDirectories);

Expand Down Expand Up @@ -1247,7 +1284,7 @@ static bool recurseDumpPathCache(const char* curPath, Vector<Platform::FileInfo>
//-----------------------------------------------------------------------------
bool Platform::dumpPath(const char *path, Vector<Platform::FileInfo>& fileVector, S32 depth)
{
if (isCachePath(path))
if (isCachePath(path) || isUserDataPath(path))
{
PROFILE_START(dumpPath);
const S32 len = dStrlen(path) + 1;
Expand Down
94 changes: 94 additions & 0 deletions engine/source/platformAndroid/T2DActivity.cpp
Expand Up @@ -1225,6 +1225,7 @@ void android_main(struct android_app* state) {

//store the cache dir
activity.loadCacheDir();
activity.loadInternalDir();

//enumerate fonts
activity.enumerateFonts();
Expand Down Expand Up @@ -2622,4 +2623,97 @@ void adprintf(const char* fmt,...) {
__android_log_print(ANDROID_LOG_INFO, "Torque2D", "%s", ss.str().c_str());
}

void T2DActivity::loadInternalDir(){

// Attaches the current thread to the JVM.
jint lResult;
jint lFlags = 0;
JavaVM* lJavaVM = platState.engine->app->activity->vm;
JNIEnv* lJNIEnv = platState.engine->app->activity->env;

JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
lJavaVMAttachArgs.name = "NativeThread";
lJavaVMAttachArgs.group = NULL;

lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
if (lResult == JNI_ERR) {
return;
}

// Retrieves NativeActivity.
jobject lNativeActivity = platState.engine->app->activity->clazz;
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);

jmethodID getFilesDir = lJNIEnv->GetMethodID(ClassNativeActivity, "getFilesDir", "()Ljava/io/File;");
jobject file = lJNIEnv->CallObjectMethod(platState.engine->app->activity->clazz, getFilesDir);
jclass fileClass = lJNIEnv->FindClass("java/io/File");
jmethodID getAbsolutePath = lJNIEnv->GetMethodID(fileClass, "getAbsolutePath", "()Ljava/lang/String;");
jstring jpath = (jstring)lJNIEnv->CallObjectMethod(file, getAbsolutePath);
const char* app_dir = lJNIEnv->GetStringUTFChars(jpath, NULL);

strcpy(internalDir, app_dir);
internalDir[strlen(app_dir)] = '\0';

lJNIEnv->ReleaseStringUTFChars(jpath, app_dir);

// Finished with the JVM.
lJavaVM->DetachCurrentThread();
}


char* _AndroidLoadInternalFile(const char* fn, U32 *size)
{
// Attaches the current thread to the JVM.
jint lResult;
jint lFlags = 0;

JavaVM* lJavaVM = engine.app->activity->vm;
JNIEnv* lJNIEnv = engine.app->activity->env;

JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
lJavaVMAttachArgs.name = "NativeThread";
lJavaVMAttachArgs.group = NULL;

lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
if (lResult == JNI_ERR) {
return "";
}

// Retrieves NativeActivity.
jobject lNativeActivity = engine.app->activity->clazz;
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);

jmethodID getClassLoader = lJNIEnv->GetMethodID(ClassNativeActivity,"getClassLoader", "()Ljava/lang/ClassLoader;");
jobject cls = lJNIEnv->CallObjectMethod(lNativeActivity, getClassLoader);
jclass classLoader = lJNIEnv->FindClass("java/lang/ClassLoader");
jmethodID findClass = lJNIEnv->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
jstring strClassName = lJNIEnv->NewStringUTF("com.garagegames.torque2d.FileWalker");
jclass FileWalkerClass = (jclass)lJNIEnv->CallObjectMethod(cls, findClass, strClassName);
jstring fileName = lJNIEnv->NewStringUTF(fn);
jmethodID MethodFileWalker = lJNIEnv->GetStaticMethodID(FileWalkerClass, "LoadInternalFile", "(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;");
jstring jcontent = (jstring)lJNIEnv->CallStaticObjectMethod(FileWalkerClass, MethodFileWalker, lNativeActivity, fileName);

lJNIEnv->DeleteLocalRef(strClassName);
lJNIEnv->DeleteLocalRef(fileName);
*size = 0;
char *buffer = NULL;
if (jcontent != NULL)
{
const char* value = lJNIEnv->GetStringUTFChars(jcontent, NULL);
*size = strlen(value);
buffer = new char[*size + 1];
strcpy(buffer, value);
buffer[*size] = '\0';

lJNIEnv->ReleaseStringUTFChars(jcontent, value);
lJavaVM->DetachCurrentThread();
return buffer;
}

lJavaVM->DetachCurrentThread();
return buffer;
}


7 changes: 7 additions & 0 deletions engine/source/platformAndroid/T2DActivity.h
Expand Up @@ -41,6 +41,7 @@ extern int _AndroidGetScreenWidth();
extern int _AndroidGetScreenHeight();
extern S32 _AndroidGameGetOrientation();
extern char* _AndroidLoadFile(const char* fileName, U32 *size);
extern char* _AndroidLoadInternalFile(const char* fileName, U32 *size);
extern void android_InitDirList(const char* dir);
extern void android_GetNextDir(const char* pdir, char *dir);
extern void android_GetNextFile(const char* pdir, char *file);
Expand Down Expand Up @@ -93,6 +94,7 @@ class T2DActivity {
bool isLayedOut;

char cacheDir[2048];
char internalDir[2048];

bool accelerometerActive;

Expand All @@ -113,6 +115,11 @@ class T2DActivity {
char *getCacheDir() {
return cacheDir;
}
void loadInternalDir();
char *getInternalDir() {
return internalDir;
}

void update();
void finishShutdown();
void finishGLSetup();
Expand Down

0 comments on commit d9e9dc3

Please sign in to comment.