diff --git a/src/main/jni-cpp-src/common/sources.txt b/src/main/jni-cpp-src/common/sources.txt
index e08a43f..da389fd 100644
--- a/src/main/jni-cpp-src/common/sources.txt
+++ b/src/main/jni-cpp-src/common/sources.txt
@@ -1,3 +1,2 @@
../src/main/jni-java-src/it/tdlight/jni/TdApi.java
../src/main/jni-java-src/it/tdlight/tdnative/NativeClient.java
-../src/main/jni-java-src/it/tdlight/tdnative/NativeLog.java
diff --git a/src/main/jni-cpp-src/tdlib/td_jni.cpp b/src/main/jni-cpp-src/tdlib/td_jni.cpp
index 371cb06..7608145 100644
--- a/src/main/jni-cpp-src/tdlib/td_jni.cpp
+++ b/src/main/jni-cpp-src/tdlib/td_jni.cpp
@@ -1,12 +1,10 @@
-
//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include
-#include |
#include |
#include |
@@ -88,23 +86,52 @@ static jstring Function_toString(JNIEnv *env, jobject object) {
static constexpr jint JAVA_VERSION = JNI_VERSION_1_6;
static JavaVM *java_vm;
-static jclass log_class;
+static jobject log_message_handler;
-static void on_log_message(int verbosity_level, const char *error_message) {
- if (verbosity_level != 0) {
- return;
- }
+static void on_log_message(int verbosity_level, const char *log_message) {
auto env = td::jni::get_jni_env(java_vm, JAVA_VERSION);
if (env == nullptr) {
return;
}
- jmethodID on_fatal_error_method = env->GetStaticMethodID(log_class, "onFatalError", "(Ljava/lang/String;)V");
- if (on_fatal_error_method) {
- jstring error_str = td::jni::to_jstring(env.get(), error_message);
- env->CallStaticVoidMethod(log_class, on_fatal_error_method, error_str);
- if (error_str) {
- env->DeleteLocalRef(error_str);
+
+ jobject handler = env->NewLocalRef(log_message_handler);
+ if (!handler) {
+ return;
+ }
+
+ jclass handler_class = env->GetObjectClass(handler);
+ if (handler_class) {
+ jmethodID on_log_message_method = env->GetMethodID(handler_class, "onLogMessage", "(ILjava/lang/String;)V");
+ if (on_log_message_method) {
+ jstring log_message_str = td::jni::to_jstring(env.get(), log_message);
+ if (log_message_str) {
+ env->CallVoidMethod(handler, on_log_message_method, static_cast(verbosity_level), log_message_str);
+ env->DeleteLocalRef((jobject)log_message_str);
+ }
}
+ env->DeleteLocalRef((jobject)handler_class);
+ }
+
+ env->DeleteLocalRef(handler);
+}
+
+static void Client_nativeClientSetLogMessageHandler(JNIEnv *env, jclass clazz, jint max_verbosity_level,
+ jobject new_log_message_handler) {
+ if (log_message_handler) {
+ td::ClientManager::set_log_message_callback(0, nullptr);
+ jobject old_log_message_handler = log_message_handler;
+ log_message_handler = jobject();
+ env->DeleteGlobalRef(old_log_message_handler);
+ }
+
+ if (new_log_message_handler) {
+ log_message_handler = env->NewGlobalRef(new_log_message_handler);
+ if (!log_message_handler) {
+ // out of memory
+ return;
+ }
+
+ td::ClientManager::set_log_message_callback(static_cast(max_verbosity_level), on_log_message);
}
}
@@ -122,7 +149,6 @@ static jint register_native(JavaVM *vm) {
};
auto client_class = td::jni::get_jclass(env, PACKAGE_NAME "/NativeClient");
- log_class = td::jni::get_jclass(env, PACKAGE_NAME "/NativeLog");
auto object_class = td::jni::get_jclass(env, API_PACKAGE_NAME "/TdApi$Object");
auto function_class = td::jni::get_jclass(env, API_PACKAGE_NAME "/TdApi$Function");
@@ -132,6 +158,8 @@ static jint register_native(JavaVM *vm) {
register_method(client_class, "nativeClientSend", "(IJ" TD_FUNCTION ")V", Client_nativeClientSend);
register_method(client_class, "nativeClientReceive", "([I[J[" TD_OBJECT "D)I", Client_nativeClientReceive);
register_method(client_class, "nativeClientExecute", "(" TD_FUNCTION ")" TD_OBJECT, Client_nativeClientExecute);
+ register_method(client_class, "nativeClientSetLogMessageHandler", "(IL" PACKAGE_NAME "/NativeClient$LogMessageHandler;)V",
+ Client_nativeClientSetLogMessageHandler);
register_method(object_class, "toString", "()Ljava/lang/String;", Object_toString);
@@ -142,7 +170,6 @@ static jint register_native(JavaVM *vm) {
td::jni::init_vars(env, API_PACKAGE_NAME);
td::td_api::Object::init_jni_vars(env, API_PACKAGE_NAME);
td::td_api::Function::init_jni_vars(env, API_PACKAGE_NAME);
- td::ClientManager::set_log_message_callback(0, on_log_message);
return JAVA_VERSION;
}
diff --git a/src/main/jni-cpp-src/tdlight/td_jni.cpp b/src/main/jni-cpp-src/tdlight/td_jni.cpp
index e34c8f9..7608145 100644
--- a/src/main/jni-cpp-src/tdlight/td_jni.cpp
+++ b/src/main/jni-cpp-src/tdlight/td_jni.cpp
@@ -1,11 +1,10 @@
//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include
-#include |
#include |
#include |
@@ -87,23 +86,52 @@ static jstring Function_toString(JNIEnv *env, jobject object) {
static constexpr jint JAVA_VERSION = JNI_VERSION_1_6;
static JavaVM *java_vm;
-static jclass log_class;
+static jobject log_message_handler;
-static void on_log_message(int verbosity_level, const char *error_message) {
- if (verbosity_level != 0) {
- return;
- }
+static void on_log_message(int verbosity_level, const char *log_message) {
auto env = td::jni::get_jni_env(java_vm, JAVA_VERSION);
if (env == nullptr) {
return;
}
- jmethodID on_fatal_error_method = env->GetStaticMethodID(log_class, "onFatalError", "(Ljava/lang/String;)V");
- if (on_fatal_error_method) {
- jstring error_str = td::jni::to_jstring(env.get(), error_message);
- env->CallStaticVoidMethod(log_class, on_fatal_error_method, error_str);
- if (error_str) {
- env->DeleteLocalRef(error_str);
+
+ jobject handler = env->NewLocalRef(log_message_handler);
+ if (!handler) {
+ return;
+ }
+
+ jclass handler_class = env->GetObjectClass(handler);
+ if (handler_class) {
+ jmethodID on_log_message_method = env->GetMethodID(handler_class, "onLogMessage", "(ILjava/lang/String;)V");
+ if (on_log_message_method) {
+ jstring log_message_str = td::jni::to_jstring(env.get(), log_message);
+ if (log_message_str) {
+ env->CallVoidMethod(handler, on_log_message_method, static_cast(verbosity_level), log_message_str);
+ env->DeleteLocalRef((jobject)log_message_str);
+ }
}
+ env->DeleteLocalRef((jobject)handler_class);
+ }
+
+ env->DeleteLocalRef(handler);
+}
+
+static void Client_nativeClientSetLogMessageHandler(JNIEnv *env, jclass clazz, jint max_verbosity_level,
+ jobject new_log_message_handler) {
+ if (log_message_handler) {
+ td::ClientManager::set_log_message_callback(0, nullptr);
+ jobject old_log_message_handler = log_message_handler;
+ log_message_handler = jobject();
+ env->DeleteGlobalRef(old_log_message_handler);
+ }
+
+ if (new_log_message_handler) {
+ log_message_handler = env->NewGlobalRef(new_log_message_handler);
+ if (!log_message_handler) {
+ // out of memory
+ return;
+ }
+
+ td::ClientManager::set_log_message_callback(static_cast(max_verbosity_level), on_log_message);
}
}
@@ -121,7 +149,6 @@ static jint register_native(JavaVM *vm) {
};
auto client_class = td::jni::get_jclass(env, PACKAGE_NAME "/NativeClient");
- log_class = td::jni::get_jclass(env, PACKAGE_NAME "/NativeLog");
auto object_class = td::jni::get_jclass(env, API_PACKAGE_NAME "/TdApi$Object");
auto function_class = td::jni::get_jclass(env, API_PACKAGE_NAME "/TdApi$Function");
@@ -131,6 +158,8 @@ static jint register_native(JavaVM *vm) {
register_method(client_class, "nativeClientSend", "(IJ" TD_FUNCTION ")V", Client_nativeClientSend);
register_method(client_class, "nativeClientReceive", "([I[J[" TD_OBJECT "D)I", Client_nativeClientReceive);
register_method(client_class, "nativeClientExecute", "(" TD_FUNCTION ")" TD_OBJECT, Client_nativeClientExecute);
+ register_method(client_class, "nativeClientSetLogMessageHandler", "(IL" PACKAGE_NAME "/NativeClient$LogMessageHandler;)V",
+ Client_nativeClientSetLogMessageHandler);
register_method(object_class, "toString", "()Ljava/lang/String;", Object_toString);
@@ -141,7 +170,6 @@ static jint register_native(JavaVM *vm) {
td::jni::init_vars(env, API_PACKAGE_NAME);
td::td_api::Object::init_jni_vars(env, API_PACKAGE_NAME);
td::td_api::Function::init_jni_vars(env, API_PACKAGE_NAME);
- td::ClientManager::set_log_message_callback(0, on_log_message);
return JAVA_VERSION;
}
diff --git a/src/main/jni-java-src/it/tdlight/tdnative/NativeClient.java b/src/main/jni-java-src/it/tdlight/tdnative/NativeClient.java
index beffb6c..24f830c 100644
--- a/src/main/jni-java-src/it/tdlight/tdnative/NativeClient.java
+++ b/src/main/jni-java-src/it/tdlight/tdnative/NativeClient.java
@@ -15,4 +15,21 @@ public class NativeClient {
double timeout);
protected static native TdApi.Object nativeClientExecute(TdApi.Function function);
+
+ private static native void nativeClientSetLogMessageHandler(int maxVerbosityLevel, LogMessageHandler logMessageHandler);
+
+ /**
+ * Interface for handler of messages that are added to the internal TDLib log.
+ */
+ public interface LogMessageHandler {
+ /**
+ * Callback called on messages that are added to the internal TDLib log.
+ *
+ * @param verbosityLevel Log verbosity level with which the message was added from -1 up to 1024.
+ * If 0, then TDLib will crash as soon as the callback returns.
+ * None of the TDLib methods can be called from the callback.
+ * @param message The message added to the internal TDLib log.
+ */
+ void onLogMessage(int verbosityLevel, String message);
+ }
}
diff --git a/src/main/jni-java-src/it/tdlight/tdnative/NativeLog.java b/src/main/jni-java-src/it/tdlight/tdnative/NativeLog.java
deleted file mode 100644
index 78acdfe..0000000
--- a/src/main/jni-java-src/it/tdlight/tdnative/NativeLog.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package it.tdlight.tdnative;
-
-import it.tdlight.jni.TdApi;
-import java.util.function.Consumer;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Class used for managing internal TDLib logging.
- */
-public class NativeLog {
-
- private static final Consumer defaultFatalErrorCallback = NativeLog::printFatalError;
- private static final AtomicReference> fatalErrorCallback
- = new AtomicReference<>(defaultFatalErrorCallback);
-
- /**
- * This function is called from the JNI when a fatal error happens to provide a better error message.
- * The function does not return.
- *
- * @param errorMessage Error message.
- */
- private static void onFatalError(String errorMessage) {
- new Thread(() -> NativeLog.fatalErrorCallback.get().accept(errorMessage)).start();
- }
-
- /**
- * Sets the callback that will be called when a fatal error happens.
- * None of the TDLib methods can be called from the callback.
- * TDLib will crash as soon as the callback returns.
- * By default the callback set to print in stderr.
- * @param fatalErrorCallback Callback that will be called when a fatal error happens.
- * Pass null to restore default callback.
- */
- public static void setFatalErrorCallback(Consumer fatalErrorCallback) {
- if (fatalErrorCallback == null) {
- fatalErrorCallback = defaultFatalErrorCallback;
- }
- NativeLog.fatalErrorCallback.set(fatalErrorCallback);
- }
-
- private static void printFatalError(String errorMessage) {
- System.err.println("TDLib fatal error: " + errorMessage);
- }
-}
| |