跳转至

Android神兵利器

大部分IDE

减少缩进 ⌘ + [

增加缩进 ⌘ + ]


vim

提交时删除修改文件前面的#

  1. 光标移动到需要删除#的第一行 ESC
  2. Ctrl + V
  3. Shift + G
  4. Delete

大工告成,:wq回车


Android查看页面名称以及查看页面布局id

查看页面名称可以使用adb shell dumpsys activity top命令,得到的信息如下

TASK com.yorek.yltodo id=408
  ACTIVITY com.yorek.yltodo/.ui.activity.SplashActivity cfb9244 pid=31840
    Local Activity dc9e5f8 State:
      mResumed=true mStopped=false mFinished=false
      mChangingConfigurations=false
      mCurrentConfig={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w360dp h620dp 480dpi nrml long port finger -keyb/v/h -nav/h s.5 themeChanged=0 themeChangedFlags=0}
      mLoadersStarted=true
      Active Fragments in fe292ef:
        #0: ReportFragment{1791fc #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag}
          mFragmentId=#0 mContainerId=#0 mTag=android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag
          mState=5 mIndex=0 mWho=android:fragment:0 mBackStackNesting=0
          mAdded=true mRemoving=false mFromLayout=false mInLayout=false
          mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
          mRetainInstance=false mRetaining=false mUserVisibleHint=true
          mFragmentManager=FragmentManager{fe292ef in HostCallbacks{d6c2085}}
          mHost=android.app.Activity$HostCallbacks@d6c2085
          Child FragmentManager{4d08eda in ReportFragment{1791fc}}:
            FragmentManager misc state:
              mHost=android.app.Activity$HostCallbacks@d6c2085
              mContainer=android.app.Fragment$1@eef6f0b
              mParent=ReportFragment{1791fc #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag}
              mCurState=5 mStateSaved=false mDestroyed=false
      Added Fragments:
        #0: ReportFragment{1791fc #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag}
      FragmentManager misc state:
        mHost=android.app.Activity$HostCallbacks@d6c2085
        mContainer=android.app.Activity$HostCallbacks@d6c2085
        mCurState=5 mStateSaved=false mDestroyed=false
    ViewRoot:
      mAdded=true mRemoved=false
      mConsumeBatchedInputScheduled=false
      mConsumeBatchedInputImmediatelyScheduled=false
      mPendingInputEventCount=0
      mProcessInputEventsScheduled=false
      mTraversalScheduled=false      mIsAmbientMode=false
      android.view.ViewRootImpl$NativePreImeInputStage: mQueueLength=0
      android.view.ViewRootImpl$ImeInputStage: mQueueLength=0
      android.view.ViewRootImpl$NativePostImeInputStage: mQueueLength=0
    Choreographer:
      mFrameScheduled=true
      mLastFrameTime=13434855 (22 ms ago)
    View Hierarchy:
      DecorView@d49d1e8[SplashActivity]
        android.widget.LinearLayout{7d34001 V.E...... ........ 0,0-1080,1920}
          android.view.ViewStub{438bea6 G.E...... ......I. 0,0-0,0 #102040b android:id/action_mode_bar_stub}
          android.widget.FrameLayout{a3f0e7 V.E...... ........ 0,0-1080,1920}
            android.support.v7.widget.FitWindowsLinearLayout{2de2494 V.E...... ........ 0,0-1080,1920 #7f09000f app:id/action_bar_root}
              android.support.v7.widget.ViewStubCompat{632db3d G.E...... ......I. 0,0-0,0 #7f09001a app:id/action_mode_bar_stub}
              android.support.v7.widget.ContentFrameLayout{a21f32 V.E...... ........ 0,0-1080,1920 #1020002 android:id/content}
                android.widget.FrameLayout{d34b483 V.E...... ........ 0,0-1080,1920}
                  android.widget.LinearLayout{ec2f600 V.E...... ........ 0,0-1080,1920 #7f09005d app:id/fl_login}
                    android.support.v4.widget.Space{3f6ee39 I.ED..... ......I. 0,0-1080,382 #7f0900bd app:id/space}
                    android.support.v7.widget.AppCompatTextView{5cefc7e V.ED..... ........ 0,382-1080,535 #7f0900e2 app:id/tv_app_name}
                    com.yorek.yltodo.ui.widget.CodeEditText{18415df VFED..CL. .F...... 0,535-1080,764 #7f09003d app:id/code_edit_text}
                    android.support.v4.widget.Space{d61722c I.ED..... ......I. 0,764-1080,1531}
                    android.support.v7.widget.AppCompatTextView{d4f34f5 V.ED..... ........ 0,1531-1080,1584 #7f0900e4 app:id/tv_finger_print_status}
                    android.support.v7.widget.AppCompatImageView{75a628a V.ED..C.. ........ 468,1608-612,1752 #7f09006a app:id/iv_finger_print}
                  android.support.v7.widget.AppCompatImageView{c3e30fb V.ED..... ........ 396,816-684,1104 #7f09006d app:id/iv_logo}
    Looper (main, tid 1) {6898518}
      package com.yorek.yltodo version Code: 1 version Name: 1.0.0 cur loop is : Looper (main, tid 1) {6898518}
---------- Dump MessageQueue on Looper (main, tid 1) {6898518}----------
     Message 0: { when=-14ms callback=android.view.Choreographer$FrameDisplayEventReceiver target=android.view.Choreographer$FrameHandler planTime=1523198725746 dispatchTime=0 finishTime=0 }
     (Total messages: 1, polling=false, quitting=false)
-------------------------- END --------------------------

    Local FragmentActivity dc9e5f8 State:
      mCreated=truemResumed=true mStopped=false mReallyStopped=false
      mLoadersStarted=true
    FragmentManager misc state:
      mHost=android.support.v4.app.FragmentActivity$HostCallbacks@7ab2b71
      mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@7ab2b71
      mCurState=5 mStateSaved=false mDestroyed=false

第一行的 TASK 就是前台任务栈的名称,第二行的 ACTIVITY 就是前台activity的名称

查看页面布局需要用到sdk里面的工具, MacOS 平台是sdk/tools/bin/uiautomatorviewer这个工具

yorek@yoreks-mbp:~/Library/Android/sdk/tools/bin$ ./uiautomatorviewer

bin目录下通过脚本的调用方式调用即可。

step 1: 点击界面左上角第二个按钮,进入分析界面
step1 这四个按钮分别是打开、设备截图、压缩的设备截图、保存

step 2: 在左侧的操作页面选择感兴趣的控件,右边会出现其对应的信息 step2

性能优化常用工具

CPU占用分析:Systrace、TraceView
内存占用分析: dump heap (MAT)、Allocation Tracker

Android Studio Profiler集成了:
Memory Profiler -> dump heap (MAT、AS)、Allocation Tracker
CPU Profiler -> Systrace、TraceView

Danger

TODO: 补充具体案例

Systrace、TraceView的区别

Systrace 可以跟踪系统的 I/O 操作、CPU 负载、Surface 渲染、GC 等事件。systrace 工具只能监控特定系统调用的耗时情况,所以它是属于 sample 类型,而且性能开销非常低。但是它不支持应用程序代码的耗时分析,所以在使用时有一些局限性。

Traceview 可以用来查看整个Java层代码执行过程有哪些函数调用,但是工具本身带来的性能开销过大,有时无法反映真实的情况。属于instrument类型。

AS Profiler

在 Android Studio 3.2 的 Profiler 中直接集成了几种性能分析工具,其中:

  • Sample Java Methods 的功能类似于 Traceview 的 sample 类型。
  • Trace Java Methods 的功能类似于 Traceview 的 instrument 类型。
  • Trace System Calls 的功能类似于 systrace。
  • SampleNative (API Level 26+) 的功能类似于 Simpleperf。

bugreport

使用bugreport命令手机日志后,可以使用chkbugreport.jar来生成便于查看的日志文件:

adb bugreport log    # 生成log.zip
unzip log.zip -d log # 解压log.zip文件夹
java -jar chkbugreport.jar log/bugreport-NMF26X-2019-12-30-10-36-35.txt # 解析日志文件

上面日志文件解析完毕后,会生成一个log/bugreport-NMF26X-2019-12-30-10-36-35_out的文件夹,打开里面的index.html文件即可。

chkbugreport是Sony的一个开源项目,地址如下:https://github.com/sonyxperiadev/ChkBugReport

这里附上一个自动dump、解析并清理原始文件的脚本。将脚本与chkbugreport-0.5-215.jar文件存放在同一个目录下,执行此脚本。执行完毕之后,格式化后的文件会放在~/Downloads目录下。

#!/bin/bash

outputDir=~/Downloads

bugreport() {
    devices_version=`adb shell getprop ro.build.version.sdk | awk '{print $1}' | tr -d $'\r'`
    if [ $devices_version -ge 24 ]
    then
        bugreportV24
    else
        bugreportPre24
    fi
}

bugreportV24() {
    echo "generating bugreport.zip ... "
    adb bugreport $outputDir/bugreport

    unzip $outputDir/bugreport.zip -d $outputDir/bugreport

    echo "parsing ... "
    bugreport_file_name=`cat $outputDir/bugreport/main_entry.txt`
    java -jar chkbugreport-0.5-215.jar $outputDir/bugreport/$bugreport_file_name

    echo "zipping out dir ... "
    bugreport_output_name=${bugreport_file_name%.txt}_out
    cd $outputDir
    zip -q -r bugreport_out bugreport/$bugreport_output_name/*
    cd -

    rm -rf $outputDir/bugreport $outputDir/bugreport.zip

    echo "Completed ... "
}

bugreportPre24() {
    bugreport_file_name="bugreport.txt"

    echo "generating bugreport.zip ... "
    adb bugreport > $outputDir/$bugreport_file_name

    echo "parsing ... "
    java -jar chkbugreport-0.5-215.jar $outputDir/$bugreport_file_name

    echo "zipping out dir ... "
    bugreport_output_name=${bugreport_file_name%.txt}_out
    cd $outputDir
    zip -q -r bugreport_out $bugreport_output_name
    cd -

    rm -rf $outputDir/bugreport.txt $outputDir/bugreport_out

    cd -

    echo "Completed ... "
}

read -r -p "Execute bugreport? [Y/N] " input

case $input in
    [Yy][Ee][Ss]|[Yy])
        bugreport
        ;;

    [Nn][Oo]|[Nn])
        ;;

    *)
        ;;
esac

评论