Question
Would you please provide an example to implement the following: register an ArkTS log listener in native code so that logs can be reported to ArkTS via a callback when the log API is called in any service on the native side?
Answer
import { hilog } from '@kit.PerformanceAnalysisKit';
export class GlobalThisAdapter {
private constructor() {
}
private static instance: GlobalThisAdapter;
private _logListener: LogsListener = new LogsListener();
public static getInstance(): GlobalThisAdapter {
if (!GlobalThisAdapter.instance) {
GlobalThisAdapter.instance = new GlobalThisAdapter();
}
return GlobalThisAdapter.instance;
}
getLogsListener(): LogsListener | undefined {
return this._logListener;
}
setLogsListener(value: LogsListener): void {
this._logListener = value;
}
}
export class LogsListener implements OnLogsListener {
public constructor() {
}
onLogs(level: LogLevel, message: string): void {
switch (level) {
case LogLevel.DEBUG:
hilog.debug(0x0000, 'debug', 'debug message is %{public}s', message);
break;
case LogLevel.INFO:
hilog.info(0x0000, 'info', 'info message is %{public}s', message);
break;
case LogLevel.WARN:
hilog.warn(0x0000, 'warn', 'warn message is %{public}s', message)
break;
case LogLevel.ERROR:
hilog.error(0x0000, 'error', 'error message is %{public}s', message);
break;
case LogLevel.FATAL:
hilog.fatal(0x0000, 'fatal', 'fatal message is %{public}s', message);
break;
default:
hilog.info(0x0000, 'info', 'info message is %{public}s', message);
}
}
}
enum LogLevel {
DEBUG = 3,
INFO,
WARN,
ERROR,
FATAL
}
export default interface OnLogsListener {
onLogs(level: number, message: string): void;
} #include "napi/native_api.h"
#include <bits/alltypes.h>
#include <cstring>
#include <hilog/log.h>
napi_ref logListenerRef = nullptr;
napi_ref onLogsFuncRef = nullptr;
static napi_value RegisterLogListener(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value globalThisAdapter = nullptr;
napi_get_cb_info(env, info, &argc, &globalThisAdapter, nullptr, nullptr);
napi_value getLogListenerFunc = nullptr;
napi_get_named_property(env, globalThisAdapter, "getLogsListener", &getLogListenerFunc);
napi_value logListener = nullptr;
napi_call_function(env, globalThisAdapter, getLogListenerFunc, 0, nullptr, &logListener);
napi_value onLogsFunc = nullptr;
napi_get_named_property(env, logListener, "onLogs", &onLogsFunc);
napi_create_reference(env, logListener, 1, &logListenerRef);
napi_create_reference(env, onLogsFunc, 1, &onLogsFuncRef);
return nullptr;
} EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},
{"registerLogListener", nullptr, RegisterLogListener, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END import { GlobalThisAdapter } from '../../../ets/interface/Log'
export const add: () => void;
export const registerLogListener: (a: GlobalThisAdapter) => void; onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
let globalThisAdapter: GlobalThisAdapter = GlobalThisAdapter.getInstance();
testNapi.registerLogListener(globalThisAdapter);
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
} static void callOnLogs(napi_env env, LogLevel level, const char *message) {
size_t argc = 2;
napi_value argv[2] = {nullptr};
int32_t tem = level;
napi_create_int32(env, tem, &argv[0]);
napi_create_string_utf8(env, message, strlen(message) + 1, &argv[1]);
napi_value logListener = nullptr;
napi_value onLogsFunc = nullptr;
napi_get_reference_value(env, logListenerRef, &logListener);
napi_get_reference_value(env, onLogsFuncRef, &onLogsFunc);
napi_call_function(env, logListener, onLogsFunc, argc, argv, nullptr);
} static napi_value Add(napi_env env, napi_callback_info info) {
callOnLogs(env, LogLevel::LOG_INFO, "execute native Add function success");
return nullptr;
}