Android Jni添加打印(C++打印)

Android Jni添加打印(C++打印)

文章目錄

  • Android Jni添加打印(C++打印)
    • 一、前言
    • 二、添加日志實現
      • 1、在某個類上面定義類型和方法
      • 2、把日志方法定義在.h文件中
      • 定義 myLog.h
      • 3、引用打印頭文件的示例代碼
        • (1) MainActivity.java 代碼
        • (2) 另外一個cpp代碼類和頭文件
        • (3)jni native-lib.cpp代碼類
        • (4)打印內容
    • 三、其他
      • 1、打印各種類型和示例
        • (1)整數類型:
        • (2)浮點數類型:
        • (3)字符類型:
        • (4)字符串類型:
        • (5)布爾類型:
      • 2、日志打印不出情況
      • 3、__android_log_write 和 __android_log_print 區別?
        • (1)參數形式:
        • (2)使用方式:

一、前言

Android Jni中添加日志打印其實就是C/C++日志打印

Android環境的C/C++代碼打印,可以添加相關頭文件后,調用打印方法

跟Android打印類似,也是有打印級別,I,D,W,E

二、添加日志實現

1、在某個類上面定義類型和方法

網上一般做法,在某一個cpp類的上面寫如下代碼:

#include <android/log.h> //添加頭文件
#define LOG_TAG "TstCPlus" //定義TAG
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

在方法中使用即可:

 LOGI("test");int result = 100;LOGI("test result = %d", result);

其他級別打印也是同理使用。

上面的方法把定義都寫在打印的定義都寫在一個類里面了,如果多個類使用打印就不方便了,

如果要多個類都能見到調用到就可以定義在.h頭文件里面,其他類加入定義一下頭文件調用到了。

2、把日志方法定義在.h文件中

定義 myLog.h

#include <android/log.h>#define LOG_TAG "TestCPlus"
#define ANDROID_PLATFORM#ifdef ANDROID_PLATFORM#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))#else#define LOGD(fmt, ...) printf(fmt"\n", ##__VA_ARGS__)#define LOGI(fmt, ...) printf(fmt"\n", ##__VA_ARGS__)#define LOGW(fmt, ...) printf(fmt"\n", ##__VA_ARGS__)#define LOGE(fmt, ...) printf(fmt"\n", ##__VA_ARGS__)
#endif
#endif

上面代碼添加了是否Android平臺的判斷,如果覺得沒必要可以直接去掉。

DEBUG的值也可以設置成false,0就是false。

在具體cpp文件中,可以重新定義TAG標簽

#include "myLog.h"
#define LOG_TAG "TAG_NAME"

3、引用打印頭文件的示例代碼

(1) MainActivity.java 代碼
    String TAG = "MainActivity Java";static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Log.i(TAG, "onCreate");TextView tv = findViewById(R.id.sample_text);tv.setText(stringFromJNI());}public native String stringFromJNI();
(2) 另外一個cpp代碼類和頭文件
//TestCPlus.cpp 代碼
#include "TestCPlus.h"
#include "Androidlog.h"int TestCPlus::add(int parameter1, int parameter2) {int result = parameter1 + parameter2;LOGI("MainActivity jni c++ result = %d", result);//添加打印,但是沒有定義TAGreturn result;
}//TestCPlus.h頭文件代碼
class TestCPlus {
//定義變量和方法
private:int number;
public:int add(int parameter1,int parameter2); //定義方法
};
(3)jni native-lib.cpp代碼類
#include <jni.h>
#include <string>#include "Androidlog.h"
#include "TestCPlus.h"
#define LOG_TAG "native-lib.cpp" //重新定義TAGextern "C" JNIEXPORT jstring JNICALL
Java_com_demo_jnilog_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {std::string hello = "Hello from C/C++";LOGD("MainActivity jni c++ ");int num= 100;LOGI("MainActivity jni c++ ,num = %d", num);TestCPlus *testCPlus;int result =  testCPlus->add(2, 50);LOGI("MainActivity jni c++ ,result = %d", result);return env->NewStringUTF(hello.c_str());
}
(4)打印內容
2024-02-29 15:07:40.706  I/MainActivity?Java: onCreate
2024-02-29 15:07:40.706  D/native-lib.cpp: MainActivity jni c++ 
2024-02-29 15:07:40.706  I/native-lib.cpp: MainActivity jni c++ ,num = 100
2024-02-29 15:07:40.706  I/TestLog: MainActivity jni c++ result = 52
2024-02-29 15:07:40.706  I/native-lib.cpp: MainActivity jni c++ ,result = 52

