File indexing completed on 2025-12-17 10:29:01
0001
0002
0003
0004 #pragma once
0005
0006 #ifdef __ANDROID__
0007
0008 #include <spdlog/details/fmt_helper.h>
0009 #include <spdlog/details/null_mutex.h>
0010 #include <spdlog/details/os.h>
0011 #include <spdlog/details/synchronous_factory.h>
0012 #include <spdlog/sinks/base_sink.h>
0013
0014 #include <android/log.h>
0015 #include <chrono>
0016 #include <mutex>
0017 #include <string>
0018 #include <thread>
0019 #include <type_traits>
0020
0021 #if !defined(SPDLOG_ANDROID_RETRIES)
0022 #define SPDLOG_ANDROID_RETRIES 2
0023 #endif
0024
0025 namespace spdlog {
0026 namespace sinks {
0027
0028
0029
0030
0031
0032
0033 template <typename Mutex, int BufferID = log_id::LOG_ID_MAIN>
0034 class android_sink final : public base_sink<Mutex> {
0035 public:
0036 explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false)
0037 : tag_(std::move(tag)),
0038 use_raw_msg_(use_raw_msg) {}
0039
0040 protected:
0041 void sink_it_(const details::log_msg &msg) override {
0042 const android_LogPriority priority = convert_to_android_(msg.level);
0043 memory_buf_t formatted;
0044 if (use_raw_msg_) {
0045 details::fmt_helper::append_string_view(msg.payload, formatted);
0046 } else {
0047 base_sink<Mutex>::formatter_->format(msg, formatted);
0048 }
0049 formatted.push_back('\0');
0050 const char *msg_output = formatted.data();
0051
0052
0053 int ret = android_log(priority, tag_.c_str(), msg_output);
0054 if (ret == -EPERM) {
0055 return;
0056 }
0057 int retry_count = 0;
0058 while ((ret == -11 ) && (retry_count < SPDLOG_ANDROID_RETRIES)) {
0059 details::os::sleep_for_millis(5);
0060 ret = android_log(priority, tag_.c_str(), msg_output);
0061 retry_count++;
0062 }
0063
0064 if (ret < 0) {
0065 throw_spdlog_ex("logging to Android failed", ret);
0066 }
0067 }
0068
0069 void flush_() override {}
0070
0071 private:
0072
0073
0074
0075
0076 template <int ID = BufferID>
0077 typename std::enable_if<ID == static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(
0078 int prio, const char *tag, const char *text) {
0079 return __android_log_write(prio, tag, text);
0080 }
0081
0082 template <int ID = BufferID>
0083 typename std::enable_if<ID != static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(
0084 int prio, const char *tag, const char *text) {
0085 return __android_log_buf_write(ID, prio, tag, text);
0086 }
0087
0088 static android_LogPriority convert_to_android_(spdlog::level::level_enum level) {
0089 switch (level) {
0090 case spdlog::level::trace:
0091 return ANDROID_LOG_VERBOSE;
0092 case spdlog::level::debug:
0093 return ANDROID_LOG_DEBUG;
0094 case spdlog::level::info:
0095 return ANDROID_LOG_INFO;
0096 case spdlog::level::warn:
0097 return ANDROID_LOG_WARN;
0098 case spdlog::level::err:
0099 return ANDROID_LOG_ERROR;
0100 case spdlog::level::critical:
0101 return ANDROID_LOG_FATAL;
0102 default:
0103 return ANDROID_LOG_DEFAULT;
0104 }
0105 }
0106
0107 std::string tag_;
0108 bool use_raw_msg_;
0109 };
0110
0111 using android_sink_mt = android_sink<std::mutex>;
0112 using android_sink_st = android_sink<details::null_mutex>;
0113
0114 template <int BufferId = log_id::LOG_ID_MAIN>
0115 using android_sink_buf_mt = android_sink<std::mutex, BufferId>;
0116 template <int BufferId = log_id::LOG_ID_MAIN>
0117 using android_sink_buf_st = android_sink<details::null_mutex, BufferId>;
0118
0119 }
0120
0121
0122
0123 template <typename Factory = spdlog::synchronous_factory>
0124 inline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name,
0125 const std::string &tag = "spdlog") {
0126 return Factory::template create<sinks::android_sink_mt>(logger_name, tag);
0127 }
0128
0129 template <typename Factory = spdlog::synchronous_factory>
0130 inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name,
0131 const std::string &tag = "spdlog") {
0132 return Factory::template create<sinks::android_sink_st>(logger_name, tag);
0133 }
0134
0135 }
0136
0137 #endif