Android Log大全

Android log系统light2011/11/20Android 系统log抓取,实现原理分析一概述本文档主要是供Android开发人员使用,特别是Framework开发。

因为Framework中95%以上的问题都是靠分析log解决的,所以开发人员必须对android整个log系统十分清楚。

什么问题抓什么log, 使用什么工具抓Log,如何分析log,如何在代码中添加log.二DDMS log关于ddms是如何工作的和ddms的详细功能,见下面android sdk中文档详细介绍:F:\02 Android\01_SDK\Gingerbread2.3\docs-2.3_r01-linux\guide\developing\tools\ddms.htmlDdms 工具中打印log的几个菜单如下:Device -> Show process status…Device -> Dump device state…Device -> Dump app state…Device -> Dump radio state…Device -> Run logcat…1、Show process status…菜单等效于在adb shell下执行adb shell ps –x 命令,该命令打印出进程的详细信息,如下:USER PID PPID VSIZE RSS WCHAN PC NAMEroot 1 0 268 180 c009b74c 0000875c S /init (u:2, s:371) root 2 0 0 0 c004e72c 00000000 S kthreadd (u:0, s:1) root 3 2 0 0 c003fdc8 00000000 S ksoftirqd/0 (u:0, s:0) root 4 2 0 0 c004b2c4 00000000 S events/0 (u:0, s:39) root 5 2 0 0 c004b2c4 00000000 S khelper (u:0, s:0) root 6 2 0 0 c004b2c4 00000000 S suspend (u:0, s:0)USER 用户名,即用户所在组PID 进程ID(Process ID)PPID 父进程的进程ID(Parent Process id)VSZ 进程所使用的虚拟内存的大小(Virtual Size)RSS 进程使用的驻留集大小或者是实际内存的大小,Kbytes字节。

WCHAN 进程正在睡眠的内核函数名称;该函数的名称是从/root/system.map文件中获得的Exploring ProcessesYou can see the output of ps -x for a specific VM by selecting Device>Show process status... in the menu bar.2、Dump device state…菜单等效于执行/system/bin/dumpstate/proc/self/fd/0等效于执行adb shell dumpstate命令To run dumpstate from Dalvik, select Device>Dump device state... in the menu bar.3、Dump app state…菜单等效于执行adb shell dumpsys命令输出android服务状态信息,即输出服务中dump函数的log.4、Dump radiostate…菜单等效于执行adb shell cat /data/logs/radio命令Examine Radio StateBy default, radio state is not output during a standard logcat (it is a lot of information). To see radio information, either click Device>Dump radio state... or run logcat as described in5、Run logcat…菜单等效于执行adb logcatTo run dumpsys (logcat) from Dalvik, select Device>Run logcat... in the menu bar.总结:除了Run logcat…菜单是实时输出设备中的log外,其他菜单都是输出设备中缓存的log 三Adb LogAndroid sdk文档中对adb的介绍见下:F:\02 Android\01_SDK\Gingerbread2.3\docs-2.3_r01-linux\guide\developing\tools\adb.html在adb 1.0.26版本共有2条命令打印log,如下:adb logcat [ <filter-spec> ] - View device logadb bugreport - return all information from the devicethat should be included in a bug report.Adb logcat常用命令logcat -c 清除已有log信息logcat -b main 显示主缓冲区的loglogcat -b radio 显示无线缓冲区的loglogcat -b events 显示事件缓冲区的loglogcat -f [filename] 将log保存到指定的文件中,例如logcat -b radio -f /data/radio.log 比较常用的是显示时间:logcat -v time &logcat -g 查看缓冲区的大小logcat -g mainlogcat -g radiologcat -g eventslogcat打印/dev/log设备下的三个文件radio, events, main数据logcat默认是输出main缓冲区的log控制日志输出格式日志信息包括了许多元数据域包括标签和优先级。

可以修改日志的输出格式,所以可以显示出特定的元数据域。

可以通过-v 选项得到格式化输出日志的相关信息.brief — Display priority/tag and PID of originating process (the default format).process — Display PID only.tag — Display the priority/tag only.thread — Display process:thread and priority/tag only.raw — Display the raw log message, with no other metadata fields.time — Display the date, invocation time, priority/tag, and PID of the originating process.long — Display all metadata fields and separate messages with a blank lines.当启动了logcat ,你可以通过-v 选项来指定输出格式:[adb] logcat [-v <format>]此外,adb shell cmd, cmd为/system/bin目录下抓log的可执行程序,如dumpsys , dumpstate 等Adb下的log命令:Adb logcatAdb bugreportAdb shell dumpsysAdb shell dumpstateAdb shell dmesg //导出当前缓存的kernel logAdb shell kmsgcat //实时查看kernel log其他查看系统当前信息命令Adb shell ps //查看系统进程信息,可以加很多有用信息Adb shell pm //查看package相关信息Adb shell am //启动apk应用Adb shell setprop //设置系统属性Adb shell getprop //查看所有系统属性Adb shell rebootAdb shell kill //通过进程ID杀死指定的进程Adb shell top //查看当前运行进程信息Adb shell vmstat //查看虚拟机信息Adb shell bootanimation //播放开机动画Adb shell df //查看分区信息Adb shell monkey //跑自动化测试用例四保存在手机的Log1、手机dropbox默认路径:/data/system/dropbox/实现机制:log文件什么场景产生?Log文件分析:2、手机anr日志默认路径:/data/anr/实现机制:log文件什么场景产生?Log文件分析:4、tombstones路径:/data/tombstoneslog文件什么场景产生?Log文件分析:五如何实现后台抓Log如:adb logcat -v time -r 1024 -n 16 -f /sdcard/bugreports/applogcat-log六log执行程序实现机制1、LogcatLogCat是在文件system/core/logcat/logcat.cpp中实现的。

从Logger设备驱动的实现知道,Log的读取是阻塞的操作,亦即,有数据可用,读出数据;否则,读操作会被BLOCK,相应的读进程也会被挂起等待。

下面看应用程序LogCat 中如何实现读的,这可能需要不断回头与写操作和驱动实现结合来看。

看具体实现之前,先看一个logcat中定义的重要的结构体log_device_t。

其中的重要的成员在后面用到的时候再具体解释。

Android的Logcat命令详解的命令参数-b <buffer>知道,logcat是可以通过参数来指定对哪个buffer(main/radio/event)进行操作的。

