Set placer to nil instead of a non-functional one in item_OnPlace (#6449)
[oweals/minetest.git] / src / porting_android.cpp
index 6871ce465b7cfac9a2c0e16e028e047a80407024..7c74f7b5b22dda0d4d3e7fa1a16fc3e09d4f0e9c 100644 (file)
@@ -21,12 +21,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #error This file may only be compiled for android!
 #endif
 
+#include "util/numeric.h"
 #include "porting.h"
 #include "porting_android.h"
+#include "threading/thread.h"
 #include "config.h"
 #include "filesys.h"
 #include "log.h"
+
 #include <sstream>
+#include <exception>
+#include <cstdlib>
 
 #ifdef GPROF
 #include "prof.h"
@@ -39,30 +44,23 @@ void android_main(android_app *app)
        int retval = 0;
        porting::app_global = app;
 
-       porting::setThreadName("MainThread");
+       Thread::setName("Main");
 
        try {
                app_dummy();
-               char *argv[] = { (char*) "minetest" };
-               main(sizeof(argv) / sizeof(argv[0]), argv);
-               }
-       catch(BaseException e) {
-               std::stringstream msg;
-               msg << "Exception handled by main: " << e.what();
-               const char* message = msg.str().c_str();
-               __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME, "%s", message);
-               errorstream << msg << std::endl;
+               char *argv[] = {strdup(PROJECT_NAME), NULL};
+               main(ARRLEN(argv) - 1, argv);
+               free(argv[0]);
+       } catch (std::exception &e) {
+               errorstream << "Uncaught exception in main thread: " << e.what() << std::endl;
                retval = -1;
-       }
-       catch(...) {
-               __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME,
-                               "Some exception occured");
+       } catch (...) {
                errorstream << "Uncaught exception in main thread!" << std::endl;
                retval = -1;
        }
 
        porting::cleanupAndroid();
-       errorstream << "Shutting down minetest." << std::endl;
+       infostream << "Shutting down." << std::endl;
        exit(retval);
 }
 
@@ -126,7 +124,7 @@ void initAndroid()
        JavaVM *jvm = app_global->activity->vm;
        JavaVMAttachArgs lJavaVMAttachArgs;
        lJavaVMAttachArgs.version = JNI_VERSION_1_6;
-       lJavaVMAttachArgs.name = "MinetestNativeThread";
+       lJavaVMAttachArgs.name = PROJECT_NAME_C "NativeThread";
        lJavaVMAttachArgs.group = NULL;
 #ifdef NDEBUG
        // This is a ugly hack as arm v7a non debuggable builds crash without this
@@ -147,7 +145,7 @@ void initAndroid()
 
 #ifdef GPROF
        /* in the start-up code */
-       __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME,
+       __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME_C,
                        "Initializing GPROF profiler");
        monstartup("libminetest.so");
 #endif
@@ -166,29 +164,63 @@ void cleanupAndroid()
        jvm->DetachCurrentThread();
 }
 
-void setExternalStorageDir(JNIEnv* lJNIEnv)
+static std::string javaStringToUTF8(jstring js)
+{
+       std::string str;
+       // Get string as a UTF-8 c-string
+       const char *c_str = jnienv->GetStringUTFChars(js, NULL);
+       // Save it
+       str = c_str;
+       // And free the c-string
+       jnienv->ReleaseStringUTFChars(js, c_str);
+       return str;
+}
+
+// Calls static method if obj is NULL
+static std::string getAndroidPath(jclass cls, jobject obj, jclass cls_File,
+               jmethodID mt_getAbsPath, const char *getter)
+{
+       // Get getter method
+       jmethodID mt_getter;
+       if (obj)
+               mt_getter = jnienv->GetMethodID(cls, getter,
+                               "()Ljava/io/File;");
+       else
+               mt_getter = jnienv->GetStaticMethodID(cls, getter,
+                               "()Ljava/io/File;");
+
+       // Call getter
+       jobject ob_file;
+       if (obj)
+               ob_file = jnienv->CallObjectMethod(obj, mt_getter);
+       else
+               ob_file = jnienv->CallStaticObjectMethod(cls, mt_getter);
+
+       // Call getAbsolutePath
+       jstring js_path = (jstring) jnienv->CallObjectMethod(ob_file,
+                       mt_getAbsPath);
+
+       return javaStringToUTF8(js_path);
+}
+
+void initializePathsAndroid()
 {
-       // Android: Retrieve ablsolute path to external storage device (sdcard)
-       jclass ClassEnv      = lJNIEnv->FindClass("android/os/Environment");
-       jmethodID MethodDir  =
-                       lJNIEnv->GetStaticMethodID(ClassEnv,
-                                       "getExternalStorageDirectory","()Ljava/io/File;");
-       jobject ObjectFile   = lJNIEnv->CallStaticObjectMethod(ClassEnv, MethodDir);
-       jclass ClassFile     = lJNIEnv->FindClass("java/io/File");
-
-       jmethodID MethodPath =
-                       lJNIEnv->GetMethodID(ClassFile, "getAbsolutePath",
-                                       "()Ljava/lang/String;");
-       jstring StringPath   =
-                       (jstring) lJNIEnv->CallObjectMethod(ObjectFile, MethodPath);
-
-       const char *externalPath = lJNIEnv->GetStringUTFChars(StringPath, NULL);
-       std::string userPath(externalPath);
-       lJNIEnv->ReleaseStringUTFChars(StringPath, externalPath);
-
-       path_storage             = userPath;
-       path_user                = userPath + DIR_DELIM + PROJECT_NAME;
-       path_share               = userPath + DIR_DELIM + PROJECT_NAME;
+       // Get Environment class
+       jclass cls_Env = jnienv->FindClass("android/os/Environment");
+       // Get File class
+       jclass cls_File = jnienv->FindClass("java/io/File");
+       // Get getAbsolutePath method
+       jmethodID mt_getAbsPath = jnienv->GetMethodID(cls_File,
+                               "getAbsolutePath", "()Ljava/lang/String;");
+
+       path_cache   = getAndroidPath(nativeActivity, app_global->activity->clazz,
+                       cls_File, mt_getAbsPath, "getCacheDir");
+       path_storage = getAndroidPath(cls_Env, NULL, cls_File, mt_getAbsPath,
+                       "getExternalStorageDirectory");
+       path_user    = path_storage + DIR_DELIM + PROJECT_NAME_C;
+       path_share   = path_storage + DIR_DELIM + PROJECT_NAME_C;
+
+       migrateCachePath();
 }
 
 void showInputDialog(const std::string& acceptButton, const  std::string& hint,
@@ -241,7 +273,7 @@ std::string getInputDialogValue()
        return text;
 }
 
-#if not defined(SERVER)
+#ifndef SERVER
 float getDisplayDensity()
 {
        static bool firstrun = true;
@@ -291,5 +323,5 @@ v2u32 getDisplaySize()
        }
        return retval;
 }
-#endif //SERVER
+#endif // ndef SERVER
 }