Skip to content

Commit

Permalink
FirebaseAndroid: introduce the new JNI module for Android support
Browse files Browse the repository at this point in the history
In order to interact with the C++ Firebase SDK, we need to have access
to the JVM and the JavaEnvironment. Introduce a JNI layer which allows
us to capture this information when loaded. Additionally, register a
`company.thebrowser.Native.RegisterActivity` method to allow us access
to the `Activity`. This is required to be called before the Firebase
layer is accessed by the application.
  • Loading branch information
compnerd committed Apr 1, 2024
1 parent d10aa46 commit 283174a
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 0 deletions.
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
cmake_minimum_required(VERSION 3.25)
project(swift-firebase
LANGUAGES Swift)
if(ANDROID)
enable_language(C)
include(FindJava)
include(UseJava)
endif()

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
Expand Down Expand Up @@ -39,6 +44,10 @@ else()
message(FATAL_ERROR "unsupported firebase-cpp-sdk platform")
endif()

if(ANDROID)
add_subdirectory(Sources/FirebaseAndroid)
endif()

add_library(FirebaseCore SHARED
Sources/FirebaseCore/FirebaseApp+Swift.swift
Sources/FirebaseCore/FirebaseConfiguration.swift
Expand All @@ -55,6 +64,10 @@ target_link_libraries(FirebaseCore PRIVATE
firebase_app
flatbuffers
zlibstatic)
if(ANDROID)
target_link_libraries(FirebaseCore PRIVATE
FirebaseAndroidJNI)
endif()

add_library(FirebaseAuth SHARED
Sources/FirebaseAuth/AuthStateDidChangeListenerHandle.swift
Expand Down
9 changes: 9 additions & 0 deletions Sources/FirebaseAndroid/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: BSD-3-Clause

add_library(FirebaseAndroidJNI SHARED
jni.c)
target_include_directories(FirebaseAndroidJNI PUBLIC
include)
target_link_libraries(FirebaseAndroidJNI PRIVATE
log)

12 changes: 12 additions & 0 deletions Sources/FirebaseAndroid/abi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#ifndef SwiftFirebase_FirebaseAndroidShim_abi_h
#define SwiftFirebase_FirebaseAndroidShim_abi_h

#if defined(FirebaseAndroidJNI_EXPORTS)
#define FIREBASE_ANDROID_ABI __attribute__((__visibility__("default")))
#else
#define FIREBASE_ANDROID_ABI __attribute__((__visibility__("default")))
#endif

#endif
20 changes: 20 additions & 0 deletions Sources/FirebaseAndroid/include/FirebaseAndroid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#ifndef SwiftFirebase_FirebaseAndroidShim_FirebaseAndroid_h
#define SwiftFirebase_FirebaseAndroidShim_FirebaseAndroid_h

#include <jni.h>

#if defined(__cplusplus)
extern "C" {
#endif

jobject _Nullable SwiftFirebase_GetActivity(void);
JNIEnv * _Nullable SwiftFirebase_GetJavaEnvironment(void);
JavaVM * _Nullable SwiftFirebase_GetJVM(void);

#if defined(__cplusplus)
}
#endif

#endif
6 changes: 6 additions & 0 deletions Sources/FirebaseAndroid/include/module.modulemap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause */

module FirebaseAndroid {
header "FirebaseAndroid.h"
export *
}
79 changes: 79 additions & 0 deletions Sources/FirebaseAndroid/jni.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#include "FirebaseAndroid.h"
#include "abi.h"
#include "log.h"

#include <assert.h>

static JavaVM *g_VM;
static JNIEnv *g_Env;
static jobject *g_Activity;

#define N_ELEMENTS(array) (sizeof((array)) / sizeof(*(array)))

static const char kClassPath[] = "company/thebrowser/Native";

static jboolean
SwiftFirebase_RegisterActivity(JNIEnv *env, jobject *this, jobject *activity)
{
assert(g_Activity == NULL && "re-registeration of activity");
if (g_Activity) return JNI_FALSE;

g_Activity = activity;
return JNI_TRUE;
}

static JNINativeMethod kMethods[] = {
{ "RegisterActivity", "()Z", SwiftFirebase_RegisterActivity },
};

static void
RegisterNativeMethods(JNIEnv *env)
{
jclass class;
jint result;

class = (*env)->FindClass(env, kClassPath);
if (class == NULL) {
LOG_ERROR("unable to find class '%s'", kClassPath);
return;
}
LOG_DEBUG("located class path '%s': %p", kClassPath, class);

result = (*env)->RegisterNatives(env, class, kMethods, N_ELEMENTS(kMethods));
if (result < 0) {
LOG_ERROR("JVM.RegisterNatives(%s): %u", kClassPath, result);
return;
}
LOG_DEBUG("registered %u methods", N_ELEMENTS(kMethods));
}

FIREBASE_ANDROID_ABI
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
g_VM = vm;
if ((*g_VM)->GetEnv(g_VM, (void **)&g_Env, JNI_VERSION_1_6) == JNI_OK)
return JNI_VERSION_1_6;
RegisterNativeMethods(g_Env);
return -1;
}

FIREBASE_ANDROID_ABI
jobject SwiftFirebase_GetActivity(void)
{
assert(g_Activity && "`GetActivity` invoked before `RegisterActivity`");
return *g_Activity;
}

FIREBASE_ANDROID_ABI
JNIEnv *SwiftFirebase_GetJavaEnvironment(void)
{
return g_Env;
}

FIREBASE_ANDROID_ABI
JavaVM *SwiftFirebase_GetJVM(void)
{
return g_VM;
}
17 changes: 17 additions & 0 deletions Sources/FirebaseAndroid/log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#ifndef SwiftFirebase_FirebaseAndroidShim_logging_h
#define SwiftFirebase_FirebaseAndroidShim_logging_h

#include <android/log.h>

#define FIREBASE_ANDROID_LOG(level, tag, ...) __android_log_print(level, tag, __VA_ARGS__)
#define FIREBASE_ANDROID_TAG "company.thebrowser.firebase"

#define LOG_DEBUG(...) FIREBASE_ANDROID_LOG(ANDROID_LOG_DEBUG, FIREBASE_ANDROID_TAG, __VA_ARGS__)
#define LOG_VERBOSE(...) FIREBASE_ANDROID_LOG(ANDROID_LOG_VERBOSE, FIREBASE_ANDROID_TAG, __VA_ARGS__)
#define LOG_INFO(...) FIREBASE_ANDROID_LOG(ANDROID_LOG_INFO, FIREBASE_ANDROID_TAG, __VA_ARGS__)
#define LOG_WARN(...) FIREBASE_ANDROID_LOG(ANDROID_LOG_WARN, FIREBASE_ANDROID_TAG, __VA_ARGS__)
#define LOG_ERROR(...) FIREBASE_ANDROID_LOG(ANDROID_LOG_ERROR, FIREBASE_ANDROID_TAG, __VA_ARGS__)

#endif

0 comments on commit 283174a

Please sign in to comment.