android_logcat/
android_log.rs1use std::{
2 ffi::CString,
3 sync::{
4 atomic::{AtomicBool, Ordering},
5 OnceLock,
6 },
7};
8
9use crate::sys::{LogPriority, __android_log_print, __android_log_write};
10
11static DEFAULT_TAG: &str = "RustLog";
13
14static GLOBAL_LOG_TAG: OnceLock<String> = OnceLock::new();
16
17static GLOBAL_LOG_ENABLED: AtomicBool = AtomicBool::new(true);
19
20pub struct Log;
22
23impl Log {
24 pub fn print(prio: LogPriority, tag: &str, msg: &str) {
26 if !Self::is_enabled() {
27 return;
28 }
29
30 unsafe {
31 __android_log_print(
32 prio as i32,
33 CString::new(tag).unwrap().as_ptr(),
34 CString::new("%s").unwrap().as_ptr(),
35 CString::new(msg).unwrap().as_ptr(),
36 );
37 }
38 }
39
40 pub fn write<T>(prio: LogPriority, tag: &str, msg: &str) {
42 if !Self::is_enabled() {
43 return;
44 }
45
46 unsafe {
47 __android_log_write(
48 prio as i32,
49 CString::new(tag).unwrap().as_ptr(),
50 CString::new(msg).unwrap().as_ptr(),
51 );
52 }
53 }
54
55 pub fn verbose<T>(tag: T, msg: T)
60 where
61 T: AsRef<str>,
62 {
63 Self::print(LogPriority::VERBOSE, tag.as_ref(), msg.as_ref());
64 }
65
66 pub fn debug<T>(tag: T, msg: T)
71 where
72 T: AsRef<str>,
73 {
74 Self::print(LogPriority::DEBUG, tag.as_ref(), msg.as_ref());
75 }
76
77 pub fn info<T>(tag: T, msg: T)
82 where
83 T: AsRef<str>,
84 {
85 Self::print(LogPriority::INFO, tag.as_ref(), msg.as_ref());
86 }
87
88 pub fn warn<T>(tag: T, msg: T)
93 where
94 T: AsRef<str>,
95 {
96 Self::print(LogPriority::WARN, tag.as_ref(), msg.as_ref());
97 }
98
99 pub fn error<T>(tag: T, msg: T)
104 where
105 T: AsRef<str>,
106 {
107 Self::print(LogPriority::ERROR, tag.as_ref(), msg.as_ref());
108 }
109
110 pub fn v<T>(msg: T)
115 where
116 T: AsRef<str>,
117 {
118 if let Some(tag) = GLOBAL_LOG_TAG.get() {
119 Self::verbose(tag.as_ref(), msg.as_ref());
120 } else {
121 Self::verbose(DEFAULT_TAG, msg.as_ref());
122 }
123 }
124
125 pub fn d<T>(msg: T)
130 where
131 T: AsRef<str>,
132 {
133 if let Some(tag) = GLOBAL_LOG_TAG.get() {
134 Self::debug(tag.as_ref(), msg.as_ref());
135 } else {
136 Self::debug(DEFAULT_TAG, msg.as_ref());
137 }
138 }
139
140 pub fn i<T>(msg: T)
145 where
146 T: AsRef<str>,
147 {
148 if let Some(tag) = GLOBAL_LOG_TAG.get() {
149 Self::info(tag.as_ref(), msg.as_ref());
150 } else {
151 Self::info(DEFAULT_TAG, msg.as_ref());
152 }
153 }
154
155 pub fn w<T>(msg: T)
160 where
161 T: AsRef<str>,
162 {
163 if let Some(tag) = GLOBAL_LOG_TAG.get() {
164 Self::warn(tag.as_ref(), msg.as_ref());
165 } else {
166 Self::warn(DEFAULT_TAG, msg.as_ref());
167 }
168 }
169
170 pub fn e<T>(msg: T)
175 where
176 T: AsRef<str>,
177 {
178 if let Some(tag) = GLOBAL_LOG_TAG.get() {
179 Self::error(tag.as_ref(), msg.as_ref());
180 } else {
181 Self::error(DEFAULT_TAG, msg.as_ref());
182 }
183 }
184
185 pub fn init(tag: &str, mixinlog: bool) {
190 let _tag = GLOBAL_LOG_TAG.get_or_init(|| tag.to_string());
191 let _enable = GLOBAL_LOG_ENABLED.store(true, Ordering::Relaxed);
192
193 if mixinlog {
194 log::set_max_level(log::LevelFilter::max());
195 log::set_logger(&Self).unwrap();
196 }
197 }
198
199 pub fn tag() -> &'static str {
201 if let Some(tag) = GLOBAL_LOG_TAG.get() {
202 tag.as_ref()
203 } else {
204 DEFAULT_TAG
205 }
206 }
207
208 pub fn enabled(enabled: bool) {
212 GLOBAL_LOG_ENABLED.store(enabled, Ordering::Relaxed);
213 }
214
215 pub fn is_enabled() -> bool {
217 GLOBAL_LOG_ENABLED.load(Ordering::Relaxed)
218 }
219}