精华内容
下载资源
问答
  • Logcat日志分析

    2018-12-10 17:08:34
    Logcat日志分析 2016年08月01日 17:32:39 Oh乌鸦呀 阅读数:3103   一,Bug出现了, 需要“干掉”它  bug一听挺吓人的,但是只要你懂了,android里的bug是很好解决的,因为android里提供了LOG机制,具体的...

    Logcat日志分析

    2016年08月01日 17:32:39 Oh乌鸦呀 阅读数:3103

     

    一,Bug出现了, 需要“干掉”它 

    bug一听挺吓人的,但是只要你懂了,android里的bug是很好解决的,因为android里提供了LOG机制,具体的底层代码,以后在来分析,只要你会看bug,

    android里应用开发也就很简单了。

    那我们先来看看android里的ANR,怎么出现ANR呢,很简单。

              # adb shell

              # cd data/app

              # monkey   -p  com.xxx.xxx   -v   3000      (com.xxx.xxx是你应用程序的包名,如果想知道monkey详细用法,执行  monkey  help  )

             实际上很多优秀android应用都会出现ANR,比如UC浏览器,360等等,如果你有兴趣可以回去试试,

             这样,ANR出现了。 开始做修改准备工作  ,得到log文件。

    有人问log文件在哪儿?
    一般在/data/log下面(但是真机才有的)。你可以通过执行命令adb shell进去看看,用pull把log文件拉到你的电脑里
     
    好,得到log文件了,我们就准备开始工作了 。 我将详细的log文件上传到附件供大家参考。

    下载地址为  http://download.csdn.net/detail/andy_android/3785393

     

    二,Log的种类

              android.util.Log常用的方法有以下六个:Log.v() Log.d() Log.i() Log.w() , Log.e()以及Log.a() (android 4.0新增加的)。根据首字母对应             VERBOSE,DEBUG,INFO,WARN,ERROR,Assert。

              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错误,这里仅显示红色的错误信息,这些错误就需要我们认真的分析,查看栈的信息了。

             6    Log.a为4.0新增加的。

              启动Eclipse,打开DDMS大家可以在LogCat里看见(前提是android 4.0的ADT)

    三,如何分析和研究Log文件,如何看日志信息 。Log在android中的地位非常重要,要是作为一个android程序员不能过分析log这关,算是android没有入门吧。 下面我们就来说说如何处理log文件。

    Log分为Fatal和ANR

    什么时候会有Log文件的产生?
    Log的产生大家都知道, 大家也都知道通过DDMS来看log(这个就不用说了),但什么时候会产生log文件呢?一般在如下几种情况会产生log文件。 
    1,程序异常退出,uncausedexception      (Fatal)
    2,程序强制关闭,ForceClosed (简称FC)       (Fatal)
    3,程序无响应,ApplicationNo Response(简称ANR)

        ANR出现的情况有以下两种

          A  界面操作按钮的点击等待响应时间超过5秒

          B  HandleMessage回调函数执行超过10秒,BroadcasterReciver里的onRecive()方法处理超过10秒

    4,手动生成。


    拿到一个日志文件,要分成多段来看。log文件很长,其中包含十几个小单元信息,但不要被吓到,事实上他主要由三大块儿组成 。

    1,系统基本信息,包括 内存,CPU,进程队列,虚拟内存 , 垃圾回收等信息 。------MEMORY INFO (/proc/meminfo) ------
    ------CPU INFO (top -n 1 -d 1 -m 30 -t) ------
    ------PROCRANK (procrank) ------
    ------VIRTUAL MEMORY STATS (/proc/vmstat) ------
    ------VMALLOC INFO (/proc/vmallocinfo) ------

    格式如下:
    ------MEMORY INFO (/proc/meminfo) ------
    MemTotal:        347076 kB
    MemFree:          56408 kB
    Buffers:           7192 kB
    Cached:          104064 kB
    SwapCached:           0 kB
    Active:          192592 kB
    Inactive:         40548 kB
    Active(anon):    129040 kB
    Inactive(anon):    1104 kB
    Active(file):     63552 kB
    Inactive(file):   39444 kB
    Unevictable:       7112 kB
    Mlocked:              0kB
    SwapTotal:            0 kB
    SwapFree:             0 kB
    Dirty:               44kB
    Writeback:            0 kB
    AnonPages:       129028 kB
    Mapped:           73728 kB
    Shmem:             1148kB
    Slab:             13072kB
    SReclaimable:      4564 kB
    SUnreclaim:        8508 kB
    KernelStack:       3472 kB
    PageTables:       12172 kB
    NFS_Unstable:         0 kB
    Bounce:               0kB
    WritebackTmp:         0 kB
    CommitLimit:     173536 kB
    Committed_AS:   7394524 kB
    VmallocTotal:    319488 kB
    VmallocUsed:      90752 kB
    VmallocChunk:    181252 kB


    2,事件信息, 也是我们主要分析的信息 。
    ------VMALLOC INFO (/proc/vmallocinfo) ------
    ------EVENT INFO (/proc/vmallocinfo) ------

    格式如下:
    ------SYSTEM LOG (logcat -b system -v time -d *:v) ------
    01-1516:41:43.671 W/PackageManager( 2466): Unknown permissioncom.wsomacp.permission.PROVIDER in package com.android.mms
    01-1516:41:43.671 I/ActivityManager( 2466): Force stopping packagecom.android.mms uid=10092
    01-1516:41:43.675 I/UsageStats( 2466): Something wrong here, didn't expectcom.sec.android.app.twlauncher to be paused
    01-1516:41:44.108 I/ActivityManager( 2466): Start proccom.sec.android.widgetapp.infoalarm for servicecom.sec.android.widgetapp.infoalarm/.engine.DataService: pid=20634uid=10005 gids={3003, 1015, 3002}
    01-1516:41:44.175 W/ActivityManager( 2466): Activity pause timeout forHistoryRecord{48589868com.sec.android.app.twlauncher/.Launcher}
    01-1516:41:50.864 I/KeyInputQueue( 2466): Input event
    01-1516:41:50.866 D/KeyInputQueue( 2466): screenCaptureKeyFlag setting0
    01-1516:41:50.882 I/PowerManagerService( 2466): Ulight 0->7|0
    01-1516:41:50.882 I/PowerManagerService( 2466): Setting target 2: cur=0.0target=70 delta=4.6666665 nominalCurrentValue=0
    01-1516:41:50.882 I/PowerManagerService( 2466): Scheduling lightanimator!
    01-1516:41:51.706 D/PowerManagerService( 2466): enableLightSensortrue
    01-1516:41:51.929 I/KeyInputQueue( 2466): Input event
    01-1516:41:51.933 W/WindowManager( 2466): No focus window, dropping:KeyEvent{action=0 code=26 repeat=0 meta=0 scancode=26mFlags=9}



    3,虚拟机信息, 包括进程的,线程的跟踪信息,这是用来跟踪进程和线程具体点的好地方。 
    ------VM TRACES JUST NOW (/data/anr/traces.txt.bugreport: 2011-01-1516:49:02) ------
    ------VM TRACES AT LAST ANR (/data/anr/traces.txt: 2011-01-15 16:49:02)------


    格式如下:
    -----pid 21161 at 2011-01-15 16:49:01 -----
    Cmdline: com.android.mms

    DALVIKTHREADS:
    "main"prio=5 tid=1 NATIVE
      |group="main" sCount=1 dsCount=0 s=N obj=0x4001d8d0self=0xccc8
      |sysTid=21161 nice=0 sched=0/0 cgrp=default handle=-1345017808
      |schedstat=( 4151552996 5342265329 10995 )
      atandroid.media.MediaPlayer._reset(Native Method)
      atandroid.media.MediaPlayer.reset(MediaPlayer.java:1218)
      atandroid.widget.VideoView.release(VideoView.java:499)
      atandroid.widget.VideoView.access$2100(VideoView.java:50)
      atandroid.widget.VideoView$6.surfaceDestroyed(VideoView.java:489)
      atandroid.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:572)
      atandroid.view.SurfaceView.updateWindow(SurfaceView.java:476)
      atandroid.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:206)
      atandroid.view.View.dispatchDetachedFromWindow(View.java:6082)
      atandroid.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1156)
      atandroid.view.ViewGroup.removeAllViewsInLayout(ViewGroup.java:2296)
      atandroid.view.ViewGroup.removeAllViews(ViewGroup.java:2254)
      atcom.android.mms.ui.SlideView.reset(SlideView.java:687)
      atcom.android.mms.ui.SlideshowPresenter.presentSlide(SlideshowPresenter.java:189)
      atcom.android.mms.ui.SlideshowPresenter$3.run(SlideshowPresenter.java:531)
      atandroid.os.Handler.handleCallback(Handler.java:587)
      atandroid.os.Handler.dispatchMessage(Handler.java:92)
      atandroid.os.Looper.loop(Looper.java:123)
      atandroid.app.ActivityThread.main(ActivityThread.java:4627)
      atjava.lang.reflect.Method.invokeNative(Native Method)
      atjava.lang.reflect.Method.invoke(Method.java:521)
      atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
      atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
      atdalvik.system.NativeStart.main(NativeMethod)

    ---------------------------------------------------------------------------------------------------------------------------------------
    闲话少说,我总结了观察log文件的基本步骤。

    1,如果是ANR问题, 则搜索“ANR”关键词。 快速定位到关键事件信息 。
    2,如果是ForceClosed和其它异常退出信息,则搜索"Fatal"关键词,快速定位到关键事件信息 。
    3,定位到关键事件信息后, 如果信息不够明确的,再去搜索应用程序包的虚拟机信息,查看具体的进程和线程跟踪的日志,来定位到代码。 

    用这种方法,出现问题,根本不需要断点调试, 直接定位到问题,屡试不爽 。 
    下面,我们就开始来分析这个例子的log。

    打开log文件, 由于是ANR错误,因此搜索"ANR",为何要加空格呢,你加上和去掉比较一下就知道了 。可以屏蔽掉不少保存到anr.log文件的无效信息。 

    定位到关键的事件信息如下:
    01-1516:49:02.433 E/ActivityManager( 2466): ANR in com.android.mms(com.android.mms/.ui.SlideshowActivity)
    01-1516:49:02.433 E/ActivityManager( 2466): Reason:keyDispatchingTimedOut
    01-1516:49:02.433 E/ActivityManager( 2466): Load: 0.6 / 0.61 / 0.42
    01-1516:49:02.433 E/ActivityManager( 2466): CPU usage from 1337225ms to57ms ago:
    01-1516:49:02.433 E/ActivityManager( 2466):   sensorserver_ya:8% = 0% user + 8% kernel / faults: 40 minor
    ......


    01-1516:49:02.433 E/ActivityManager( 2466):  -com.android.mms:0% = 0% user + 0% kernel
    01-1516:49:02.433 E/ActivityManager( 2466):  -flush-179:8: 0% =0% user + 0% kernel
    01-1516:49:02.433 E/ActivityManager( 2466): TOTAL: 25% = 10% user + 14%kernel + 0% iowait + 0% irq + 0% softirq
    01-1516:49:02.436 I/        ( 2466):dumpmesg >"/data/log/dumpstate_app_anr.log"


    我们用自然语言来描述一下日志,这也算是一种能力吧。 
    01-1516:49:02.433 E/ActivityManager( 2466): ANR in com.android.mms(com.android.mms/.ui.SlideshowActivity)
    翻译:在16:49分2秒433毫秒的时候ActivityManager(进程号为2466)发生了如下错误:com.android.mms包下面的.ui.SlideshowActivity无响应。

    01-1516:49:02.433 E/ActivityManager( 2466): Reason:keyDispatchingTimedOut
    翻译:原因,keyDispatchingTimeOut-按键分配超时 

    01-1516:49:02.433 E/ActivityManager( 2466): Load: 0.6 / 0.61 /0.42
    翻译:5分钟,10分钟,15分钟内的平均负载分别为:0.6, 0.61 ,0.42

    在这里我们大概知道问题是什么了,结合我们之前的操作流程,我们知道问题是在点击按钮某时候可能处理不过来按钮事件,导致超时无响应。那么现在似乎已经可以进行工作了 。我们知道Activity中是通过重载dispatchTouchEvent(MotionEventev)来处理点击屏幕事件  。然后我们可以顺藤摸瓜,一点点分析去查找原因 。但这样够了么 ?
    其实不够, 至少我们不能准确的知道到底问题在哪儿 , 只是猜测,比如这个应用程序中,我就在顺藤摸瓜的时候发现了多个IO操作的地方都在主线程中,可能引起问题,但不好判断到底是哪个  ,所以我们目前掌握的信息还不够。 

    于是我们再分析虚拟机信息, 搜索“DalvikThread”关键词,快速定位到本应用程序的虚拟机信息日志,如下:
    -----pid 2922 at 2011-01-13 13:51:07 -----
    Cmdline: com.android.mms

    DALVIKTHREADS:
    "main"prio=5 tid=1 NATIVE
      |group="main" sCount=1 dsCount=0 s=N obj=0x4001d8d0self=0xccc8
      |sysTid=2922 nice=0 sched=0/0 cgrp=default handle=-1345017808
      |schedstat=( 3497492306 15312897923 10358 )
      atandroid.media.MediaPlayer._release(Native Method)
      atandroid.media.MediaPlayer.release(MediaPlayer.java:1206)
      atandroid.widget.VideoView.stopPlayback(VideoView.java:196)
      atcom.android.mms.ui.SlideView.stopVideo(SlideView.java:640)
      atcom.android.mms.ui.SlideshowPresenter.presentVideo(SlideshowPresenter.java:443)
      atcom.android.mms.ui.SlideshowPresenter.presentRegionMedia(SlideshowPresenter.java:219)
      atcom.android.mms.ui.SlideshowPresenter$4.run(SlideshowPresenter.java:516)
      atandroid.os.Handler.handleCallback(Handler.java:587)
      atandroid.os.Handler.dispatchMessage(Handler.java:92)
      atandroid.os.Looper.loop(Looper.java:123)
      atandroid.app.ActivityThread.main(ActivityThread.java:4627)
      atjava.lang.reflect.Method.invokeNative(Native Method)
      atjava.lang.reflect.Method.invoke(Method.java:521)
      atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
      atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
      atdalvik.system.NativeStart.main(Native Method)

    "BinderThread #3" prio=5 tid=11 NATIVE
      |group="main" sCount=1 dsCount=0 s=N obj=0x4837f808self=0x242280
      |sysTid=3239 nice=0 sched=0/0 cgrp=default handle=2341032
      |schedstat=( 32410506 932842514 164 )
      atdalvik.system.NativeStart.run(Native Method)

    "AsyncQueryWorker"prio=5 tid=9 WAIT
      |group="main" sCount=1 dsCount=0 s=N obj=0x482f4b80self=0x253e10
      |sysTid=3236 nice=0 sched=0/0 cgrp=default handle=2432120
      |schedstat=( 3225061 26561350 27 )
      atjava.lang.Object.wait(Native Method)
      -waiting on <0x482f4da8> (a android.os.MessageQueue)
      atjava.lang.Object.wait(Object.java:288)
      atandroid.os.MessageQueue.next(MessageQueue.java:146)
      atandroid.os.Looper.loop(Looper.java:110)
      atandroid.os.HandlerThread.run(HandlerThread.java:60)

    "Thread-9"prio=5 tid=8 WAIT
      |group="main" sCount=1 dsCount=0 s=N obj=0x4836e2b0self=0x25af70
      |sysTid=2929 nice=0 sched=0/0 cgrp=default handle=2370896
      |schedstat=( 130248 4389035 2 )
      atjava.lang.Object.wait(Native Method)
      -waiting on <0x4836e240> (a java.util.ArrayList)
      atjava.lang.Object.wait(Object.java:288)
      atcom.android.mms.data.Contact$ContactsCache$TaskStack$1.run(Contact.java:488)
      atjava.lang.Thread.run(Thread.java:1096)

    "BinderThread #2" prio=5 tid=7 NATIVE
      |group="main" sCount=1 dsCount=0 s=N obj=0x482f8ca0self=0x130fd0
      |sysTid=2928 nice=0 sched=0/0 cgrp=default handle=1215968
      |schedstat=( 40610049 1837703846 195 )
      atdalvik.system.NativeStart.run(Native Method)

    "BinderThread #1" prio=5 tid=6 NATIVE
      |group="main" sCount=1 dsCount=0 s=N obj=0x482f4a78self=0x128a50
      |sysTid=2927 nice=0 sched=0/0 cgrp=default handle=1201352
      |schedstat=( 40928066 928867585 190 )
      atdalvik.system.NativeStart.run(Native Method)

    "Compiler"daemon prio=5 tid=5 VMWAIT
      |group="system" sCount=1 dsCount=0 s=N obj=0x482f1348self=0x118960
      |sysTid=2926 nice=0 sched=0/0 cgrp=default handle=1149216
      |schedstat=( 753021350 3774113668 6686 )
      atdalvik.system.NativeStart.run(Native Method)

    "JDWP"daemon prio=5 tid=4 VMWAIT
      |group="system" sCount=1 dsCount=0 s=N obj=0x482f12a0self=0x132940
      |sysTid=2925 nice=0 sched=0/0 cgrp=default handle=1255680
      |schedstat=( 2827103 29553323 19 )
      atdalvik.system.NativeStart.run(Native Method)

    "SignalCatcher" daemon prio=5 tid=3 RUNNABLE
      |group="system" sCount=0 dsCount=0 s=N obj=0x482f11e8self=0x135988
      |sysTid=2924 nice=0 sched=0/0 cgrp=default handle=1173688
      |schedstat=( 11793815 12456169 7 )
      atdalvik.system.NativeStart.run(Native Method)

    "HeapWorker"daemon prio=5 tid=2 VMWAIT
      |group="system" sCount=1 dsCount=0 s=N obj=0x45496028self=0x135848
      |sysTid=2923 nice=0 sched=0/0 cgrp=default handle=1222608
      |schedstat=( 79049792 1520840200 95 )
      atdalvik.system.NativeStart.run(Native Method)

    -----end 2922 -----

    每一段都是一个线程,当然我们还是看线程号为1的主线程了。通过分析发现关键问题是这样:
      atcom.android.mms.ui.SlideshowPresenter$3.run(SlideshowPresenter.java:531)
    定位到代码:
    mHandler.post(newRunnable() {
                      public void run() {
                          try {
                              presentRegionMedia(view,(RegionMediaModel) model, dataChanged);
                          } catch (OMADRMException e) {
                              Log.e(TAG, e.getMessage(), e);
                              Toast.makeText(mContext,
                                     mContext.getString(R.string.insufficient_drm_rights),
                                     Toast.LENGTH_SHORT).show();
                          } catch (IOException e){
                              Log.e(TAG, e.getMessage(), e);
                              Toast.makeText(mContext,
                                     mContext.getString(R.string.insufficient_drm_rights),
                                     Toast.LENGTH_SHORT).show();
                          

                          }
                      }

    很清楚了,Handler.post方法之后执行时间太长的问题。 继续看presentRegionMedia(view,(RegionMediaModel) model, dataChanged);方法, 发现最终是调用的framework中MediaPlayer.stop方法。
    至此,我们的日志分析算是告一段落。 可以开始思考解决办法了。 

    四,如何通过Handler或者多线程来解决某操作执行时间过程的问题。结合上面的分析,我们知道问题似乎是线程队列中某个操作presentRegionMedia(view,(RegionMediaModel) model, dataChanged);执行时间太长所导致的界面无响应。 因此比较典型的做法当然是控制线程队列 。在这里我们不得不提一下Handler  . 

    Handler在Android中是什么样的作用和地位呢?

    1. 线程之间消息传递 ,通过sendMessage方法 。我们通常用来后台子线程向主线程传递消息,主线程接到通知之后做更新界面等操作。

    2. 通过管理消息队列(MessageQueue)来安排计划任务。 这个常常会被人忽略,很多书上也没有提到这个作用。

    Handler这个单词中文意思是管理者,处理者的意思。 通过这个意思顾名思义,我们知道这个对象就是个操作对象。那么要操作谁呢?

    当然是消息队列(MessageQueue)。Android消息队列类似于Win32队列设计。 都是采用线性结构,先进先出 。其实在智能手机平台很久以前就用这种消息结构了 。比如Palm ,只不过Palm是整个进程共享一个消息队列,而Android是线程为单位的队列罢了。

    那么是否每个线程或者子线程都有消息队列呢?

    很遗憾,不是的,也没有必要。 在Android中,只有使用了Looper的线程才有消息队列。 当然如果你要简单建立一个有消息队列的线程也很方便,直接使用HandlerThread即可,这个类继承于Thread类。怎么用我就不多说了吧 。你懂的 !

    Handler有两种方式来操作消息队列。

    一种是通过sendMessage(Message)方法,发送消息体

    另一种是通过post(Runnable)方法 , 发送Runnable对象 。

    注意:这点请注意,虽然发送方法含参不同 , 但他们使用的是同一个消息队列。 我记得Mars的视频教程上说有两个队列,一个是消息队列,一个是线程队列。 这种说法是错误的 。事实上只有一个消息队列,没有所谓的线程队列。 当然了 ,post(Runnable)也没有启动新的线程,仍然是在当前线程。

    注意:还有一种说法,说Handler对象在主线程,这种说法也是错误的, 准确的说是在产生他的线程中 。 虽然常常我们是在主线程产生他的。

    那么我们要在Android建立多线程程序该如何做呢?很简单,就是Java的多线程方式。要么实现Runnable接口,要么继承Thread类。

    关于线程同步,线程锁定,线程异步,线程池 这些概念也是一样的 。 我就不累述了。

     

    好了,经过一点儿简单的介绍,我们有了一些Handler的基础,现在开始回到我们的问题开始来分析:

    mHandler.post(newRunnable() {
                      public void run() {
                          try {
                              presentRegionMedia(view,(RegionMediaModel) model, dataChanged);
                          } catch (OMADRMException e) {
                              Log.e(TAG, e.getMessage(), e);
                              Toast.makeText(mContext,
                                     mContext.getString(R.string.insufficient_drm_rights),
                                     Toast.LENGTH_SHORT).show();
                          } catch (IOException e){
                              Log.e(TAG, e.getMessage(), e);
                              Toast.makeText(mContext,
                                     mContext.getString(R.string.insufficient_drm_rights),
                                     Toast.LENGTH_SHORT).show();
                          

                          }
                      }
     

    从上面这段代码中,我们可以看出,在做播放器控制按钮(比如播放,暂停,停止)等操作的时候, 是通过Handler.post(Runnable)来放到消息队列中, 排序来处理 。 那么之所以这里出现了无响应,很有可能是因为某一项控制操作太耗时或者耗资源。 这时候又接收到新的要处理的消息,就会处理不过来了。 因此我试图让队列中同时只有一个控制播放器按钮的任务在。 我对代码做了如下改动:

    Runnabler = new Runnable(){
                      public void run() {
                          try {
                              presentRegionMedia(view,(RegionMediaModel) model, dataChanged);
                          } catch (OMADRMException e) {
                              Log.e(TAG, e.getMessage(), e);
                              Toast.makeText(mContext,
                                     mContext.getString(R.string.insufficient_drm_rights),
                                     Toast.LENGTH_SHORT).show();
                          } catch (IOException e){
                              Log.e(TAG, e.getMessage(), e);
                              Toast.makeText(mContext,
                                     mContext.getString(R.string.insufficient_drm_rights),
                                     Toast.LENGTH_SHORT).show();
                          

                          }
                      }
     

    mHandler.removeCallbacks(r);

    mHandler.post(r);

    代码慢慢看,思路很简单:其实就是在postRunnable之前先清除队列中已存的相同Runnable实例。 这样可以保证同时队列中只有一个操作在处理 。

     

    很遗憾,不生效。:(,改动之后,问题依然存在,欲哭无泪 。

     

    再来,我将整个模式改为message再试试,核心代码如下 :

    if(mHandler.hasMessages(MEDIA_PLAY_WHAT_MESSAGEFLAG))

    {

    return ;

    }

    Messagemsg = mHandler.obtainMessage() ;

    msg.what= this.MEDIA_PLAY_WHAT_MESSAGEFLAG ;

    msg.obj= mMeidaPlayMessageObj ;

    mHandler.sendMessageDelayed(msg,1000) ;

     

    代码慢慢看,思路也很简单,通过发消息的方式, 先检测如果有相关消息队列,就直接跳出函数,不做任何处理,否则延迟一秒后再向队列发送一条消息 。

     

    为何我用了1秒这个这么长的时间呢,因为这么长时间如果都处理不了,那就不是压力测试的问题了,而是方法本身的问题了,这也是通过排除法来试图排除是因为点击屏幕过快产生的问题。

    编译,再试 ,很不辛,又不生效,不幸被我猜中了 。 仰望苍天 !

     

    现在问题很明显了:不是压力测试时候点击过快导致的ANR,而是某些方法本身有问题。

    通过之前我们的日志

    -----pid 2922 at 2011-01-13 13:51:07 -----
    Cmdline: com.android.mms

    DALVIKTHREADS:
    "main"prio=5 tid=1 NATIVE
      |group="main" sCount=1 dsCount=0 s=N obj=0x4001d8d0self=0xccc8
      |sysTid=2922 nice=0 sched=0/0 cgrp=default handle=-1345017808
      |schedstat=( 3497492306 15312897923 10358 )
      atandroid.media.MediaPlayer._release(Native Method)
      atandroid.media.MediaPlayer.release(MediaPlayer.java:1206)
      atandroid.widget.VideoView.stopPlayback(VideoView.java:196)
      atcom.android.mms.ui.SlideView.stopVideo(SlideView.java:640)
     

    很容易就知道了问题出在每次执行完了MediaPlayer.stop()方法调用之后会调用release()来释放播放器资源。 而这个方法中又死在了_release()方法上。 这是一个Native方法。

    因此,真相大白 ,问题是在Framework层的MediaPlayer调用的Native方法_release()上。

    展开全文
  • logcat日志分析

    2020-05-22 16:54:02
    1、Android日志系统提供了记录和查看系统调试信息的功能,日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来查看和使用。 2、logca 日志开头: 1....... beginning of xxx 3...

        一、简介:
            1、Android日志系统提供了记录和查看系统调试信息的功能,日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来查看和使用。
            
            2、logca 日志开头:
            1....... beginning of xxx
            
            
            3、开发者选项,有一个选项叫做“日志记录器缓冲区大小”,默认是256K,日志是循环写入环形缓冲区的,在通常情况下,写满时最旧的日志会被删除以给新输出的日志留内存空间。
            
        二、logcat缓冲区
            
            Android log 输出量巨大,特别是通信系统的log,因此,Android把log输出到不同的缓冲区中,目前定义了四个log缓冲区:
                
                Radio : 输出通信系统的log,如:WiFi,蓝牙,3/4/5G,GPS,NFC等
                System: 输出系统组件的log,权限比较高,如:调用相机,调用录制,调用麦克风等
                Events: 输出event模块的log,event翻译过来就是事件,如:通过手指点击屏幕的某一处地方,称为点击事件;通过按电源或者音量加减等
                Main:    所有java层的log,(不属于上面3层的log)
                
            如果测试APP,需要输出Main,命令:adb logcat -b radio,adb logcat 默认抓取Main
            
        三、日志文件分析
            
             adb logcat -v time > logcat.txt
            
            输出的日志格式如下所示:
            
                
                
            由五部分组成:
            
                1、写下日志的时间,如上中 “05-22 12:27:15.370”
                
                2、优先级,在Android 中,日志的优先级从低到高分成以下几种:
                
                    V ---Verbose(啰嗦,最低级别,开发调试中的一些详细信息,仅在开发中使用,不可在发布产品上打开)
                    D ---Debug(调试,用于调试的信息,可以在发布产品中关闭,比较常见)
                    I ---Info(信息,一般提示性的消息)
                    W ---Warning(警告)
                    E ---Error(错误,已经出现可影响运行的错误,比如应用crash时输出的日志)
                    
                3、标签(tag),标明日志发起者和方便日志的过滤筛选,如上中“libTGL”
                
                4、PID(进程ID),如上中 “1438”
                
                5、正文,本日志的主体内容
            
        四、常见问题日志查找(抓取的日志中需要有“方法调用栈”)
        
            1、crash问题(程序崩溃,弹出某某程序停止运行框)

                                      
            
                在日志中搜索“FATAL EXCEPTION” ,发现 优先级为 E,下面的都是错误日志
            
            2、ANR问题
                
                ANR 全名 Application Not Responding,也就是应用无响应,当操作在一段时间内系统无法处理时,系统层面会弹出右图那样的ANR 对话框。

     

                    


                
                    1.为用户在主线程长时间被阻塞时提供处理交互,提高用户体验
                    2.Android系统一种自身检测机制

     


                    
                在日志中搜索 “ANR in” ,发现 优先级为 E,下面的都是错误日志,但是下面说的都是一下 发生ANR 前和发生后 CPU 的情况;在“ANR in” 的上一行日志 “wrote stack trance to '/data/anr/traces.txt'” ----------这行日志说明,系统把“方法调用栈”的日志写在了traces.txt里
                
                打开 traces.txt 后,发现时间和anr发生的时间不对应,是因为:两份日志是处于不同的模块,导致有时间上的差异,差异在几秒内;但是traces日志有一个特点,他只会保存最新的一份报错的日志,如果有多次报错,会被覆盖。
                
                这里可以使用的“dropbox”,文件路径在 “/data/system/dropbox”,在此目录中,如果是“SYSTEM_BOOT”开头,为系统启动的日志,“data_app”开头的,为手动安装的第三方的日志,里面gz结尾的压缩包文件,内容已经有了anr或者crash的 logcat日志和 方法调用栈 日志。(注释:一个anr一个文件)

    展开全文
  • App logcat日志分析

    2020-02-23 22:00:06
    文章目录logcat日志文件缓冲区 logcat日志文件 android日志系统提供了记录和查看系统调试信息的功能,日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来查看和使用,命令为: adb ...

    logcat日志文件

    android日志系统提供了记录和查看系统调试信息的功能,日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来查看和使用,命令为:

    adb logcat [<option>]...[<fiter-spec>]..
    

    开发者选项中有个叫日志记录缓冲区大小,默认是256k,也就是超过了256k就要清理掉旧数据

    那么缓冲区是如何定义的

    缓冲区

    由于logcat输出量巨大,特别是信息系统的log,因此,android把log输出到不同的缓冲区,目前定义了4个缓冲区:
    1、radio:输出通信系统的log(手机里与通信相关的,例如wifi,345G,蓝牙,gps)
    2、system:输出系统组件的log(例如调用摄像头,麦克风)
    3、events:输出event模块的log(触摸事件,按键事件等)
    4、main:输出所有java层的log(不包括以上)
    如果我们想查看通讯的log日志
    那么

    adb logcat -b radio >d:\radio_log.log
    

    在这里插入图片描述
    我们平时使用main就可以了,main就是默认,咱们不指定模块就是system和main,所以我们平时用的应该是这个样子的
    在这里插入图片描述
    可能大部分人第一次看都是想 这是什么鬼 看不懂啊
    那么咱们来慢慢解析
    日志分5部分
    1、写下日志时的时间
    2、优先级
    优先级是下面的字符,顺序是从低到高:
    V — 明细 verbose(最低优先级)
    D — 调试 debug
    I — 信息 info
    W — 警告 warn
    E — 错误 error
    F — 严重错误 fatal
    S — 无记载 silent

    标记是一个简短的字符串,用于标识原始消息的来源。如下是一个日志输出的消息,优先级是“D”,标记是“PowerManagerService”:

    D/PowerManagerService( 305): onSensorChanged: light value: 306.0
    使用logcat命令查看android日志输出:

    adb logcat //显示全部日志
    adb logcat > c:\test.log //将日志保存到文件test.log

    根据tag标记和级别过滤日志输出:

    仅输出标记为“ActivityManager”且优先级大于等于“Info”和标记为“PowerManagerService”并且优先级大于等于“Debug”的日志:

    adb logcat ActivityManager:I PowerManagerService:D *:S

    注:*:S用于设置所有标记的日志优先级为S,这样可以确保仅输出符合条件的日志。

    adb logcat *:W //显示所有优先级大于等于“warning”的日志

    adb logcat -s PowerManagerService //显示PowerManagerService的日志信息
    3、标签(tag),标明日志发起者和方便日志过滤
    4、PID 进程号
    5、正文 日志主体内容
    说道时间,时间咱刚才的日志也没有啊,加上-v time即可

    adb logcat -v time -b radio >d:\radio_log.log
    

    在这里插入图片描述
    对上了吧这回

    那么我们要观察优先级,重要的是W和E,我们重点观察E,也就是错误的日志,那么分为几种:
    1、内存泄露
    2、内存溢出
    3、内存抖动
    4、崩溃
    5、ANR

    我们主要说崩溃和ANR
    崩溃我们就直接在日志中搜索Crash关键字,保险的话搜索FATAL EXCEPTION关键字(表示出现严重错误),之下所有同级别的日志都需要截取,发给开发

    ANR:我们在日志中所有ANR in关键字,在发生ANR之前会将anr信息写在/data/anr/traces.txt中将其中的日志发送给开发,这记录最近一次anr,多次的话/data/system/dropbox,其中会有多种异常信息

    展开全文
  • adb logcat日志分析

    千次阅读 2014-07-30 11:30:59
    1、adb logcat 1)此命令用于输出手机或模块器开机以及用户对手机/模拟器进行操作后生成的系统日志,... 2)logcat输出的日志类似为 [img]file:///F:/androidTest/adb%20logcat.html[/img] 备注:(一)日...
    1、adb logcat
    1)此命令用于输出手机或模块器开机以及用户对手机/模拟器进行操作后生成的系统日志,最后显示的日志为用户最近操作记录的日志。

    2)logcat输出的日志类似为 [img]file:///F:/androidTest/adb%20logcat.html[/img]

    备注:(一)日志格式为:等级(I)/标签(Activity)
    即<priority>/<tag>
    (二)日志的等由小到大为:
    V--明细(view)
    D--调式(debug)
    I--信息(information)
    W--警告(warm)
    E--错误(error)
    F--严重错误(fail)
    S--无记载(最高级别,没有什么被 记载)

    3)如果想要减少输出的内容,可以在adb logcat后面加上过滤表达式来限制系统只出来目标日志。可用多个表达一起限制。

    4)过滤表达式的格式为:tag:prority (因为同一个tag可以有不同的优先级)

    如:adb logcat ActivityManager:I MyApp:D *:S

    备注1:仅用于输出标记为“ActivityManager”且优先级大于等于"I"和标记为“MyApp”,优先级大于等于"Debug"的日志。

    备注2:*:S是用于设置ActivityManager:I MyApp:D输出的日志再次过滤 ,标记这些日志的优先级为S(即只输入ActivityManager:I MyApp:D日志,其他的不输出)

    备注3:一般都会在过滤后加上*:S以输出符合指令的日志


    5)adb logcat *:W // "*"是指所有的tag, "*:W"是指输出所有的优先级为W以上的所有tag日志信息


    6)adb logcat是用在pc端以打印logcat;adb shell logcat是用于连上手机或模拟器后,远程获取模拟器的系统日志。两者打印出来的日志是一样的。

    7)控制日志的输出格式:
    日志消息在标记和优先之外还有很多其他字段,这些字体可以通过修改输出格式来控制输出结果,adb logcat -v +下面的字段就可以输出相应的日志格式。

    brief:
    (按默认方式显示日志)
    process:
    (priority<process 号> 日志信息)

    tag:
    (priority/tag: 日志信息)

    thread:
    (priority<线程名称>日志信息)

    raw:
    (只显示日志信息)

    time:
    (时间 priority/tag<process号>:日志信息)


    long:
    (时间 priority/tag<process号>:日志信息),但它是隔一行输出日志



    备注:Start是指启动了service,但没有启动过Activity.START+Displayed是指用户启动过的Activity

    8)Viewing Alternative Log Buffers

    Android 日志系统为日志消息保留了多个循环缓冲区,而且不是所有的消息都被发送到默认缓冲区,要想查看这些附加的缓冲区,可以使用 -b选项,以下是可以指定的缓冲区:

    adb logcat [-b <buffer>]
    radio:
    查看包含在无线/电话相关的缓冲区消息

    events:
    查看事件相关的消息

    main:
    查看主缓冲区(默认缓冲区)


    9)adb logcat -d(dump) -f(filename) + 手机路径:

    把系统日志输出到手机或模拟器里的文件里保存
    展开全文
  • 日志文件分析 例:adb shell monkey - p com . qq - vvv 100 > E : \info . txt 输出通信系统的log -- -- - 重定向到 D :\lemon59\logcat_radio . txt 拒绝访问是重定向文件要传到一个文件里,而不是一个目录里...
  • 查看LogCat日志

    千次阅读 2015-05-16 14:39:40
    Android开发系列:查看LogCat日志  2013-11-05 15:16:16| 分类: 安卓|举报|字号 订阅   下载LOFTER客户端 LogCat日志 1. Window >...
  • logcat日志工具

    2016-07-05 19:53:54
    日志工具类提供了五种方法打印日志 log.v(); 打印琐碎,意义较小的日志,对应级别为verbose,android日志级别里最低的一种。 log.d(); 用于打印一些调试信息,帮助分析和调试项目,对应级别为debug,比前一种高一...
  • logcat日志文件

    2019-10-04 12:45:52
    android日志系统提供了记录和查看系统调试信息的功能,日志都是从各个软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来进行查看和使用 开发者选项,有个选项叫做“日志记录器缓冲区大小”,默认是...
  • 看懂logcat日志

    千次阅读 2018-12-10 14:20:43
    看懂logcat日志 2016年12月14日 23:03:26 小飞哥0217 阅读数:10752 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/flueky/article/details/53645361   前言 准备工作 下载...
  • 我在学习的时候遇到了LogCat不打印日志的...在日志打印的时候我们能选择过滤掉没必要打印出来的日志所以有可能你设置打印日志级别的时候级别过高所以不显示出LogCat日志。 就是在红框框里的日志级别,下面我来解...
  • LogCat日志信息

    2016-01-21 10:12:05
    1、Android 中的日志工具类是 Log(android.util.Log),这个类中提供了如下几个方法来供我们打印日志。  1. Log.v()  ...用于打印一些调试信息,对你调试程序和分析问题是有帮助 的。对应级别debug,比 v
  • adb 实时输出logcat日志到指定文件

    万次阅读 2019-01-03 11:46:01
    1,通过adb连接(WiFi连接或者数据线连接)Android设备 2,PC端进入命令窗口(win +R组合键后,输入cmd) 3,adb shell logcat -v time >...//C:\Users\Administrator\Desktop\logcat.txt 日志输出路径,如果没有...
  • 主要介绍了Android开发之在程序中时时获取logcat日志信息的方法,结合实例形式较为详细的分析了实时获取logcat日志的原理、步骤与相关实现技巧,并附带相应的demo源码供读者下载参考,需要的朋友可以参考下
  • adb logcat 日志过滤

    千次阅读 2016-03-01 17:57:16
    eclipse 自带的 LogCat 工具太垃圾了, 开始用 adb logcat 在终端查看日志; 1. 解析 adb logcat 的帮助信息 在命令行中输入 adb logcat --help 命令, 就可以显示该命令的帮助信息; [plain] view ...
  • logcat 日志 注解

    2016-04-04 13:41:00
     2、Log.d的输出颜色是蓝色的,仅输出debug调试的意思,但他会输出上层的信息,过滤起来可以通过DDMS的Logcat标签来选择;  3、Log.i的输出为绿色,一般提示性的消息information,它不会输出Log.v和Log.d的信息,...
  • Android测试之logcat日志

    2020-02-17 16:03:26
    日志是从各个软件和系统的一些缓冲区中记录下来的,提供记录、查看系统调试信息的功能,可以通过logcat来查看。 缓冲区 缓冲区是环形的、首尾相连,用于缓存固定数据大小的日志信息,开发者选项中有一个叫“日志记录...
  • 过滤adb logcat 日志

    2018-01-12 23:24:00
    ... 开发当中经常看到 log 如洪水般瞬间刷满了屏幕,对自己有用的信息都被淹没了,影响心情也影响效率。下面是几个我所知道的过滤方法。 ...1. 只显示需要的输出,白名单 ...adb logcat -v time -t 500 > 1.txt收集日志
  • Android系统测试或App测试过程中, 有的Android终端设备由于磁盘太小,未开启随系统自启动logcat序列log, 即未实时在后台截取Logcat log,所以需要测试人员进行手动...通过以上命令来进行手动截取Logcat 日志。 我...
  • android SDK-抓取apk包的logcat日志

    千次阅读 2017-06-23 10:20:37
    1、确保计算机里面有以下三个文件,才能抓取logcat日志(只需要这三个文件就可以了)。如果你的计算机有Android sdk,以下三个文件会在你的sdk下的platform-tools文件夹里面。如果需要打印logcat日志的计算机没有 ...
  • logcat源码分析

    2014-01-07 13:17:36
     Logcat工具内置在Android系统中,可以在主机上通过adb logcat...主要是介绍Logcat读取日志的主线,即从打开日志设备文件到读取日志设备文件的日志记录到输出日志记录的主要过程.  Logcat工具源代码位于system/co
  • 摘要:本节主要来讲解Android10.0 logd、logcat读写日志源码内容 阅读本文大约需要花费20分钟。 文章首发微信公众号:大猫玩程序 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! ...
  • 摘要:本节主要来讲解Android10.0 日志系统的架构分析,以及logd、logcat的初始化操作 阅读本文大约需要花费15分钟。 文章首发微信公众号:大猫玩程序 专注于Android系统级源码分析,Android的平台设计,欢迎...
  • Android开发系列:查看LogCat日志

    千次阅读 2012-12-12 10:03:22
    LogCat日志 1. Window > Customize Perspective 2. 选择Shortcuts 标签 3. 在Submenus 选择Show View 4. 在Shortcut Categories选择Android 5. 在右边勾上 LogCat,然后确定。 6. Window > Show View > ...
  • Coolpad在Eclipse不输出LogCat日志

    千次阅读 2015-07-18 09:54:35
    1. 问题描述用Eclipse 打开Android应用工程,然后用usb线连接上酷派...但是应用打的日志LogCat中没有显示,在LogCat总看到这些信息:adb: unable to open /proc/15382/oom_adj adb: unable to open /proc/15384/oom
  • 不是安卓工程师,也能看logcat日志

    万次阅读 2016-12-14 23:03:26
    手上有好几个项目不定期出现问题,而自己又去不了开发现场看日志分析问题、做debug操作。 目前比较流行的两种查看日志的方式有: 1. 开发者通过在开发工具的logcat窗口查看日志输出。优点:具备日志筛选功能,能够...
  • 使用appium框架执行Android自动化...方法1:执行自动化测试时,同时打开另外一个cmd,用来抓取日志,以下是使用python脚本或直接在命令行获取logcat日志实例: 1)python(log文件名加上了当前时间): #encoding:utf-8
  • LogCat :Android中一个... 而LogCat , 就是程序的日志。通过日志,你可以知道运行时间,运行位置,运行结果,运行时缓冲区的东东。 我们先添加LogCat 点击Eclipse 导航栏中的 Window——>Show View...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,227
精华内容 3,290
关键字:

logcat日志分析