Logcat的b参数解析的地方,是通过传递进来的参数(main/radio/event)来创建了一个上面的结构变量,而这些结构通过log_device_t.next链接起来因为logcat可能会同时操作多个Buffer,而read()会阻塞读取进程,对其他Buffer的读取就不能进行,所以这里用select()来判断可读取的Buffer。

合集下载

Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)

Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)

在Android群里,经常会有人问我,Android Log是怎么用的,今天我就把从网上以及SDK里东拼西凑过来,让大家先一睹为快,希望对大家入门Android Log有一定的帮助.android.util.Log常用的方法有以下5个:Log.v() Log.d() Log.i() Log.w() 以及Log.e() 。

根据首字母对应VERBOSE,DEBUG,INFO, WARN,ERROR。

1、Log.v 的调试颜色为黑色的,任何消息都会输出,这里的v代表verbose?嗦的意思,平时使用就是Log.v("","");2、Log.d的输出颜色是蓝色的,仅输出debug调试的意思,但他会输出上层的信息,过滤起来可以通过DDMS的Logcat标签来选择.3、Log.i的输出为绿色,一般提示性的消息information,它不会输出Log.v和Log.d的信息,但会显示i、w和e的信息4、Log.w的意思为橙色,可以看作为warning警告,一般需要我们注意优化Android代码,同时选择它后还会输出Log.e的信息。

5、Log.e为红色,可以想到error错误,这里仅显示红色的错误信息,这些错误就需要我们认真的分析,查看栈的信息了。

