最近被上头要求设计一个程序,将JNI的调试信息保存在一个文件当中,此处参考了多位大神的文章:
adb环境配置:右键我的电脑->属性->高级->环境变量->Path,在Path中添加Android SDK安装路径中adb.exe(在platform tools文件夹中)的路径(注意环境变量添加的规范,用';'分号隔开前一个路径)
1. 操作解释:因JNI程序是在android的平台运行,故此处使用的方式是利用java的Runtime.getRuntime().exec(命令语句)方法来执行adb的logcat命令,以此获取logcat的调试信息并利用IO流将其写出到SD卡中。
2. 文件查找:
a. 真机测试: logrecord.txt文件在:文件管理—>手机存储—>logRecordData目录中
b. 虚拟机测试:选择工具栏的Tools—>Android—>Android Device Monitor—>打开界面后在左侧device处选择正在使用的设备—>选择右侧的FileExplorer—>storage —>sdcard—>logRecordData
3. 代码部分
3.1获取权限
<!--获取log信息权限和sd卡的写入权限--> <uses-permission android:name="android.permission.READ_LOGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3.2创建一个LogcatHelper(这部分代码不是我的,是别人的:转自http://blog.csdn.net/way_ping_li/article/details/8487866)
package cprocess.cpart.utils; import android.content.Context; import android.os.Environment; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.Date; public class LogcatHelper { private static LogcatHelper INSTANCE = null; private static String PATH_LOGCAT; private LogDumper mLogDumper = null; private int mPId; public void init(Context context) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) {// 优先保存到SD卡中:映射的方式获取sd卡根目录Environment.getExternalStorageDirectory().getAbsolutePath()
PATH_LOGCAT = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "logRecordData"; } else {// 如果SD卡不存在,就保存到本应用的目录下 PATH_LOGCAT = context.getFilesDir().getAbsolutePath() + File.separator + "logRecordData"; } File file = new File(PATH_LOGCAT); if (!file.exists()) { file.mkdirs(); } } public static LogcatHelper getInstance(Context context) { if (INSTANCE == null) { INSTANCE = new LogcatHelper(context); } return INSTANCE; } private LogcatHelper(Context context) { init(context); mPId = android.os.Process.myPid();//取得当前的进程名 } public void start() { if (mLogDumper == null) mLogDumper = new LogDumper( String.valueOf(mPId), PATH_LOGCAT); mLogDumper.start(); } public void stop() { if (mLogDumper != null) { mLogDumper.stopLogs(); mLogDumper = null; } } private class LogDumper extends Thread { private Process logcatProc; private BufferedReader mReader = null; private boolean mRunning = true; String cmds = null; private String PID; private FileOutputStream out = null; public LogDumper( String pid, String dir) { PID = pid; try { out = new FileOutputStream(new File(dir,"logrecord"+ MyDate.getFileName() + ".txt")); } catch (FileNotFoundException e) { e.printStackTrace(); } /** * 关于adb logcat的操作可以在Termial输入"adb logcat --help"查询 * * */ cmds = "logcat -s JNI_LOG | grep \"(" + PID + ")\"";//包含当前进程名的TAG为JNI_LOG的logcat信息 } public void stopLogs() { mRunning = false; } @Override public void run() { try { logcatProc = Runtime.getRuntime().exec(cmds); mReader = new BufferedReader(new InputStreamReader( logcatProc.getInputStream()), 1024); String line = null; while (mRunning && (line = mReader.readLine()) != null) { if (!mRunning) { break; } if (line.length() == 0) { continue; } if (out != null&& line.contains(PID)) { out.write((MyDate.getDateEN() + " " + line + "\n") .getBytes()); } } } catch (IOException e) { e.printStackTrace(); } finally { if (logcatProc != null) { logcatProc.destroy(); logcatProc = null; } if (mReader != null) { try { mReader.close(); mReader = null; } catch (IOException e) { e.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } out = null; } } } } } class MyDate { public static String getFileName() { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String date = format.format(new Date(System.currentTimeMillis())); return date;// 2012-10-03 } public static String getDateEN() { SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String date1 = format1.format(new Date(System.currentTimeMillis())); return date1;// 2012-10-03 23:41:31 } }3.3在JNI文件中调用<android/log.h>并定义相应的LOGCAT参数及规则
#include <jni.h> #include <android/log.h> #define JNI_DEBUG #ifdef JNI_DEBUG #ifndef LOG_TAG #define LOG_TAG "JNI_LOGINFO"//自定义的标签 #endif //优先级是下面的字符,顺序是从低到高: //V — 明细 verbose(最低优先级) //D — 调试 debug //I — 信息 info //W — 警告 warn //E — 错误 error //F — 严重错误 fatal #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)//verbose #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)//debug #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)//info #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)//warn #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)//error #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)//fatal #endif /* * 格式为:Java_包名_类名_函数名 */ JNIEXPORT jstring JNICALL Java_cutils_CUtilA_getStringFromCA (JNIEnv *env, jclass obj){ LOGI("log信息测试I"); LOGD("log信息测试D"); LOGW("log信息测试W"); LOGE("log信息测试E"); LOGV("log信息测试V"); LOGF("log信息测试F"); char *str = "JNI中实例化的arg1"; jstring jstr = (*env)->NewStringUTF(env, str); return jstr; };
3.4在android的activtiy中进行相应的JNI接口文件的调用和LogcatHelper的实例化和调用
转载或参考自:
http://blog.csdn.net/way_ping_li/article/details/8487866
http://blog.csdn.net/tumuzhuanjia/article/details/39555445
http://blog.csdn.net/nfer_zhuang/article/details/44701657
http://blog.csdn.net/tumuzhuanjia/article/details/39555445