Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
project(TimezoneHermesFix)
cmake_minimum_required(VERSION 3.9.0)

set(PACKAGE_NAME "timezone-hermes-fix")

# Add your sources
add_library(
${PACKAGE_NAME}
SHARED
src/main/cpp/TimezoneHermesFix.cpp
src/main/cpp/OnLoad.cpp
)

# Configure C++ 17
set_target_properties(
${PACKAGE_NAME}
PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
LINKER_LANGUAGE CXX
)

find_package(fbjni REQUIRED CONFIG)
find_package(ReactAndroid REQUIRED CONFIG)
find_package(hermes-engine REQUIRED CONFIG)
string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_HERMES=1")

target_link_libraries(
${PACKAGE_NAME}
hermes-engine::libhermes
)

target_include_directories(
${PACKAGE_NAME}
PRIVATE
"src/main/cpp"
"${REACT_NATIVE_DIR}/ReactCommon"
"${REACT_NATIVE_DIR}/ReactCommon/callinvoker"
"${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/react/turbomodule"
# Add Hermes include directories
"${REACT_NATIVE_DIR}/ReactCommon/hermes"
"${REACT_NATIVE_DIR}/third-party/hermes/API"
)

# Link libraries
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
target_link_libraries(
${PACKAGE_NAME}
ReactAndroid::reactnative
)
else()
target_link_libraries(
${PACKAGE_NAME}
ReactAndroid::reactnativejni
)
endif()

target_link_libraries(
${PACKAGE_NAME}
android
log
fbjni::fbjni
ReactAndroid::jsi
)

39 changes: 39 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,29 @@ def getExtOrIntegerDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["TimezoneHermesFix_" + name]).toInteger()
}

def REACT_NATIVE_BUILD_FROM_SOURCE = findProject(":packages:react-native:ReactAndroid") != null
def REACT_NATIVE_DIR = REACT_NATIVE_BUILD_FROM_SOURCE
? findProject(":packages:react-native:ReactAndroid").getProjectDir().parent
: file(providers.exec {
workingDir(rootDir)
commandLine("node", "--print", "require.resolve('react-native/package.json')")
}.standardOutput.asText.get().trim()).parent

def reactNativeArchitectures() {
def value = project.getProperties().get("reactNativeArchitectures")
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}

def resolveBuildType() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests()['args'].toString()

return tskReqStr.contains('Release') ? 'release' : 'debug'
}

def reactProperties = new Properties()
file("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }

android {
namespace "com.timezonehermesfix"

Expand All @@ -33,10 +56,19 @@ android {
defaultConfig {
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
externalNativeBuild {
cmake {
cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all"
arguments "-DANDROID_STL=c++_shared",
"-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}"
abiFilters(*reactNativeArchitectures())
}
}
}

buildFeatures {
buildConfig true
prefab true
}

buildTypes {
Expand All @@ -62,6 +94,12 @@ android {
]
}
}

externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}

repositories {
Expand All @@ -74,6 +112,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
dependencies {
implementation "com.facebook.react:react-android"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "com.facebook.react:hermes-android"
}

react {
Expand Down
11 changes: 11 additions & 0 deletions android/src/main/cpp/OnLoad.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <jni.h>
#include <fbjni/fbjni.h>
#include "TimezoneHermesFix.h"

using namespace facebook::jni;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return initialize(vm, [] {
TimezoneHermesFix::registerNatives();
});
}
90 changes: 90 additions & 0 deletions android/src/main/cpp/TimezoneHermesFix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include "TimezoneHermesFix.h"
#include <jsi/jsi.h>
#include <ReactCommon/CallInvokerHolder.h>
#include <fbjni/fbjni.h>
#include <hermes/hermes.h>
#include <android/log.h>

using namespace facebook;
using namespace facebook::jni;
using namespace facebook::react;
using namespace facebook::hermes;

#define LOG_TAG "TimezoneHermesFix"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

void TimezoneHermesFix::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", TimezoneHermesFix::initHybrid),
makeNativeMethod("coSieDzieje", TimezoneHermesFix::coSieDzieje),
});
}

jni::local_ref<TimezoneHermesFix::jhybriddata> TimezoneHermesFix::initHybrid(
jni::alias_ref<jhybridobject>) {
return makeCxxInstance();
}

void TimezoneHermesFix::coSieDzieje(jlong jsRuntimePtr) {
LOGD("coSieDzieje called with jsRuntimePtr: %ld", jsRuntimePtr);

// Get JSI Runtime pointer (equivalent to iOS cxxBridge.runtime)
auto jsiRuntime = reinterpret_cast<jsi::Runtime*>(jsRuntimePtr);
if (jsiRuntime == nullptr) {
LOGE("jsiRuntime is null");
return;
}

// Cast to HermesRuntime (equivalent to iOS reinterpret_cast)
auto hermesRuntime = reinterpret_cast<HermesRuntime*>(jsiRuntime);
if (hermesRuntime == nullptr) {
LOGE("hermesRuntime is null - not running on Hermes");
return;
}

try {
// Call resetTimezoneCache on Hermes runtime (same as iOS)
hermesRuntime->resetTimezoneCache();
LOGD("Successfully called resetTimezoneCache on Hermes runtime");

} catch (const jsi::JSError& error) {
LOGE("JSI Error calling resetTimezoneCache: %s", error.getMessage().c_str());
} catch (const std::exception& error) {
LOGE("Exception calling resetTimezoneCache: %s", error.what());
}
}

//void TimezoneHermesFix::resetHermesTimezoneCacheNative(
// JNIEnv* env,
// jclass clazz,
// jlong jsRuntimePtr,
// jobject callInvokerHolder
//) {
// LOGD("resetHermesTimezoneCacheNative called with jsRuntimePtr: %ld", jsRuntimePtr);
//
// // Get JSI Runtime pointer (equivalent to iOS cxxBridge.runtime)
// auto jsiRuntime = reinterpret_cast<jsi::Runtime*>(jsRuntimePtr);
// if (jsiRuntime == nullptr) {
// LOGE("jsiRuntime is null");
// return;
// }
//
// // Cast to HermesRuntime (equivalent to iOS reinterpret_cast)
//// auto hermesRuntime = reinterpret_cast<HermesRuntime*>(jsiRuntime);
//// if (hermesRuntime == nullptr) {
//// LOGE("hermesRuntime is null - not running on Hermes");
//// return;
//// }
//
// try {
// // Call resetTimezoneCache on Hermes runtime (same as iOS)
//// hermesRuntime->resetTimezoneCache();
// LOGD("Successfully called resetTimezoneCache on Hermes runtime");
//
// } catch (const jsi::JSError& error) {
// LOGE("JSI Error calling resetTimezoneCache: %s", error.getMessage().c_str());
// } catch (const std::exception& error) {
// LOGE("Exception calling resetTimezoneCache: %s", error.what());
// }
//}
21 changes: 21 additions & 0 deletions android/src/main/cpp/TimezoneHermesFix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <jni.h>
#include <jsi/jsi.h>
#include <ReactCommon/CallInvokerHolder.h>
#include <fbjni/fbjni.h>

using namespace facebook;

class TimezoneHermesFix: public jni::HybridClass<TimezoneHermesFix> {
public:
static constexpr auto kJavaDescriptor = "Lcom/timezonehermesfix/TimezoneHermesFixModule;";
static void registerNatives();
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>);

void coSieDzieje(jlong jsRuntimePtr);

private:
friend HybridBase;
TimezoneHermesFix() {}
};
Loading
Loading