下面是我做的一个简单的LogDemo(Step By Step):Step 1:准备工作(打开LogCat视窗).启动Eclipse,在Window->Show V iew会出来一个对话框,当我们点击Ok按钮时,会在控制台窗口出现LogCat视窗.如下图:Step 2:新建一个Android工程,命名为LogDemo.Step 3:设计UI界面,我们在这里就加了一个Button按钮(点击按钮出现Log日志信息). Main.xml代码如下:<?xml version="1.0" encoding="utf-8"?>< LinearLayout xmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent">< TextV iewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="@string/hello"/ >< Buttonandroid:id="@+id/bt"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Presse Me Look Log"/ >< /LinearLayout >Step 4:设计主类LogDemo.java,代码如下:package com.android.test;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;public class LogDemo extends Activity {private static final String ACTIVITY_TAG="LogDemo";private Button bt;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentV iew(yout.main);//通过findV iewById找到Button资源bt = (Button)findV iewById(R.id.bt);//增加事件响应bt.setOnClickListener(new Button.OnClickListener(){@Overridepublic void onClick(View v) {Log.v(LogDemo.ACTIVITY_TAG, "This is V erbose.");Log.d(LogDemo.ACTIVITY_TAG, "This is Debug.");Log.i(LogDemo.ACTIVITY_TAG, "This is Information");Log.w(LogDemo.ACTIVITY_TAG, "This is Warnning.");Log.e(LogDemo.ACTIVITY_TAG, "This is Error.");}});}}Step 5:运行LogDemo工程,效果如下:当我们点击按钮时,会触发事件,在Logcat视窗下有如下效果:。

android logd函数 用法

android logd函数 用法

android logd函数用法Android中的logd函数是一个用于打印调试信息的函数。

在Android开发中,经常需要进行调试,以便了解应用程序中的问题并找出解决方案。

logd函数可以帮助开发者在应用程序中输出调试信息,方便查找问题。

本文将详细介绍logd函数的用法,包括如何使用、参数介绍以及常见应用场景等。

一、logd函数的基本介绍logd函数属于Android系统的日志工具,用于在应用程序中输出调试信息。

它的使用方式类似于System.out.println()函数,在应用程序的任何位置都可以调用。

logd函数的全名为android.util.Log.d(String tag, String msg),其中tag表示日志的标签,用于区分不同模块或功能的日志信息;msg表示具体的日志信息内容。

二、logd函数的使用方法1. 导入日志库在开始使用logd函数之前,需要先导入日志库,可以在Java类文件的顶部添加以下语句:import android.util.Log;这会使得Log类可用,从而可以使用logd函数。

2. 在代码中调用logd函数logd函数可以在代码的任何位置进行调用,以输出相应的日志信息。

可以在方法中、循环中或条件判断中使用,以便进行详细的调试。

以下是调用logd函数的示例代码:Log.d("MainActivity", "This is a debug message.");在这个示例代码中,"MainActivity"表示日志的标签,"This is a debug message."表示具体的日志信息内容。

3. 设置日志级别除了logd函数外,在Android中还有logi、logw、loge等其他日志打印函数,它们分别对应不同的日志级别。

在默认情况下,只有日志级别大于或等于应用的日志级别才会被输出,这样可以避免在发布版本中输出过多的日志信息。

Android开发学习之Log的使用

Android开发学习之Log的使用

Android开发学习之Log的使⽤Log(android.util.log)是Android Studio中的⽇志⼯具类,熟练使⽤log会对你以后的Android开发之旅有很⼤的帮助。

* log类有五个⽅法,分别是(级别由低到⾼):根据⾸字母对应VERBOSE,DEBUG,INFO, WARN,ERROR。

1.Log.v():打印⼀些最为繁琐、意义不⼤的⽇志信息2.Log.d():打印⼀些调试信息(logd+tab)3.Log.i():打印⼀些⽐较重要的数据,可帮助你分析⽤户⾏为数据(logi+tab)4.Log.w():打印⼀些警告信息,提⽰程序该处可能存在的风险(logw+tab)5.Log.e():打印程序中的错误信息(loge+tab)(这五个⽅法都可以进⾏重载)注意:不同的打印⽅法在使⽤时都是某个⽅法带上(String tag, String msg)参数,tag表⽰的是打印信息的标签,msg表⽰的是需要打印的信息。

Android Studio中查看logAndroid Studio为开发者提供了良好的log查看⼯具,开发者可以通过如下⽅式打开log视图:View > Tool Windows > Logcat,或者⽤默认的快捷键 Alt+6 打开/隐藏 Logcat视图。

下⾯简单介绍⼀下该⼯具的使⽤。

1、Logcat中选择筛选条件如下截图中,标注了Android Studio中使⽤Logcat视图的常⽤功能,开发者可以根据实际情况选择过滤条件。

2、Log信息颜⾊设置查看log的时候,有⼀个⼩技巧,为了便于查看不同等级的log,Android Studio对不同等级的log信息设置了不同的颜⾊。

开发者也可以根据⾃⼰的爱好,⾃⾏设置颜⾊或者其他属性,这样,在查看log的时候,就容易对log等级进⾏区分,查看的时候就⽐较有层次感。

设置路径为:File > Settings > Editor > Colors & Fonts > Android Logcat。

AndroidANRlogtrace日志文件分析

AndroidANRlogtrace日志文件分析

AndroidANRlogtrace⽇志⽂件分析什么是ANR?ANR:Application Not Responding,即应⽤⽆响应ANR⽇志Trace⽂件获取系统⽣成的Trace⽂件保存在data/anr,可以⽤过命令adb pull data/anr/取出traces.txt只保留最后⼀次ANR的信息,Android系统有个DropBox功能功能,它能记录系统出现的crash错误.因此保留有发⽣过的ANR的信息.(log路径:/data/system/dropbox)获取系统crash log: adb shell dumpsys dropbox --print >>log.txtTrace⽂件怎么⽣成的?当APP(包括系统APP和⽤户APP)进程出现ANR、应⽤响应慢或WatchDog的监视没有得到回馈时,系统会dump此时的top进程,进程中Thread的运⾏状态就都dump到这个Trace⽂件中了.导致ANR的常见⼏种情况:1:Input dispatching timed out(5 seconds) 按键或触摸事件处理超时(⼀般是UI主线程做了耗时的操作,这类ANR最常见)2:BroadcastTimeout(10 seconds) ⼴播的分发和处理超时(⼀般是onReceiver执⾏时间过长)3:ServiceTimeout(20 seconds) Service的启动和执⾏超时另外还有ProviderTimeout和WatchDog等导致的ANR.还有当系统内存或CPU资源不⾜时容易出现ANR,⼀般这种情况会有lowmemorykill的log打印.应⽤ANR产⽣的时候,ActivityManagerService的appNotResponding⽅法就会被调⽤,然后在/data/anr/traces.txt⽂件中写⼊ANR相关信息.final void appNotResponding(ProcessRecord app, ActivityRecord activity,ActivityRecord parent, boolean aboveSystem, final String annotation) {// ... ...if (MONITOR_CPU_USAGE) {updateCpuStatsNow(); // 更新CPU使⽤率}// ... ...final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);// dumpStackTraces是输出traces⽂件的函数File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids,NATIVE_STACKS_OF_INTEREST);String cpuInfo = null;if (MONITOR_CPU_USAGE) {updateCpuStatsNow(); // 再次更新CPU信息synchronized (mProcessCpuTracker) {// 输出ANR发⽣前⼀段时间内的CPU使⽤率cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);}info.append(processCpuTracker.printCurrentLoad());info.append(cpuInfo);}// 输出ANR发⽣后⼀段时间内的CPU使⽤率info.append(processCpuTracker.printCurrentState(anrTime));Slog.e(TAG, info.toString());if (tracesFile == null) {// There is no trace file, so dump (only) the alleged culprit's threads to the logProcess.sendSignal(app.pid, Process.SIGNAL_QUIT);}// 将ANR信息同时输出到DropBox中addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,cpuInfo, tracesFile, null);// ... ...synchronized (this) {// 显⽰ANR提⽰对话框// Bring up the infamous App Not Responding dialogMessage msg = Message.obtain();HashMap<String, Object> map = new HashMap<String, Object>();msg.what = SHOW_NOT_RESPONDING_MSG;msg.obj = map;msg.arg1 = aboveSystem ? 1 : 0;map.put("app", app);if (activity != null) {map.put("activity", activity);}mUiHandler.sendMessage(msg);}}避免ANR?UI线程尽量只做跟UI相关的⼯作耗时的⼯作(⽐如数据库操作,I/O,连接⽹络或者别的有可能阻碍UI线程的操作)把它放⼊单独的线程处理尽量⽤Handler来处理UIthread和别的thread之间的交互分析ANR的Log:出现ANR的log如下:06-22 10:37:46.204 3547 3604 E ActivityManager: ANR in org.code:MessengerService // ANR出现的进程包名E ActivityManager: PID: 17027 // ANR进程IDE ActivityManager: Reason: executing service org.code/.ipc.MessengerService //导致ANR的原因E ActivityManager: Load: 8.31 / 8.12 / 8.47E ActivityManager: CPU usage from 0ms to 6462ms later: //CPU在ANR发⽣后的使⽤情况E ActivityManager: 61% 3547/system_server: 21% user + 39% kernel / faults: 13302 minor 2 majorE ActivityManager: 0.2% 475/debuggerd: 0% user + 0.1% kernel / faults: 6086 minor 1 majorE ActivityManager: 10% 5742/com.android.phone: 5.1% user + 5.1% kernel / faults: 7597 minorE ActivityManager: 6.9% 5342/com.android.systemui: 2.1% user + 4.8% kernel / faults: 4158 minorE ActivityManager: 0.1% 477/debuggerd64: 0% user + 0.1% kernel / faults: 4013 minorE ActivityManager: 5.7% 16313/org.code: 3.2% user + 2.4% kernel / faults: 2412 minorE ActivityManager: 3.7% 17027/org.code:MessengerService: 1.7% user + 2% kernel / faults: 2571 minor 6 majorE ActivityManager: 2.6% 306/cfinteractive: 0% user + 2.6% kernel... ...E ActivityManager: +0% 17168/kworker/0:1: 0% user + 0% kernelE ActivityManager: 0% TOTAL: 0% user + 0% kernel + 0% softirq // CUP占⽤情况E ActivityManager: CPU usage from 5628ms to 6183ms later:E ActivityManager: 42% 3547/system_server: 17% user + 24% kernel / faults: 11 minorE ActivityManager: 12% 3604/ActivityManager: 1.7% user + 10% kernelE ActivityManager: 12% 3609/android.display: 8.7% user + 3.5% kernelE ActivityManager: 3.5% 5304/Binder_6: 1.7% user + 1.7% kernelE ActivityManager: 3.5% 5721/Binder_A: 1.7% user + 1.7% kernelE ActivityManager: 3.5% 5746/Binder_C: 3.5% user + 0% kernelE ActivityManager: 1.7% 3599/Binder_1: 0% user + 1.7% kernelE ActivityManager: 1.7% 3600/Binder_2: 0% user + 1.7% kernelI ActivityManager: Killing 17027:org.code:MessengerService/u0a85 (adj 1): bg anrI art : Wrote stack traces to '/data/anr/traces.txt' //art这个TAG打印对traces操作的信息D GraphicsStats: Buffer count: 9W ActivityManager: Scheduling restart of crashed service org.code/.ipc.MessengerService in 1000mslog打印了ANR的基本信息,我们可以分析CPU使⽤率推测ANR发⽣的时候设备在做什么⼯作;如果CPU使⽤率很⾼,接近100%,可能是在进⾏⼤规模的计算更可能是陷⼊死循环;如果CUP使⽤率很低,说明主线程被阻塞了,并且当IOwait很⾼,可能是主线程在等待I/O操作的完成.对于ANR只是分析Log很难知道问题所在,我们还需要通过Trace⽂件分析stack调⽤情况.----- pid 17027 at 2017-06-22 10:37:39 ----- // ANR出现的进程pid和时间(和上述log中pid⼀致)Cmd line: org.code:MessengerService // ANR出现的进程名Build fingerprint: 'Homecare/qucii8976v3_64:6.0.1/pansen06141150:eng/test-keys' // 下⾯记录系统版本,内存等状态信息ABI: 'arm64'Build type: optimizedZygote loaded classes=6576 post zygote classes=13Intern table: 13780 strong; 17 weakJNI: CheckJNI is on; globals=283 (plus 158 weak)Libraries: /system/lib64/libandroid.so /system/lib64/libcompiler_rt.so /system/lib64/libjavacrypto.so /system/lib64/libjnigraphics.so /system/lib64/libmedia_jni.so /system/lib64/libwebviewchromium_loader.so libjavacore.so (7 Heap: 29% free, 8MB/12MB; 75731 objectsDumping cumulative Gc timingsTotal number of allocations 75731Total bytes allocated 8MBTotal bytes freed 0BFree memory 3MBFree memory until GC 3MBFree memory until OOME 183MBTotal memory 12MBMax memory 192MBZygote space size 3MBTotal mutator paused time: 0Total time waiting for GC to complete: 0Total GC count: 0Total GC time: 0Total blocking GC count: 0Total blocking GC time: 0suspend all histogram: Sum: 76us 99% C.I. 0.100us-28us Avg: 7.600us Max: 28usDALVIK THREADS (15):// Signal Catcher是记录traces信息的线程// Signal Catche(线程名)、(daemon)表⽰守护进程、prio(线程优先级,默认是5)、tid(线程唯⼀标识ID)、Runnable(线程当前状态)"Signal Catcher" daemon prio=5 tid=3 Runnable//线程组名称、suspendCount、debugSuspendCount、线程的Java对象地址、线程的Native对象地址| group="system" sCount=0 dsCount=0 obj=0x12d8f0a0 self=0x5598ae55d0//sysTid是线程号(主线程的线程号和进程号相同)| sysTid=17033 nice=0 cgrp=default sched=0/0 handle=0x7fb2350450| state=R schedstat=( 4348125 172343 3 ) utm=0 stm=0 core=1 HZ=100| stack=0x7fb2254000-0x7fb2256000 stackSize=1013KB| held mutexes= "mutator lock"(shared held)native: #00 pc 0000000000489e28 /system/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::ArtMethod*, void*)+236)native: #01 pc 0000000000458fe8 /system/lib64/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+220)native: #02 pc 0000000000465bc8 /system/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+688)native: #03 pc 0000000000466ae0 /system/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*)+276)native: #04 pc 000000000046719c /system/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)+188)native: #05 pc 0000000000467a84 /system/lib64/libart.so (art::ThreadList::DumpForSigQuit(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)+492)native: #06 pc 0000000000431194 /system/lib64/libart.so (art::Runtime::DumpForSigQuit(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)+96)native: #07 pc 000000000043e604 /system/lib64/libart.so (art::SignalCatcher::HandleSigQuit()+1256)native: #08 pc 000000000043f214 /system/lib64/libart.so (art::SignalCatcher::Run(void*)+452)native: #09 pc 0000000000068714 /system/lib64/libc.so (__pthread_start(void*)+52)native: #10 pc 000000000001c604 /system/lib64/libc.so (__start_thread+16)(no managed stack frames)//main(线程名)、prio(线程优先级,默认是5)、tid(线程唯⼀标识ID)、Sleeping(线程当前状态)"main" prio=5 tid=1 Sleeping| group="main" sCount=1 dsCount=0 obj=0x73132d10 self=0x5598a5f5e0//sysTid是线程号(主线程的线程号和进程号相同)| sysTid=17027 nice=0 cgrp=default sched=0/0 handle=0x7fb6db6fe8| state=S schedstat=( 420582038 5862546 143 ) utm=24 stm=18 core=6 HZ=100| stack=0x7fefba3000-0x7fefba5000 stackSize=8MB| held mutexes=// java 堆栈调⽤信息(这⾥可查看导致ANR的代码调⽤流程)(分析ANR最重要的信息)at ng.Thread.sleep!(Native method)- sleeping on <0x0c60f3c7> (a ng.Object)at ng.Thread.sleep(Thread.java:1031)- locked <0x0c60f3c7> (a ng.Object) // 锁住对象0x0c60f3c7at ng.Thread.sleep(Thread.java:985)at android.os.SystemClock.sleep(SystemClock.java:120)at org.code.ipc.MessengerService.onCreate(MessengerService.java:63) //导致ANR的代码at android.app.ActivityThread.handleCreateService(ActivityThread.java:2877)at android.app.ActivityThread.access$1900(ActivityThread.java:150)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1427)at android.os.Handler.dispatchMessage(Handler.java:102)at android.os.Looper.loop(Looper.java:148)at android.app.ActivityThread.main(ActivityThread.java:5417)at ng.reflect.Method.invoke!(Native method)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)在log中显⽰的pid在traces⽂件中与之对应,trace log中会打印当前所有线程的堆栈信息,⼀般我们主要关注main线程的堆栈(也有分析其他线程的情况,通过分析ANR发⽣时系统状态推测出设备正在进⾏操作)⽽这⾥然后通过查看堆栈调⽤信息分析ANR的代码.上述ANR实际上在org.code.ipc.MessengerService.onCreate中63⾏调⽤SystemClock.sleep(10000)代码导致的;这是⽐较简单ANR⽰例.以上仅为解决ANR问题提供⼀个思路,具体问题还需要根据实际情况具体分析线程状态的分类: java中定义的线程状态:// libcore/libart/src/main/java/java/lang/Thread.java/*** A representation of a thread's state. A given thread may only be in one* state at a time.*/public enum State {/*** The thread has been created, but has never been started.*/NEW,/*** The thread may be run.*/RUNNABLE,/*** The thread is blocked and waiting for a lock.*/BLOCKED,/*** The thread is waiting.*/WAITING,/*** The thread is waiting for a specified amount of time.*/TIMED_WAITING,/*** The thread has been terminated.*/TERMINATED}C代码中定义的线程状态:// /art/runtime/thread_state.henum ThreadState {// Thread.State JDWP statekTerminated = 66, // TERMINATED TS_ZOMBIE Thread.run has returned, but Thread* still aroundkRunnable, // RUNNABLE TS_RUNNING runnablekTimedWaiting, // TIMED_WAITING TS_WAIT in Object.wait() with a timeoutkSleeping, // TIMED_WAITING TS_SLEEPING in Thread.sleep()kBlocked, // BLOCKED TS_MONITOR blocked on a monitorkWaiting, // WAITING TS_WAIT in Object.wait()kWaitingForGcToComplete, // WAITING TS_WAIT blocked waiting for GCkWaitingForCheckPointsToRun, // WAITING TS_WAIT GC waiting for checkpoints to runkWaitingPerformingGc, // WAITING TS_WAIT performing GCkWaitingForDebuggerSend, // WAITING TS_WAIT blocked waiting for events to be sentkWaitingForDebuggerToAttach, // WAITING TS_WAIT blocked waiting for debugger to attachkWaitingInMainDebuggerLoop, // WAITING TS_WAIT blocking/reading/processing debugger eventskWaitingForDebuggerSuspension, // WAITING TS_WAIT waiting for debugger suspend allkWaitingForJniOnLoad, // WAITING TS_WAIT waiting for execution of dlopen and JNI on load codekWaitingForSignalCatcherOutput, // WAITING TS_WAIT waiting for signal catcher IO to completekWaitingInMainSignalCatcherLoop, // WAITING TS_WAIT blocking/reading/processing signalskWaitingForDeoptimization, // WAITING TS_WAIT waiting for deoptimization suspend allkWaitingForMethodTracingStart, // WAITING TS_WAIT waiting for method tracing to startkWaitingForVisitObjects, // WAITING TS_WAIT waiting for visiting objectskWaitingForGetObjectsAllocated, // WAITING TS_WAIT waiting for getting the number of allocated objectskStarting, // NEW TS_WAIT native thread started, not yet ready to run managed codekNative, // RUNNABLE TS_RUNNING running in a JNI native methodkSuspended, // RUNNABLE TS_RUNNING suspended by GC or debugger};两者可以看出在C代码中定义更为详细,Traces中显⽰的线程状态都是C代码定义的.我们可以通过查看线程状态对应的信息分析ANR问题.如: TimedWaiting对应的线程状态是TIMED_WAITINGkTimedWaiting, // TIMED_WAITING TS_WAIT in Object.wait() with a timeout 执⾏了⽆超时参数的wait函数kSleeping, // TIMED_WAITING TS_SLEEPING in Thread.sleep() 执⾏了带有超时参数的sleep函数ZOMBIE 线程死亡,终⽌运⾏RUNNING/RUNNABLE 线程可运⾏或正在运⾏TIMED_WAIT 执⾏了带有超时参数的wait、sleep或join函数MONITOR 线程阻塞,等待获取对象锁WAIT 执⾏了⽆超时参数的wait函数INITIALIZING 新建,正在初始化,为其分配资源STARTING 新建,正在启动NATIVE 正在执⾏JNI本地函数VMWAIT 正在等待VM资源SUSPENDED 线程暂停,通常是由于GC或debug被暂停。

如何进行Android应用的日志记录和追踪(四)

如何进行Android应用的日志记录和追踪(四)

在Android开发中,日志记录和追踪是非常关键的,它不仅可以帮助开发者及时发现和解决问题,还能提供对应用程序运行状态的详细了解。

本文将介绍如何进行Android应用的日志记录和追踪,以帮助开发者更好地进行应用调试和性能优化。

1. 使用系统日志工具Android系统提供了一套日志记录工具,包括Logcat和DDMS等,可以帮助开发者记录和查看应用的日志信息。

可以使用Log类的静态方法,如()、()、()等,根据不同类型的日志记录信息的重要程度进行选择。

通过使用这些方法,可以将日志信息输出到Logcat窗口,方便开发者查看。

在使用Log类进行日志记录时,可以在代码的不同位置插入不同级别的日志输出语句,以跟踪应用的执行流程。

例如,在方法的入口处插入()语句,显示方法开始执行的日志信息,在方法的出口处插入()语句,显示方法执行结束的日志信息。

这样,开发者可以通过查看日志信息,更好地了解应用的执行过程。

2. 定制日志记录除了使用系统日志工具外,开发者还可以通过自定义日志记录类来满足特定的需求。

例如,可以创建一个名为Logger的类,提供不同级别的日志记录方法。

在这个自定义的Logger类中,可以设置日志记录的最低级别,并将日志信息输出到指定的文件或网络服务。

在使用自定义日志记录类时,可以在应用的不同模块中使用不同的Logger实例。

例如,在网络请求模块中使用一个Logger实例,将网络请求的相关信息记录到日志文件中;在UI界面模块中使用另一个Logger实例,将用户操作的相关信息记录到日志文件中。

这样,可以更好地组织和管理应用的日志信息。

3. 使用第三方日志库除了使用系统日志工具和自定义日志记录类外,开发者还可以使用第三方日志库来进行日志记录和追踪。

这些第三方日志库通常提供更多的功能和扩展性,可以满足复杂的日志记录需求。

常见的第三方日志库包括Log4j、SLF4J、Timber等。

这些库可以帮助开发者更好地管理日志记录,如设置日志的输出级别、输出格式,支持日志的存储和上传等。

android抓取各种log的方法

android抓取各种log的方法

android抓取各种log的方法在Android开发过程中,我们经常遇到需要抓取各种日志的情况。

日志是开发调试中必不可少的工具,可以帮助我们定位问题,分析程序运行时的情况。

本文将介绍几种常用的方法,帮助您在Android平台上抓取各种日志。

一、Logcat日志Logcat是Android开发中最常用的日志工具,可以输出各种类型的日志信息,包括verbose、debug、info、warn和error等级的日志。

我们可以使用Log类来输出日志信息,例如:```javaimport android.util.Log;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);Log.d(TAG, "This is a debug message");Log.i(TAG, "This is an info message");Log.w(TAG, "This is a warning message");Log.e(TAG, "This is an error message");}}```在Logcat控制台中,可以通过过滤器来选择要显示的日志级别,以及筛选特定的tag,方便我们查看所需的日志信息。

二、文件日志除了在Logcat中输出日志外,我们也可以将日志保存到文件中,以便于离线查看和分析。

Android系统提供了File类和FileOutputStream 类,可以将日志写入到SD卡或应用的私有目录中。

LogAndroid7.1logd日志记录缓冲区大小Android5.1抓取系统日志脚本

LogAndroid7.1logd⽇志记录缓冲区⼤⼩Android5.1抓取系统⽇志脚本⼀.Android7.1 logd ⽇志记录缓冲区⼤⼩先看上层1.1. 布局 KEYprivate static final String SELECT_LOGD_SIZE_KEY = "select_logd_size";private static final String SELECT_LOGD_SIZE_PROPERTY = "persist.logd.size";1.2. writeLogdSizeOption()updateLogpersistValues()private void writeLogdSizeOption(Object newValue) {boolean disable = (newValue != null) &&(newValue.toString().equals(SELECT_LOGD_OFF_SIZE_MARKER_VALUE));String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);if (currentTag == null) {currentTag = "";}// filter clean and unstack all references to our settingString newTag = currentTag.replaceAll(",+" + SELECT_LOGD_TAG_SILENCE, "").replaceFirst("^" + SELECT_LOGD_TAG_SILENCE + ",*", "").replaceAll(",+", ",").replaceFirst(",+$", "");if (disable) {newValue = SELECT_LOGD_MINIMUM_SIZE_VALUE;// Make sure snet_event_log get through first, but do not overrideString snetValue = SystemProperties.get(SELECT_LOGD_SNET_TAG_PROPERTY);if ((snetValue == null) || (snetValue.length() == 0)) {snetValue = SystemProperties.get(SELECT_LOGD_RUNTIME_SNET_TAG_PROPERTY);if ((snetValue == null) || (snetValue.length() == 0)) {SystemProperties.set(SELECT_LOGD_SNET_TAG_PROPERTY, "I");}}// Silence all log sources, security logs notwithstandingif (newTag.length() != 0) {newTag = "," + newTag;}// Stack settings, stack to help preserve original valuenewTag = SELECT_LOGD_TAG_SILENCE + newTag;}if (!newTag.equals(currentTag)) {SystemProperties.set(SELECT_LOGD_TAG_PROPERTY, newTag);}String defaultValue = defaultLogdSizeValue();final String size = ((newValue != null) && (newValue.toString().length() != 0)) ?newValue.toString() : defaultValue;SystemProperties.set(SELECT_LOGD_SIZE_PROPERTY, defaultValue.equals(size) ? "" : size);SystemProperties.set("ctl.start", "logd-reinit");pokeSystemProperties();updateLogdSizeValues();}private void updateLogdSizeValues() {if (mLogdSize != null) {String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);String currentValue = SystemProperties.get(SELECT_LOGD_SIZE_PROPERTY);if ((currentTag != null) && currentTag.startsWith(SELECT_LOGD_TAG_SILENCE)) {currentValue = SELECT_LOGD_OFF_SIZE_MARKER_VALUE;}if (mLogpersist != null) {String currentLogpersistEnable= SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_ENABLE);if ((currentLogpersistEnable == null)|| !currentLogpersistEnable.equals("true")|| currentValue.equals(SELECT_LOGD_OFF_SIZE_MARKER_VALUE)) {writeLogpersistOption(null, true);mLogpersist.setEnabled(false);} else if (mLastEnabledState) {mLogpersist.setEnabled(true);}}if ((currentValue == null) || (currentValue.length() == 0)) {currentValue = defaultLogdSizeValue();}//gatsby 加载res 资源String[] values = getResources().getStringArray(R.array.select_logd_size_values);String[] titles = getResources().getStringArray(R.array.select_logd_size_titles);int index = 2; // punt to second entry if not foundif (SystemProperties.get("ro.config.low_ram").equals("true")) {mLogdSize.setEntries(R.array.select_logd_size_lowram_titles);titles = getResources().getStringArray(R.array.select_logd_size_lowram_titles);index = 1;}String[] summaries = getResources().getStringArray(R.array.select_logd_size_summaries);for (int i = 0; i < titles.length; i++) {if (currentValue.equals(values[i])|| currentValue.equals(titles[i])) {index = i;break;}}mLogdSize.setValue(values[index]);mLogdSize.setSummary(summaries[index]);mLogdSize.setOnPreferenceChangeListener(this);}}⼆.LogBuffer.cpp persist.logd.sizepersist.logd.sizero.logd.sizeLOG_BUFFER_SIZE, 即256kLOG_BUFFER_MIN_SIZE, 即64k三.默认512K--- a/frameworks/base/packages/SettingsLib/res/values-zh-rCN/arrays.xml+++ b/frameworks/base/packages/SettingsLib/res/values-zh-rCN/arrays.xml@@ -62,6 +62,7 @@<item msgid="8665206199209698501">"关闭"</item><item msgid="1593289376502312923">"64K"</item><item msgid="487545340236145324">"256K"</item>+ <item msgid="487545340236145324">"512K"</item><item msgid="2423528675294333831">"1M"</item><item msgid="180883774509476541">"4M"</item><item msgid="2803199102589126938">"16M"</item>@@ -76,6 +77,7 @@<item msgid="6921048829791179331">"关闭"</item><item msgid="2969458029344750262">"每个⽇志缓冲区 64K"</item><item msgid="1342285115665698168">"每个⽇志缓冲区 256K"</item>+ <item>"每个⽇志缓冲区 512K"</item><item msgid="1314234299552254621">"每个⽇志缓冲区 1M"</item><item msgid="3606047780792894151">"每个⽇志缓冲区 4M"</item><item msgid="5431354956856655120">"每个⽇志缓冲区 16M"</item>diff --git a/frameworks/base/packages/SettingsLib/res/values/arrays.xml b/frameworks/base/packages/SettingsLib/res/values/arrays.xml old mode 100644new mode 100755index 920e061..b57115b--- a/frameworks/base/packages/SettingsLib/res/values/arrays.xml+++ b/frameworks/base/packages/SettingsLib/res/values/arrays.xml@@ -122,6 +122,7 @@<string-array name="select_logd_size_values" translatable="false" ><item>32768</item><item>65536</item>+ <item>524288</item><item>262144</item><item>1048576</item><item>4194304</item>diff --git a/system/core/logd/LogBuffer.cpp b/system/core/logd/LogBuffer.cppold mode 100644new mode 100755index 0497a89..5a2a597--- a/system/core/logd/LogBuffer.cpp--- a/system/core/logd/LogBuffer.cpp+++ b/system/core/logd/LogBuffer.cpp@@ -97,14 +97,20 @@ void LogBuffer::init() {static const char global_tuneable[] = "persist.logd.size"; // Settings Appstatic const char global_default[] = "ro.logd.size"; // BoardConfig.mk+ SLOGE("gatsby LogBuffer init");+unsigned long default_size = property_get_size(global_tuneable);+ SLOGE("000 gatsby default_size -> %lu .",default_size);if (!default_size) {+ SLOGE("000 gatsby default_size aaa -> %lu .",default_size);default_size = property_get_size(global_default);+ SLOGE("000 gatsby default_size bbb -> %lu .",default_size);if (!default_size) {default_size = property_get_bool("ro.config.low_ram",BOOL_DEFAULT_FALSE)LOG_BUFFER_MIN_SIZE // 64K: LOG_BUFFER_SIZE; // 256K+ SLOGE("000 gatsby default_size ccc -> %lu .",default_size);}}@@ -116,24 +122,32 @@ void LogBuffer::init() {snprintf(key, sizeof(key), "%s.%s",global_tuneable, android_log_id_to_name(i));+ //getprop persist.logd.sizeunsigned long property_size = property_get_size(key);if (!property_size) {snprintf(key, sizeof(key), "%s.%s",global_default, android_log_id_to_name(i));property_size = property_get_size(key);+ SLOGE("111 gatsby global_tuneable -> %s . android_log_id_to_name(i) -> %s .",global_tuneable,android_log_id_to_name(i)); + SLOGE("111 gatsby property_size -> %lu .",property_size);}if (!property_size) {property_size = default_size;+ SLOGE("2222 gatsby property_size -> %lu .",property_size);}if (!property_size) {+ //256kproperty_size = LOG_BUFFER_SIZE;+ SLOGE("333 gatsby property_size -> %lu .",property_size);}if (setSize(i, property_size)) {+ //64ksetSize(i, LOG_BUFFER_MIN_SIZE);+ SLOGE("444 gatsby property_size -> %lu .",property_size);}}bool lastMonotonic = monotonic;四.Android5.1 抓取系统⽇志脚本 4.1.logger.sh#!/system/bin/shFILE_PATH=/mnt/internal_sd/loggerFILE_PREFIX_KERNLOG=kernlogFILE_PREFIX_MAINLOG=mainlogFILE_PREFIX_RADIOLOG=radiologFILE_PREFIX_PPPDLOG=pppdlog#sleep 30if [ ! -d $FILE_PATH ]thenmkdir -p $FILE_PATHfirename_logfile(){FILE_PREFIX=$1LAST_LAST_LAST_FILE=`busybox find $FILE_PATH/ -name "$FILE_PREFIX-*st"`LAST_LAST_FILE=`busybox find $FILE_PATH/ -name "$FILE_PREFIX-*st"`LAST_FILE=`busybox find $FILE_PATH/ -name "$FILE_PREFIX-*.log"`#change log files nameecho "$LAST_LAST_LAST_FILE $LAST_LAST_FILE $LAST_FILE"rm $LAST_LAST_FILEmv $LAST_LAST_FILE $LAST_LAST_stmv $LAST_FILE $LAST_st}logger_kmsg(){echo "logger $FILE_PREFIX_KERNLOG ..."rename_logfile $FILE_PREFIX_KERNLOGbusybox cat /proc/kmsg > $FILE_PATH/$FILE_PREFIX_KERNLOG-`date +%Y%m%d-%H%M%S`.log}logger_logcat(){echo "logger $FILE_PREFIX_MAINLOG ..."rename_logfile $FILE_PREFIX_MAINLOGlogcat -b main -b radio -b system -v time -f $FILE_PATH/$FILE_PREFIX_MAINLOG-`date +%Y%m%d-%H%M%S`.log }logger_pppd(){echo "logger $FILE_PREFIX_PPPDLOG ..."#rename_logfile $FILE_PREFIX_PPPDLOGlogcat -v time -s pppd > $FILE_PATH/$FILE_PREFIX_PPPDLOG-`date +%Y%m%d-%H%M%S`.log}logger_radio(){echo "logger $FILE_PREFIX_RADIOLOG ..."# rename_logfile $FILE_PREFIX_RADIOLOGlogcat -v time -b radio -f $FILE_PATH/$FILE_PREFIX_RADIOLOG-`date +%Y%m%d-%H%M%S`.log}case "$1" inkernel)logger_kmsg;;android)logger_logcat;;pppd)logger_pppd;;radio)logger_radio;;*)print "error argument, only for kernel, android, radio,pppd\n";;esac4.2.device\rockchip\common\init.rk30board.rcservice logger_kernel /system/bin/logger.sh kerneluser rootgroup rootdisabledoneshotservice logger_android /system/bin/logger.sh androiduser rootgroup rootdisabledoneshotservice logger_radio /system/bin/logger.sh radiouser rootgroup rootdisabledoneshotservice logger_pppd /system/bin/logger.sh pppduser rootgroup rootdisabledoneshoton property:persist.sys.logger=1start logger_kernelstart logger_androidstart logger_radiostart logger_pppd4.3. a.最⼤保存5份⽂件 b.满5份之后删除最旧的⼀份c.Notepad++ 下编辑-⽂档格式转换-转换为UNIX格式 test.shcount=5for i in `seq $(($count+1))`doecho "i is $i"if [ ! -f "log/kmsg_$i.log" ]; thenecho "i is break!"breakfidoneif [ $i -eq $(($count+1)) ]; thenrm -rf log/kmsg_1.logi=$countfor j in `seq $(($count-1))`doecho "log/kmsg_$(($j+1)).log log/kmsg_$j.log"mv log/kmsg_$(($j+1)).log log/kmsg_$j.logdonefitouch log/kmsg_$i.logecho `date +%Y.%m.%d.%H.%M.%S` > log/kmsg_$i.log kmsg.sh#Save five files as max.count=5for i in `seq $(($count+1))`do#echo "i is $i"if [ ! -f "/data/log/kmsg_$i.log" ]; thenbreakfidoneif [ $i -eq $(($count+1)) ]; thenrm /data/log/kmsg_1.logi=$countfor j in `seq $(($count-1))`do#echo "/data/log/kmsg_$(($j+1)).log /data/log/kmsg_$j.log" mv /data/log/kmsg_$(($j+1)).log /data/log/kmsg_$j.logdoneficat /proc/kmsg > /data/log/kmsg_$i.log#cat /proc/kmsg > /data/log/kmsg_`date +%Y%m%d%H%M%S`.log 。

【最新精选】android抓取log方法

Android日志系统提供了记录和查看系统调试信息的功能。

日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过 logcat 命令来查看和使用.使用logcat命令你可以用 logcat 命令来查看系统日志缓冲区的内容:[adb] logcat [<option>] ... [<filter-spec>] ...复制代码请查看Listing of logcat Command Options ,它有对logcat命令有详细的描述 .你也可以在你的电脑或运行在模拟器/设备上的远程adb shell端来使用logcat命令,也可以在你的电脑上查看日志输出。

$ adb logcat复制代码你也这样使用:# logcat复制代码过滤日志输出每一个输出的Android日志信息都有一个标签和它的优先级.日志的标签是系统部件原始信息的一个简要的标志。

(比如:“View”就是查看系统的标签).优先级有下列集中,是按照从低到高顺利排列的:V — Verbose (lowest priority)D — DebugI — InfoW — WarningE — ErrorF — FatalS — Silent (highest priority, on which nothing is ever printed)在运行logcat的时候在前两列的信息中你就可以看到 logcat 的标签列表和优先级别,它是这样标出的:<priority>/<tag> .下面是一个logcat输出的例子,它的优先级就似乎I,标签就是1.ActivityManage: I/ActivityManager( 585): Starting activity: Intent{ action=android.intent.action...}复制代码为了让日志输出能体现管理的级别,你还可以用过滤器来控制日志输出,过滤器可以帮助你描述系统的标签等级.过滤器语句按照下面的格式描tag:priority ... , tag 表示是标签,priority 是表示标签的报告的最低等级. 从上面的tag的中可以得到日志的优先级. 你可以在过滤器中多次写tag:priority .这些说明都只到空白结束。

Android TombstoneCrash的log分析和定位 -

Android Tombstone/Crash的log分析和定位有一句话叫做常在河边走,哪有不湿鞋。

我们这些研究和开发Android的工程师正应了这句话,相必大家在调试的时候经常会遇到这么个东西吧*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***Build fingerprint: 'XXXXXXXXX'pid: 1658, tid: 13086 >>> system_server <<<signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 64696f7er0 00000000 r1 00000001 r2 ad12d1e8 r3 7373654dr4 64696f72 r5 00000406 r6 00974130 r7 40d14008r8 4b857b88 r9 4685adb4 10 00974130 fp 4b857ed8ip 00000000 sp 4b857b50 lr afd11108 pc ad115ebc cpsr 20000030d0 4040000040000000 d1 0000004200000003d2 4e72cd924285e370 d3 00e81fe04b1b64d8d4 3fbc71c7009b64d8 d5 3fe999999999999ad6 4010000000000000 d7 4000000000000000d8 4000000000000000 d9 0000000000000000d10 0000000000000000 d11 0000000000000000d12 0000000000000000 d13 0000000000000000d14 0000000000000000 d15 0000000000000000scr 80000012#00 pc 000108d8 /system/lib/libc.so#01 pc 0003724c /system/lib/libxvi020.so#02 pc 0000ce02 /system/lib/libxvi020.so#03 pc 0000d672 /system/lib/libxvi020.so#04 pc 00010cce /system/lib/libxvi020.so#05 pc 00004432 /system/lib/libwimax_jni.so#06 pc 00011e74 /system/lib/libdvm.so#07 pc 0004354a /system/lib/libdvm.so#08 pc 00017088 /system/lib/libdvm.so#09 pc 0001c210 /system/lib/libdvm.so#10 pc 0001b0f8 /system/lib/libdvm.so#11 pc 00059c24 /system/lib/libdvm.so#12 pc 00059e3c /system/lib/libdvm.so#13 pc 0004e19e /system/lib/libdvm.so#14 pc 00011b94 /system/lib/libc.so#15 pc 0001173c /system/lib/libc.socode around pc:ad115e9c 4620eddc bf00bd70 0001736e 0001734ead115eac 4605b570 447c4c0a f7f44620 e006edc8ad115ebc 42ab68e3 68a0d103 f7f42122 6864edd2ad115ecc d1f52c00 44784803 edbef7f4 bf00bd70ad115edc 00017332 00017312 2100b51f 46682210code around lr:afd110e8 e2166903 1a000018 e5945000 e1a02004afd110f8 e2055a02 e1a00005 e3851001 ebffed92afd11108 e3500000 13856002 1a000001 ea000009afd11118 ebfffe50 e1a01004 e1a00006 ebffed92afd11128 e1a01005 e1550000 e1a02006 e3a03000stack:4b857b10 40e43be84b857b14 008572804b857b18 000000004b857b1c 034e89684b857b20 ad118ce9 /system/lib/libnativehelper.so4b857b24 000000024b857b28 00000406.....初一看到直接崩溃,我的个妈,这么一大坨,啥玩意啊,完全搞不懂,没有头绪撒。

Android 程序中增加LOGCAT,LOG

最近在研究Android 2.3.3源代码的C/C++层,需要对代码进行一些调试,但是奇怪的是,直接添加LOGD("XXXXXXXX");,使用logcat却看不到任何输出,换成LOGI、LOGV、LOGW、LOGE也没有效果。于是在网上查找解决方法,经过几次试验,终于找到了,现在贴到下面备忘:
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "ProjectName", __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "ProjectName", __VA_ARGS__)
ANDROID_LOG_DEFAULT,
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
第三步:这样就可以使用了:LOGD("我要看到的调试信息^_^");
这样,在logcat端看到的输出是:
D/keymatch( 32):我要看到的调试信息^_^
如果想改变输出中的各项内容,可以参考相应颜色的标示,比如,如果想定义LOGE,就可以把上面的ANDROID_LOG_DEBUG改成ANDROID_LOG_ERROR,同理,LOGI神马的也都以此类推:
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT,
这样写完以后,如果直接编译,就会报 __android_log_write 方法undefined.
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档