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

9 篇文章 0 订阅

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

一、前言

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");
    }

    @Override
    protected 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);//添加打印,但是没有定义TAG
    return 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" //重新定义TAG

extern "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函数更灵活,可以使用格式化字符串来输出带有变量值的日志信息。

实际使用中,可以根据需要选择合适的函数来打印日志。

  • 28
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值