Android 使用NDK记录日志到本地(c++,NDK)包括jni函数的动态已经静态注册,native与Java相互调用

最近在计算一大批视频的播放时长,于是使用了Android的videoview库。然后Android studio 用的3.0,顺便就用了Android的ndk来操作了一下日志。虽然Java原生也能实现,这里我不知为啥就没用原生的。。。。。。=。=。。。

功能点:

      在Android Java文件中调用c++中的方法,达到文件的新建,日志的记录,日志的追加,日志文件的删除。

 

知识点:

    我想了想这个项目虽然很简单,但是包含内容还是比较完整的,包括c++ 基础 jni函数的两种注册,cmake的节点含义,       native与Java相互调用。

如何使用:

step1:

 在项目中的build文件中的

allprojects节点下面添加
maven { url "https://raw.githubusercontent.com/NDKFile/NDK/master" }

step2:

 在app中的build文件中添加

implementation 'com.ndklog:log_lib:1.0.0'

use :

FileUtils .getInstance.FileWrite("","");

FileUtils .getInstance.FileDelete("");

 

 

 

所有源代码如下:

 

 native_lib.c++   代码:

此文件主要是动态注册了文件操作的函数,以及静态注册一个原生的方法。

#include <jni.h>
#include <string>
#include "fileutil.h"

// 静态注册的 函数
extern "C" JNIEXPORT
jstring
JNICALL
Java_com_example_administrator_ndkfile_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}



jint File_write(JNIEnv* env,jobject thiz,jstring content,jstring filepath){
    fileutil* fileutil1 = new fileutil();
    jint  result = fileutil1->Write_file(env,thiz,content,filepath);
    delete(fileutil1);
    fileutil1=NULL;
    return result;

}


jint File_Delete(JNIEnv* env,jobject thiz, jstring filepath){
    fileutil* fileutil1 = new fileutil();
    jint  result = fileutil1->Delete_file(env,thiz,filepath);
    delete(fileutil1);
    fileutil1=NULL;
    return result;

}


// jni 函数列表
static JNINativeMethod getMethods[] = {
//        括号内代表传入参数的签名符号,为空可以不写,括号外代表返回参数的签名符号,为空填写 V,对应关系入下表
        {"FileWrite", "(Ljava/lang/String;Ljava/lang/String;)I",(void*)File_write},
        {"FileDelete", "(Ljava/lang/String;)I",(void*)File_Delete},

};

//此函数通过调用RegisterNatives方法来注册我们的函数
static int registerNativeMethods(JNIEnv* env, const char* className,JNINativeMethod* getMethods,int methodsNum){
    jclass clazz;
    //找到声明native方法的类
    clazz = env->FindClass(className);
    if(clazz == NULL){
        return JNI_FALSE;
    }
    //注册函数 参数:java类 所要注册的函数数组 注册函数的个数
    if(env->RegisterNatives(clazz,getMethods,methodsNum) < 0){
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

static int registerNatives(JNIEnv* env){
    //指定类的路径,通过FindClass 方法来找到对应的类
    const char* className  = "com/example/administrator/ndkfile/FileUtils";
    return registerNativeMethods(env,className,getMethods, sizeof(getMethods)/ sizeof(getMethods[0]));
}

//回调函数 在加载JNI 的时候去注册函数
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved ){
    JNIEnv* env = NULL;
    //获取JNIEnv
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    __glibcxx_assert(env != NULL);
    //注册函数 registerNatives ->registerNativeMethods ->env->RegisterNatives
    if(!registerNatives(env)){
        return -1;
    }
    //返回jni 的版本
    return JNI_VERSION_1_6;

}

 fileutil.h 头文件

定义了文件操作的方法以及,构造函数和析构函数
//
// Created by Administrator on 2019/11/28 0028.
//

#ifndef NDKFILE_FILEUTIL_H
#define NDKFILE_FILEUTIL_H


#include <jni.h>

class fileutil {


public:
    fileutil();
    ~ fileutil();
    jint Delete_file(JNIEnv* env,jobject thiz,jstring filepath);
    jint Write_file(JNIEnv* env,jobject thiz,jstring content,jstring filepath);

};


#endif //NDKFILE_FILEUTIL_H

fileutil.cpp 文件

文件类的实现:
//
// Created by Administrator on 2019/11/28 0028.
//

#include "fileutil.h"
#include <iostream>
#include <android/log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <cstdlib>
#include <unistd.h>

// 定义info信息
#define  LOG_TAG    "[CHENZHU_JNILOG]"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
using namespace std;

fileutil::fileutil(){
    LOGI("构造函数");
};


/**
 * File_write--操作文件目录
 * 返回0--成功
 */

jint fileutil::Write_file(JNIEnv* env,jobject thiz,jstring content,jstring filepath){

    FILE * file;
    const char * file_path  = env->GetStringUTFChars( filepath, JNI_FALSE);
    const char * write_content  = env->GetStringUTFChars( content, JNI_FALSE);

    LOGI("go to file write:%s\n", file_path);

    file = fopen(file_path,"a+");//如果文件存在就添加内容,如果文件不存在就创建新文件
    if (file== NULL){
        LOGI("open file faile%s\n","");
    }else{
        LOGI("open file success%s\n","");
    }

    fputs(write_content,file);//写入操作
    fclose(file);//关闭文件流
    //free(filepath);//释放动态内存,防止内存泄露

    //在这里再回调一下 Java 告诉他写入完成
    jclass j_class = env->FindClass("com/example/administrator/ndkfile/FileUtils");
    jmethodID  method = env->GetStaticMethodID(j_class, "callByJNI","(I)V");
   // 回调静态方法
    env->CallStaticVoidMethod(j_class, method, 666);
    return 0;//正确 执行返回

}

jint fileutil::Delete_file(JNIEnv* env,jobject thiz,jstring filepath) {
    const  char* dirName = env->GetStringUTFChars(filepath,JNI_FALSE);

    if(0 == access(dirName,0)) {//目录存在
        LOGI("目录存在 需要删除\n");
        int issuccess= remove(dirName);
        if (issuccess==0){
            LOGI("目录存在 删除成功\n");
            return 0;
        } else{
            LOGI("目录存在 删除失败\n");
            return 1;
        }

    } else{
        LOGI("目录不存在 不用删除\n");
        return 0;
    }

}

fileutil::~fileutil() {
    LOGI("析构函数");
}

对应的Java文件 Fileutil.Java

package com.example.administrator.ndkfile;

public class FileUtils {

    //类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
    private static FileUtils instance;

    //构造器私有化
    private FileUtils(){}

    //方法同步,调用效率低
    public static synchronized FileUtils getInstance(){
        if(instance==null){
            instance=new FileUtils();
        }
        return instance;
    }

    public  native int FileWrite(String conten,String path);
    public  native int FileDelete(String path);
    public static void  callByJNI(int data){
        System.out.print("JNI 使用了回调:"+data);
    }


}

 

MainActivity中调用

 

 

 

adb 连接手机查看  

 cd 到对应目录下 。cat查看信息,如果要copy 到电脑上的话 

//    要推出 adb shell然后   adb pull /sdcard/data.txt data.txt
//    adb copy 到电脑的C:\Users\Administrator\Desktop  上

 

 

 

后面如果有同学需要继续完善 上传这些日志到服务器的话给我留言 我把后面的继续完善。

github源码地址 https://github.com/chenzhu005774/NDKFile

 

发布了34 篇原创文章 · 获赞 22 · 访问量 4万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览