| |
| |
| |
|
|
| #ifdef ANDROID |
| #include "common/android_storage.h" |
|
|
| namespace AndroidStorage { |
| JNIEnv* GetEnvForThread() { |
| thread_local static struct OwnedEnv { |
| OwnedEnv() { |
| status = g_jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); |
| if (status == JNI_EDETACHED) |
| g_jvm->AttachCurrentThread(&env, nullptr); |
| } |
|
|
| ~OwnedEnv() { |
| if (status == JNI_EDETACHED) |
| g_jvm->DetachCurrentThread(); |
| } |
|
|
| int status; |
| JNIEnv* env = nullptr; |
| } owned; |
| return owned.env; |
| } |
|
|
| AndroidOpenMode ParseOpenmode(const std::string_view openmode) { |
| AndroidOpenMode android_open_mode = AndroidOpenMode::NEVER; |
| const char* mode = openmode.data(); |
| int o = 0; |
| switch (*mode++) { |
| case 'r': |
| android_open_mode = AndroidStorage::AndroidOpenMode::READ; |
| break; |
| case 'w': |
| android_open_mode = AndroidStorage::AndroidOpenMode::WRITE; |
| o = O_TRUNC; |
| break; |
| case 'a': |
| android_open_mode = AndroidStorage::AndroidOpenMode::WRITE; |
| o = O_APPEND; |
| break; |
| } |
|
|
| |
| if (*mode == '+' || (*mode == 'b' && mode[1] == '+')) { |
| android_open_mode = AndroidStorage::AndroidOpenMode::READ_WRITE; |
| } |
|
|
| return android_open_mode | o; |
| } |
|
|
| void InitJNI(JNIEnv* env, jclass clazz) { |
| env->GetJavaVM(&g_jvm); |
| native_library = clazz; |
|
|
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ |
| F(JMethodID, JMethodName, Signature) |
| #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \ |
| F(JMethodID, JMethodName, Signature) |
| #define F(JMethodID, JMethodName, Signature) \ |
| JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature); |
| ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) |
| ANDROID_STORAGE_FUNCTIONS(FS) |
| #undef F |
| #undef FS |
| #undef FR |
| } |
|
|
| void CleanupJNI() { |
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) |
| #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) |
| #define F(JMethodID) JMethodID = nullptr; |
| ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) |
| ANDROID_STORAGE_FUNCTIONS(FS) |
| #undef F |
| #undef FS |
| #undef FR |
| } |
|
|
| bool CreateFile(const std::string& directory, const std::string& filename) { |
| if (create_file == nullptr) |
| return false; |
| auto env = GetEnvForThread(); |
| jstring j_directory = env->NewStringUTF(directory.c_str()); |
| jstring j_filename = env->NewStringUTF(filename.c_str()); |
| return env->CallStaticBooleanMethod(native_library, create_file, j_directory, j_filename); |
| } |
|
|
| bool CreateDir(const std::string& directory, const std::string& filename) { |
| if (create_dir == nullptr) |
| return false; |
| auto env = GetEnvForThread(); |
| jstring j_directory = env->NewStringUTF(directory.c_str()); |
| jstring j_directory_name = env->NewStringUTF(filename.c_str()); |
| return env->CallStaticBooleanMethod(native_library, create_dir, j_directory, j_directory_name); |
| } |
|
|
| int OpenContentUri(const std::string& filepath, AndroidOpenMode openmode) { |
| if (open_content_uri == nullptr) |
| return -1; |
|
|
| const char* mode = ""; |
| switch (openmode) { |
| case AndroidOpenMode::READ: |
| mode = "r"; |
| break; |
| case AndroidOpenMode::WRITE: |
| mode = "w"; |
| break; |
| case AndroidOpenMode::READ_WRITE: |
| mode = "rw"; |
| break; |
| case AndroidOpenMode::WRITE_TRUNCATE: |
| mode = "wt"; |
| break; |
| case AndroidOpenMode::WRITE_APPEND: |
| mode = "wa"; |
| break; |
| case AndroidOpenMode::READ_WRITE_APPEND: |
| mode = "rwa"; |
| break; |
| case AndroidOpenMode::READ_WRITE_TRUNCATE: |
| mode = "rwt"; |
| break; |
| case AndroidOpenMode::NEVER: |
| return -1; |
| } |
| auto env = GetEnvForThread(); |
| jstring j_filepath = env->NewStringUTF(filepath.c_str()); |
| jstring j_mode = env->NewStringUTF(mode); |
| return env->CallStaticIntMethod(native_library, open_content_uri, j_filepath, j_mode); |
| } |
|
|
| std::vector<std::string> GetFilesName(const std::string& filepath) { |
| auto vector = std::vector<std::string>(); |
| if (get_files_name == nullptr) |
| return vector; |
| auto env = GetEnvForThread(); |
| jstring j_filepath = env->NewStringUTF(filepath.c_str()); |
| auto j_object = |
| (jobjectArray)env->CallStaticObjectMethod(native_library, get_files_name, j_filepath); |
| const jsize j_size = env->GetArrayLength(j_object); |
| vector.reserve(j_size); |
| for (int i = 0; i < j_size; i++) { |
| auto string = (jstring)(env->GetObjectArrayElement(j_object, i)); |
| vector.emplace_back(env->GetStringUTFChars(string, nullptr)); |
| } |
| return vector; |
| } |
|
|
| bool CopyFile(const std::string& source, const std::string& destination_path, |
| const std::string& destination_filename) { |
| if (copy_file == nullptr) |
| return false; |
| auto env = GetEnvForThread(); |
| jstring j_source_path = env->NewStringUTF(source.c_str()); |
| jstring j_destination_path = env->NewStringUTF(destination_path.c_str()); |
| jstring j_destination_filename = env->NewStringUTF(destination_filename.c_str()); |
| return env->CallStaticBooleanMethod(native_library, copy_file, j_source_path, |
| j_destination_path, j_destination_filename); |
| } |
|
|
| bool RenameFile(const std::string& source, const std::string& filename) { |
| if (rename_file == nullptr) |
| return false; |
| auto env = GetEnvForThread(); |
| jstring j_source_path = env->NewStringUTF(source.c_str()); |
| jstring j_destination_path = env->NewStringUTF(filename.c_str()); |
| return env->CallStaticBooleanMethod(native_library, rename_file, j_source_path, |
| j_destination_path); |
| } |
|
|
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ |
| F(FunctionName, ReturnValue, JMethodID, Caller) |
| #define F(FunctionName, ReturnValue, JMethodID, Caller) \ |
| ReturnValue FunctionName(const std::string& filepath) { \ |
| if (JMethodID == nullptr) { \ |
| return 0; \ |
| } \ |
| auto env = GetEnvForThread(); \ |
| jstring j_filepath = env->NewStringUTF(filepath.c_str()); \ |
| return env->Caller(native_library, JMethodID, j_filepath); \ |
| } |
| ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) |
| #undef F |
| #undef FR |
|
|
| } |
| #endif |
|
|