可以看到未定義 LOG_TAG 的 TestCPlus.cpp文件打印的就是使用原本的TAG,定義了的,就是用新的TAG

三、其他

1、打印各種類型和示例

在C++中,可以使用不同的格式化輸出來打印各種數據類型。下面是一些常見的數據類型及其對應的打印格式:

(1)整數類型:
 int: 使用"%d"格式打印,例如:`int num = 10; printf("%d", num);`long: 使用"%ld"格式打印,例如:`long num = 1000000; printf("%ld", num);`short: 使用"%hd"格式打印,例如:`short num = 5; printf("%hd", num);`
(2)浮點數類型:
 float: 使用"%f"格式打印,例如:`float num = 3.14; printf("%f", num);`double: 使用"%lf"格式打印,例如:`double num = 2.71828; printf("%lf", num);`
(3)字符類型:
char: 使用"%c"格式打印,
例如:`char ch = 'A'; printf("%c", ch);`
(4)字符串類型:
char數組或指針:使用"%s"格式打印,
例如:`char str[] = "Hello"; printf("%s", str);`
參數的里面的jstring打印示例:
Java_com_example_example_NativeClass_printString(JNIEnv* env, jobject obj, jstring str) {const char* nativeString = env->GetStringUTFChars(str, NULL);if (nativeString != NULL) {LOGI("String from Java: %s\n", nativeString);env->ReleaseStringUTFChars(str, nativeString);//或者:std::string hello = "Hello from C++";LOGI("stringFromJNI hello = %s", hello.c_str());}
}
(5)布爾類型:
bool: 使用"%d"或"%s"格式打印,分別將true打印為1,false打印為0或者"true"和"false",
例如:`bool flag = true; printf("%d", flag);`

上面的打印printf在Android平臺打印都替換成 LOGI 即可。

以上是一些常見數據類型的打印方式,你可以根據具體需要選擇合適的格式化輸出來打印不同的數據類型。

2、日志打印不出情況

如果在JNI的CPP文件中日志打印不出來,可能有以下幾個原因:

1. 缺少日志打印庫:在CPP文件中,需要包含頭文件 ``,并且使用 Android NDK 提供的日志庫函數來進行打印。
請確保你的CPP文件中正確包含了該頭文件。2. 編譯配置問題:在編譯時,需要將日志庫鏈接到你的JNI庫中。
在 Android.mk 或 CMakeLists.txt 文件中,確保添加了正確的鏈接庫配置。
示例:`LOCAL_LDLIBS += -llog`。3. 日志級別設置問題:檢查你的日志打印語句中的日志級別參數,
例如 `__android_log_print(ANDROID_LOG_DEBUG, "TAG", "Log message");`。
確保日志級別設置正確,以便在運行時打印出來。4. 運行時過濾問題:在 Android Logcat 中,可能需要設置正確的過濾條件,以確保你的日志能夠顯示出來。
請確保你在 Logcat 中設置了正確的標簽過濾條件,以及你期望的日志級別過濾條件。

如果以上步驟都確認無誤,但仍然無法打印日志,可以檢查一下日志打印語句是否被執行到,或者嘗試在其他位置打印日志,以確定是否是特定位置的問題。另外,確保你的應用具有適當的權限來寫入日志。

如果問題仍然存在,建議提供更多的代碼細節或錯誤信息,以便更好地理解問題并提供幫助。

3、__android_log_write 和 __android_log_print 區別?

兩個方法都是log.h里面定義的方法,目前看,兩種方式都是可以打印,但是區別有什么呢

在Android的JNI開發中,__android_log_write__android_log_print都是用于在native代碼中打印日志的函數。它們的區別如下:

(1)參數形式:
 `__android_log_write`函數的參數形式為:`__android_log_write(int prio, const char *tag, const char *msg)`。其中,`prio`表示日志的優先級,`tag`表示日志的標簽,`msg`表示日志的內容。`__android_log_print`函數的參數形式為:`__android_log_print(int prio, const char *tag, const char *fmt, ...)`。其中,`prio`和`tag`的含義與`__android_log_write`相同,而`fmt`是一個格式化字符串,后面可以是可變參數。

第一種方式比較接近Java代碼的打印,msg字符串里面要包含所有打印的信息。

第二種就是c++的打印方式,可以輸入多個參數。在cpp文件中一般都是使用第二種。

(2)使用方式:
 `__android_log_write`函數需要將日志內容作為字符串傳入,可以直接調用該函數輸出,例如:`__android_log_write(ANDROID_LOG_DEBUG, "TAG", "Log message");``__android_log_print`函數使用類似于`printf`函數的格式化字符串,可以傳入多個參數,例如:`__android_log_print(ANDROID_LOG_DEBUG, "TAG", "Log message: %d", value);`

總的來說,__android_log_write函數更直接,適合簡單的日志輸出;

__android_log_print函數更靈活,可以使用格式化字符串來輸出帶有變量值的日志信息。

實際使用中,可以根據需要選擇合適的函數來打印日志。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717674.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717674.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717674.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【詳識JAVA語言】面向對象程序三大特性之三:多態

多態 多態的概念 多態的概念&#xff1a;通俗來說&#xff0c;就是多種形態&#xff0c;具體點就是去完成某個行為&#xff0c;當不同的對象去完成時會產生出不同的狀態。 多態實現條件 在java中要實現多態&#xff0c;必須要滿足如下幾個條件&#xff0c;缺一不可&#xf…

循環隊列與循環雙端隊列

文章目錄 前言循環隊列循環雙端隊列 前言 1、學習循環隊列和循環雙端隊列能加深我們對隊列的理解&#xff0c;提高我們的編程能力。 2、本文循環隊列使用的是數組&#xff0c;循環雙端隊列用的是雙向鏈表 3、題目連接&#xff1a;設計循環隊列 &#xff0c;設計循環雙端隊列。 …

【機器學習】有監督學習算法之:支持向量機

支持向量機 1、引言2、決策樹2.1 定義2.2 原理2.3 實現方式2.4 算法公式2.5 代碼示例 3、總結 1、引言 小屌絲&#xff1a;魚哥&#xff0c;泡澡啊。 小魚&#xff1a;不去 小屌絲&#xff1a;… 此話當真&#xff1f; 小魚&#xff1a;此話不假 小屌絲&#xff1a;到底去還是…

Linux 網絡接口的混雜模式(Promiscuous mode)認知

寫在前面 博文內容為 混雜模式的簡單認知理解不足小伙伴幫忙指正 認定一件事&#xff0c;即使拿十分力氣都無法完成&#xff0c;也要拿出十二分力氣去努力。 —《劍來》 網絡接口的混雜模式 混雜模式(Promiscuous mode)&#xff0c;簡稱 Promisc mode&#xff0c;俗稱監聽模式…

什么是支持向量機(Support vector machine)和其原理

作為機器學習的基礎算法&#xff0c;SVM被反復提及&#xff0c;西瓜書、wiki都能查到詳細介紹&#xff0c;但是總是覺得還差那么點&#xff0c;于是決定自己總結一下。 一、什么是SVM&#xff1f; 1、解決什么問題&#xff1f; SVM&#xff0c;最原始的版本是用于最簡單的線…

藍橋杯備賽第五篇(動態規劃)

1.數位dp public class Main {static long[] limit;static int length;static long[][] dp;public static long dfs(int pos, int pre, boolean flag, boolean lead) {if (pos length) return 1;if (!flag && !lead && dp[pos][pre] ! -1) return dp[pos][pr…

總結 HashTable, HashMap, ConcurrentHashMap 之間的區別

1.多線程環境使用哈希表 HashMap 不行,線程不安全 更靠譜的,Hashtable,在關鍵方法上加了synchronized 后來標準庫又引入了一個更好的解決方案;ConcurrentHashMap 2.HashMap 首先HashMap本身線程不安全其次HashMap的key值可以為空&#xff08;當key為空時&#xff0c;哈希會…

【Java數據結構】——五道算法題讓你靈活運用Map和Set

目錄 一.只出現一次的數字 二.寶石與石頭 三.舊鍵盤 四.給定一個數組&#xff0c;統計每個元素出現的次數 五.前K個高頻單詞 一.只出現一次的數字 136. 只出現一次的數字 - 力扣&#xff08;LeetCode&#xff09; 算法原理&#xff1a;我們將nums中每個元素都存入到set中…

C/C++嵌入式開發環境搭建,Qt交叉編譯,cmake交叉編譯,clion/vscode遠程開發

目錄 交叉編譯簡介cmake 交叉編譯clion 交叉編譯vscode 遠程嵌入式開發Qt交叉編譯1.安裝交叉編譯工具2.交叉編譯qt庫3.將交叉編譯的Qt庫復制到板子上4.安裝和配置 Qt Creator&#xff0c;支持交叉編譯5.QT嵌入式開發6.QT嵌入式開發報錯解決QIconvCodec::convertToUnicode: usin…

ASUS華碩天選5筆記本電腦FX607JV原裝出廠Win11系統下載

ASUS TUF Gaming F16 FX607JV天選五原廠Windows11系統 適用型號&#xff1a; FX607JU、FX607JI、FX607JV、 FX607JIR、FX607JVR、FX607JUR 下載鏈接&#xff1a;https://pan.baidu.com/s/1l963wqxT0q1Idr98ACzynQ?pwd0d46 提取碼&#xff1a;0d46 原廠系統自帶所有驅動、…

TypeScript中 “ <> “ 語法 和 “ : “ 怎么使用

在 TypeScript 中&#xff0c;尖括號語法(<Type>)和as關鍵字(value as Type)都是用于類型斷言&#xff0c;而冒號(:)用于類型注解。這三種語法在不同的場景下使用&#xff1a; 尖括號語法和as關鍵字&#xff1a; 尖括號語法(<Type>value)&#xff1a; 這種語法在…

[LeetBook]【學習日記】鏈表反轉

來源于「Krahets」的《圖解算法數據結構》 https://leetcode.cn/leetbook/detail/illustration-of-algorithm/ 鏈表反轉的遞歸要點 遞歸終止條件為當前節點為空&#xff0c;表明遍歷到了鏈表尾部遞歸函數傳入參數為當前節點的下一個節點按照是否重新開辟存儲空間分類下面只寫…

python自動化學習--3.8python操作EXCEL文件python日志收集處理

1、Excel文件處理 安裝 openpxl 第三方庫 openpxl 模塊三大組件: 1、工作簿 &#xff08;包含多個sheet工作表&#xff09; 2、工作表 &#xff08;某個數據包含在某個工作表&#xff09; 3、單元格 1、創建excel工作簿 import openpyxl"""Excel表格的創建…

【簡說八股】Spring事務失效可能是哪些原因?

Spring事務介紹 Spring事務是指在Spring框架中對數據庫操作進行管理的一種機制&#xff0c;它確保一組數據庫操作要么完全執行成功&#xff08;提交&#xff09;&#xff0c;要么完全不執行&#xff08;回滾&#xff09;&#xff0c;從而保持數據一致性和完整性。 Spring框架…

GotoXy控制臺光標的位置更新

光標控制解釋 控制臺的光標更新方法, 用于控制數據輸出位置 void gotoXY(int x, int y)//新函數&#xff1a;更新光標 {COORD c;c.X x;c.Y y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c); }代碼解釋 這段代碼定義了一個名為 gotoXY 的函數&#xff0c;…

設計模式-裝飾者模式應用實踐

裝飾者模式&#xff08;Decorator Pattern&#xff09;是一種結構型設計模式&#xff0c;它允許動態地向一個現有的對象添加新的功能&#xff0c;同時不改變其結構。這種模式通過創建一個裝飾類來包裝原有的類&#xff0c;提供額外的行為。 下面是一個使用 Java 實現裝飾者模式…

【Spring Boot】實現全局異常處理

1.定義基礎異常接口類 /*** description: 服務接口類* author: MrVK* date: 2021/4/19 21:39*/ public interface BaseErrorInfoInterface {/*** 錯誤碼* return*/String getResultCode();/*** 錯誤描述* return*/String getResultMsg(); } 2.定義錯誤處理枚舉類 /*** desc…

小伙伴詢問AI該怎么學習?本人的一點總結,以思維導圖呈現

如有需要思維導圖的在后臺請留郵箱&#xff0c;相關知識結構目錄 部分導圖

nn.Linear() 使用提醒

原本以為它是和nn.Conv2d()一樣&#xff0c;就看第二個維度的數值&#xff0c;今天才知道&#xff0c;它是只看最后一個維度的數值&#xff01;&#xff01;&#xff01; 例子1 Descripttion: Result: Author: Philo Date: 2024-02-27 14:33:50 LastEditors: Philo LastEditT…

git使用merge命令把dev分支的mian.js文件和src下面的vuex文件夾以及config文件夾單獨合并到master分支上

使用 git merge 命令來單獨合并特定文件或文件夾到另一個分支通常不是最直接的方法&#xff0c;因為 merge 命令是用來合并兩個分支的所有更改的。然而&#xff0c;你可以通過 git cherry-pick 命令或者通過創建臨時補丁&#xff08;patch&#xff09;來實現這一點。 下面是一個…