Ver Fonte

Add ability to read and write to app internal dir and cache dir in Android, getUserDataDirectory() and getUserHomeDirectory() are point to inernal storage.

Nora Ky há 9 anos atrás
pai
commit
d9e9dc329e

+ 29 - 0
engine/compilers/android-studio/app/src/main/java/com/garagegames/torque2d/FileWalker.java

@@ -1,6 +1,12 @@
 package com.garagegames.torque2d;
 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.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.util.Hashtable;
 import java.util.Hashtable;
 import java.util.Vector;
 import java.util.Vector;
 
 
@@ -331,6 +337,29 @@ public class FileWalker
 		return ret;
 		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)
 	public static void OpenURL(Context context, String url)
 	{
 	{
 		Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
 		Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

+ 45 - 8
engine/source/platformAndroid/AndroidFileio.cpp

@@ -46,6 +46,36 @@
 //Cache handling functions
 //Cache handling functions
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 bool isCachePath(const char* path)
 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)
 	if (!path || !*path)
 	      return false;
 	      return false;
@@ -142,7 +172,7 @@ File::~File()
 File::Status File::open(const char *filename, const AccessMode openMode)
 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 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)
 	  if (dStrlen(filename) > MAX_MAC_PATH_LONG)
 	   	  Con::warnf("File::open: Filename length is pretty long...");
 	   	  Con::warnf("File::open: Filename length is pretty long...");
@@ -155,7 +185,14 @@ File::Status File::open(const char *filename, const AccessMode openMode)
 	  switch (openMode)
 	  switch (openMode)
 	  {
 	  {
 	  case Read:
 	  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;
 		 break;
 	  case Write:
 	  case Write:
 		 handle = (void *)fopen(filename, "wb"); // write only
 		 handle = (void *)fopen(filename, "wb"); // write only
@@ -794,7 +831,7 @@ bool Platform::isFile(const char *path)
    if (!path || !*path) 
    if (!path || !*path) 
       return false;
       return false;
 
 
-   if (isCachePath(path))
+   if (isCachePath(path) || isUserDataPath(path))
    {
    {
 	  // make sure we can stat the file
 	  // make sure we can stat the file
 	  struct stat statData;
 	  struct stat statData;
@@ -824,7 +861,7 @@ bool Platform::isDirectory(const char *path)
    if (!path || !*path) 
    if (!path || !*path) 
       return false;
       return false;
    
    
-   if (isCachePath(path))
+   if (isCachePath(path) || isUserDataPath(path))
    {
    {
 	  // make sure we can stat the file
 	  // make sure we can stat the file
 	  struct stat statData;
 	  struct stat statData;
@@ -847,7 +884,7 @@ S32 Platform::getFileSize(const char* pFilePath)
    if (!pFilePath || !*pFilePath) 
    if (!pFilePath || !*pFilePath) 
       return 0;
       return 0;
    
    
-   if (isCachePath(pFilePath))
+   if (isCachePath(pFilePath) || isUserDataPath(pFilePath))
    {
    {
 	  struct stat statData;
 	  struct stat statData;
 	  if( stat(pFilePath, &statData) < 0 )
 	  if( stat(pFilePath, &statData) < 0 )
@@ -899,7 +936,7 @@ inline bool isGoodDirectoryCache(dirent* entry)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 bool Platform::hasSubDirectory(const char *path) 
 bool Platform::hasSubDirectory(const char *path) 
 {
 {
-	if (isCachePath(path))
+	if (isCachePath(path) || isUserDataPath(path))
 	{
 	{
 	   DIR *dir;
 	   DIR *dir;
 	   dirent *entry;
 	   dirent *entry;
@@ -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)
 bool Platform::dumpDirectories(const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath)
 {
 {
-	if (isCachePath(path))
+	if (isCachePath(path) || isUserDataPath(path))
 	{
 	{
 	   PROFILE_START(dumpDirectories);
 	   PROFILE_START(dumpDirectories);
 
 
@@ -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)
 bool Platform::dumpPath(const char *path, Vector<Platform::FileInfo>& fileVector, S32 depth)
 {
 {
-	if (isCachePath(path))
+	if (isCachePath(path) || isUserDataPath(path))
 	{
 	{
 		PROFILE_START(dumpPath);
 		PROFILE_START(dumpPath);
 		const S32 len = dStrlen(path) + 1;
 		const S32 len = dStrlen(path) + 1;

+ 94 - 0
engine/source/platformAndroid/T2DActivity.cpp

@@ -1225,6 +1225,7 @@ void android_main(struct android_app* state) {
 
 
     //store the cache dir
     //store the cache dir
     activity.loadCacheDir();
     activity.loadCacheDir();
+    activity.loadInternalDir();
 
 
     //enumerate fonts
     //enumerate fonts
     activity.enumerateFonts();
     activity.enumerateFonts();
@@ -2622,4 +2623,97 @@ void adprintf(const char* fmt,...) {
     __android_log_print(ANDROID_LOG_INFO, "Torque2D", "%s", ss.str().c_str());
     __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 - 0
engine/source/platformAndroid/T2DActivity.h

@@ -41,6 +41,7 @@ extern int _AndroidGetScreenWidth();
 extern int _AndroidGetScreenHeight();
 extern int _AndroidGetScreenHeight();
 extern S32 _AndroidGameGetOrientation();
 extern S32 _AndroidGameGetOrientation();
 extern char* _AndroidLoadFile(const char* fileName, U32 *size);
 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_InitDirList(const char* dir);
 extern void android_GetNextDir(const char* pdir, char *dir);
 extern void android_GetNextDir(const char* pdir, char *dir);
 extern void android_GetNextFile(const char* pdir, char *file);
 extern void android_GetNextFile(const char* pdir, char *file);
@@ -93,6 +94,7 @@ private:
     bool isLayedOut;
     bool isLayedOut;
     
     
     char cacheDir[2048];
     char cacheDir[2048];
+    char internalDir[2048];
 
 
     bool accelerometerActive;
     bool accelerometerActive;
 
 
@@ -113,6 +115,11 @@ public:
     char *getCacheDir() {
     char *getCacheDir() {
     	return cacheDir;
     	return cacheDir;
     }
     }
+    void loadInternalDir();
+    char *getInternalDir() {
+    	return internalDir;
+    }
+
     void update();
     void update();
     void finishShutdown();
     void finishShutdown();
     void finishGLSetup();
     void finishGLSetup();