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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章