Android实用的工具命令

高效干活

Posted by River on January 25, 2022

前言

码农无论是战斗力还是待遇,呈现了数量级的差异;那些大神高手除了天赋加刻苦训练以外; 基本都会总结提炼自己常用的工具,包括命令行,知识库等。

1、apksigner命令

apksigner -keystore /Users/river/Documents/hellobike-android/HellobikeAndroidAtlasApp/app/keys/easybike_release.jks -signedjar    /Users/river/Documents/mpaas加固/temp/hello.apk_arm32_sign.apk   /Users/river/Documents/mpaas加固/temp/hello.apk_arm32_unsign.apk  easybikerelease 

尽量使用apksigner,不要用jarsigner。

2、git命令

git在开发中非常普遍,熟练使用git命令也是基本功。

清除缓存
git rm -r --cached . 

集中清楚本地分支
git branch |grep  'lqj' |xargs git branch -D 

3、adb查看当前的页面类全路径

adb shell dumpsys activity top |grep ACTIVITY

这个命令适用于所有的Android应用,非常实用。

4、debug包不能用adb install安装解决

android.injected.testOnly=false

在gradle.properties文件中配置

5、crt文件转pem文件

openssl x509 -in  /Users/xxx/ca.crt -inform der -text  -out ca.pem

pem文件是crt文件base64编码后的文本文件,对照性比较强。

6、启动优化分析工具

trace文件在线解析地址: https://ui.perfetto.dev/#!/viewer?trace_id

生成trace文件步骤:

  1. cd /Users/xxx/Library/Android/sdk/platform-tools/systrace

  2. python systrace.py gfx view wm am pm ss dalvik app sched -b 90960 -a com.jingyao.easybike -o dex8.html

  3. 打开app,等首页渲染结束敲回车;上述命令有文件最大阀值的限制,如果启动太慢可以早点敲回车键。

制作一个plugin工作对方法埋点:

准备一个一个简单的封装类,可以直接放在项目中。
package com.tencent.matrix.trace.core;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Trace;



public class TraceTag {

    private static final String TAG = "TraceTag";

    /**
     * hook method when it's called in.
     *
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    public static void i(String name) {
        Trace.beginSection(name);
    }

    /**
     * hook method when it's called out.
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    public static void o() {
        Trace.endSection();
    }
}

参考微信matrix的方法插桩,在matrix-gradle-plugin工程的MethodTracer$TraceMethodAdapter 中插入代码:

    @Override
    protected void onMethodEnter() {
        TraceMethod traceMethod = collectedMethodMap.get(methodName);
        if (traceMethod != null) {
            traceMethodCount.incrementAndGet();
            mv.visitLdcInsn(traceMethod.id);
            mv.visitMethodInsn(INVOKESTATIC, TraceBuildConstants.MATRIX_TRACE_CLASS, "i", "(I)V", false);
            // 上面是matrxi源码,下面才是自己插入的代码
            // 插入systrace的调用
            String sectionName = methodName;
            int length = sectionName.length();
            if (length > TraceBuildConstants.MAX_SECTION_NAME_LEN) {
                // 先去掉参数
                int parmIndex = sectionName.indexOf('(');
                sectionName = sectionName.substring(0, parmIndex);
                // 如果依然更大,直接裁剪
                length = sectionName.length();
                if (length > TraceBuildConstants.MAX_SECTION_NAME_LEN) {
                    sectionName = sectionName.substring(length - TraceBuildConstants.MAX_SECTION_NAME_LEN);
                }
            }
            mv.visitLdcInsn(sectionName);
            mv.visitMethodInsn(INVOKESTATIC, TraceBuildConstants.MATRIX_TRACE_SYSTRACE_CLASS, "i", "(Ljava/lang/String;)V", false);
      
        }
    }
    
    
    @Override
    protected void onMethodExit(int opcode) {
        TraceMethod traceMethod = collectedMethodMap.get(methodName);
        if (traceMethod != null) {
            if (hasWindowFocusMethod && isActivityOrSubClass && isNeedTrace) {
                TraceMethod windowFocusChangeMethod = TraceMethod.create(-1, Opcodes.ACC_PUBLIC, className,
                        TraceBuildConstants.MATRIX_TRACE_ON_WINDOW_FOCUS_METHOD, TraceBuildConstants.MATRIX_TRACE_ON_WINDOW_FOCUS_METHOD_ARGS);
                if (windowFocusChangeMethod.equals(traceMethod)) {
                    traceWindowFocusChangeMethod(mv, className);
                }
            }

            traceMethodCount.incrementAndGet();
            mv.visitLdcInsn(traceMethod.id);
            // 上面是matrxi源码,下面才是自己插入的代码
            // 插入systrace的调用
            mv.visitMethodInsn(INVOKESTATIC, TraceBuildConstants.MATRIX_TRACE_CLASS, "o", "(I)V", false);
        }
    }
    
    public class TraceBuildConstants {
        public final static String MATRIX_TRACE_SYSTRACE_CLASS = "com/tencent/matrix/trace/core/TraceTag";
        //没有必要插桩类做过滤
            public final static String DEFAULT_BLACK_TRACE =
        "[package]\n"
                + "-keeppackage android/\n"
                + "-keeppackage com/tencent/matrix/\n"
                + "-keepclass com/tencent/matrix/trace/core/TraceTag\n";
    }
    
    public class Configuration {
        
        public int parseBlackFile(MappingCollector processor){
                
                 String blackStr = TraceBuildConstants.DEFAULT_BLACK_TRACE + FileUtil.readFileAsString(blackListFilePath);

                String[] blackArray = blackStr.trim().replace("/", ".").split("\n");
               
                 if (blackArray != null) {
                for (String black : blackArray) {
                if (black.length() == 0) {
                continue;
                }
                if (black.startsWith("#")) {
                continue;
                }
                if (black.startsWith("[")) {
                continue;
                }

                if (black.startsWith("-keepclass ")) {
                black = black.replace("-keepclass ", "");
                blackSet.add(processor.proguardClassName(black, black));
                } else if (black.startsWith("-keeppackage ")) {
                black = black.replace("-keeppackage ", "");
                blackSet.add(processor.proguardPackageName(black, black));
            }
        }
    }
    return blackSet.size();
        }
    }

```

trace文件大致的形态效果 trace文件示意图

总结

  1. 工欲善其事,必先利其器;熟练使用工具库可以大幅度提升工作效率。