Compartilhamento de plug-in de gancho de instrumentação de bytecode de método Android, enterramento completo, monitoramento de desempenho, threads, monitoramento de criação de IO, one-stop, altamente personalizável, muito fácil de usar!

Endereço do projeto: hook-method-plugin

Este é um plug-in para o gancho do método android. Quando o método entra e sai, todos os parâmetros atualmente em execução são chamados de volta para a interface fixa. Usando isso, o desenvolvimento da fatia do método pode ser realizado. Ao configurar o ponto de gancho, o monitoramento do gancho pode ser alcançado.

Com este plug-in, você pode:

  1. Ponto de enterramento completo do Android, navegação na página, clique, etc. Nenhum ponto de enterramento de rastreamento, basta configurar o ponto de gancho conforme necessário, o método de configuração é o seguinte
  2. Estatísticas de desempenho demoradas do método Android
  3. Vários interceptadores, por exemplo, para interceptar um método, antes que um método seja executado, primeiro determine a autoridade ou faça os preparativos
  4. Adicione o código ao pacote jar de terceiros referenciado, adicione a criação de encadeamento, o monitoramento relacionado a e/s de arquivo, etc.
  5. Verifique a lógica de execução que faz referência a SDKs de terceiros, como verificar quais SDKs obtêm localização, imei e execuções frequentes em segundo plano

Mostrar resultados

Por exemplo, no desenvolvimento diário, podemos inevitavelmente precisar executar algumas tarefas de enterramento de eventos de clique. Se usarmos este plug-in, podemos configurar e contar diretamente todos os pontos de enterramento de eventos de clique uma vez. Vamos dar uma olhada nos métodos específicos:

  1. Primeiro defina o ponto de gancho, o objetivo desse ponto de gancho é monitorar todos os eventos de clique. Adicione o seguinte código ao build.gradle no módulo app, e o significado dos campos detalhados será explicado abaixo.
apply plugin: 'com.miqt.plugin.hookmethod'
hook_method {
    
    
    buildLog = true
    injectJar = false //是否hook引用的第三方jar包
    enable = true
    hookTargets {
    
    
        hook_onclick {
    
     // <-- 定义Hook点
            interfaces = "android/view/View\$OnClickListener"//<-- hook条件1,继承了这个接口
            methodName = "onClick"							//<-- hook条件2,方法名
            descriptor = "(Landroid/view/View;)V"			//<-- hook条件3,方法参数和返回值类型
            hookTiming = "Enter"							//<-- hook条件4,指定是在方法进入时进行Hook
        }
    }
}

hook_method é a configuração geral do plug-in e hookTargets é a configuração do ponto Hook. Ao compilar, ele será filtrado de acordo com as condições de filtro definidas. Somente quando as quatro condições forem atendidas ao mesmo tempo, a instrumentação será realizada.

Observe que, por se tratar de uma operação de bytecode, as definições aqui descriptorsão tanto descritores de campo quanto descritores de bytecode.Se você não conhece, pode encontrar no Baidu, que é bem simples. Tudo bem se você não quiser saber, apresentarei um método para visualizar diretamente as informações do bytecode de um método. Usar @HookInfoanotações

Após a configuração acima, escrevemos um botão casualmente e adicionamos um evento de clique.

public class MainActivity extends Activity {
    
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                Toast.makeText(MainActivity.this, "onClick", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Clique no botão de sincronização para compilar o projeto. Neste momento, o plug-in irá gerar automaticamente a classe de processamento do manipulador de encaminhamento de gancho para o evento de clique:

Algo assim: HookHandler

Neste momento, abrimos a descompilação e visualização do Apk e podemos ver o código do stub:

public class MainActivity extends Activity {
    
    
    /* access modifiers changed from: protected */
    public void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
    
    
            /* class com.asm.code.MainActivity.AnonymousClass1 */

            public void onClick(View view) {
    
    
                HookHandler.hook_onclickEnter(this, "com/asm/code/MainActivity$1", "onClick", "[android.view.View]", "void", new Object[]{
    
    view});//<--插桩的代码
                Toast.makeText(MainActivity.this, "onClick", 0).show();
            }
        });
    }
}

Neste ponto, só precisamos hook_onclickEnterescrever a lógica global de monitoramento e processamento de eventos de clique neste método. Tudo isso é feito automaticamente pelo plug-in. Precisamos apenas configurar as regras do Gancho. Não é muito simples.

Exemplo de portal de configuração: https://github.com/miqt/android-plugin/blob/master/app/build.gradle

Por analogia, o plug-in também pode atingir o propósito de programação de aspectos customizando as regras do Hook e o código de qualquer método no projeto do Hook.

Usar método de configuração

  1. Adicionar repositório maven

    maven {
          
           url 'https://raw.githubusercontent.com/miqt/maven/master' }
    maven {
          
           url 'https://gitee.com/miqt/maven/raw/master' }
    

    Ainda não pode puxar a biblioteca?

    maven {
          
           url 'https://raw.fastgit.org/miqt/maven/master' }
    

    Ou vá para o endereço git do meu armazém para baixá-lo e dependa dele localmente.

    Eu usei no início jcenter(), mas depois esta biblioteca foi oficialmente obsoleta, mas agora a versão 0.3.5 ainda pode ser extraída desta biblioteca, e eu uso gitee e github como endereços de armazenamento de armazém para versões posteriores.

  2. Adicionar dependências de plug-in

    Diretório raiz do projeto: build.gradle adicione o seguinte código

    dependencies {
          
          
        classpath 'com.miqt:hook-method-plugin:0.4.1'
    }
    

    O plug-in é habilitado no módulo correspondente, que pode ser applicationoulibrary

    apply plugin: 'com.miqt.plugin.hookmethod'
    hook_method {
          
          
        buildLog = true
        injectJar = false //是否hook引用的第三方jar包
        enable = true
        hookTargets {
          
          
            hook_onclick {
          
           // <-- 自定义Hook点
                interfaces = "android/view/View\$OnClickListener"	//<-- hook条件1,继承了这个接口
                methodName = "onClick"	//<-- hook条件2,方法名
                descriptor = "(Landroid/view/View;)V"	//<-- hook条件3,方法参数和返回值类型
                hookTiming = "Enter"	//<-- hook条件4,指定是在方法进入时进行Hook
            }
        }
    }
    
  3. Adicionar dependências da biblioteca de classes no módulo correspondente

    dependencies {
          
          
        implementation 'com.miqt:hook-method-lib:0.4.1'
    }
    

    Limpe o projeto e execute-o, filtre o logcat MethodHookHandlere veja o resultado da impressão!

Descrição dos parâmetros de configuração do plug-in

Parâmetros em hook_method {}

Isso é para definir a configuração relacionada ao plug-in.

parâmetro É necessário? tipo significado Padrões
habilitar não bool Se deve habilitar verdadeiro
runVariant não corda Ambiente de execução do plug-in, as vezes queremos apenas inserir stubs no ambiente debug, e o ambiente de release não precisa disso, neste momento pode ser configurado para: DEBUG, ou seja, somente quando o DEBUG for executado, o plug-in é executado. Este parâmetro tem quatro valores de enumeração: DEBUG
: Somente Depurar instrumentação de tempo de execução
RELEASE: Somente RELEASE instrumentação de tempo de execução
SEMPRE: Todos os tempos de execução (padrão)
NEVER: Nunca instrumentação, equivalente a habilitar = false
SEMPRE
jarra de injeção não bool Se deve implementar a inserção de gancho de acordo com as regras para todos os jars e aars dependentes de terceiros referenciados falso
buildLog não bool Se o registro de compilação do plug-in deve ser gerado na pasta .\app\build\plugin. Quando houver um erro na compilação, abra verdadeiro
manipulador não corda A classe receptora do Handler encaminhado pelo Gancho de instrumentação é a classe de processamento da instrumentação. Por exemplo, se você passar xxx.xxx.A, a classe A.java será gerada automaticamente após a compilação, e o método será gerado automaticamente, semelhante a este : com.miqt.hookplugin.HookHandler
handlerDir não corda A classe receptora do Handler encaminhada pelo Hook instrumentado é gerada nesse caminho, o padrão .\src\main\javageralmente não é necessário customizar .\src\main\java

Parâmetros em hookTargets {}

estrutura:

hook_method {
    
    
    hookTargets {
    
    
        name1 {
    
    
        	条件1 = value1
        	条件2 = value2
        	条件3 = value3
        }
        name2 {
    
    
        	条件1 = value1
        	条件2 = value2
        	条件3 = value3
        }
    }
}

Aqui está a definição das condições do filtro do ponto do exaustor, a lógica é que as condições definidas pelos parâmetros 1, 2 e 3 devem ser atendidas antes que as estacas possam ser inseridas.

Nota: Se for definido: hook_All{ }este parâmetro incondicional significa que todos os métodos serão fragmentados.

parâmetro É necessário? tipo significado Padrões
nome sim corda A posição de name1 e name2 acima significa o nome do ponto de gancho. Este nome será eventualmente o nome do método receptor de gancho neste ponto, que pode ser definido por você mesmo nulo
acesso não int Restrições: Modificadores de acesso ao método, como private, public, static, final, são definidos neste Opcodes.ACC_PRIVATE|Opcodes.ACC_STATICformulário -1
interfaces não corda A condição limitante: qual interface deve ser implementada pela classe onde o método está localizado, por exemplo, a interface OnClickListener é escrita assim: nenhum interfaces = "android/view/View\$OnClickListener"ponto é usado aqui e / é usado para indicar que este é um identificador de bytecode. Adicione a anotação @HookInfo ao método ou classe e o plug-in exibirá automaticamente o identificador de bytecode correspondente no console de compilação e no arquivo de log de Log de compilação. nulo
superNome não corda Restrição: A classe do método deve ser uma subclasse de superName nulo
nome da classe não corda Restrição: o nome da classe onde o método está localizado, aqui está o nome completo, como com/xxx/A, suporta restrições regulares nulo
nome do método não corda Restrição: nome do método, suporte para restrições regulares nulo
descritor não corda Restrição: method field descriptor , se você não sabe como escrevê-lo, use a tag @HookInfo para ver a saída. nulo
anotação não corda Restrição: O método ou classe deve conter esta anotação nulo
assinatura não corda Restrição: O método ou classe deve conter este genérico nulo
exceções não corda Restrição: O método deve estar em conformidade com a forma de lançar uma exceção nulo
hookTiming não corda Condições restritas: quando o método entra no stub ou quando sai
Enter: quando o método entra
Return: quando o método sai
Enter|Return: ao entrar e sair (padrão)
Entrar|Retornar

anotação embutida

@HookInfo: Exibe as informações de condição de restrição de bytecode correspondente, que podem ser copiadas e impressas para o mesmo tipo de método Hook
@HookMethod: Marque o método hook, não há necessidade de escrever hookTargets, pode ser entendido como @HookMethodInherited integrado
: Marque o método hook, há herança de classe, não há necessidade de escrever hookTargets, pode ser entendido como o
@IgnoreMethodHook interno : marque o método ignore, a prioridade mais alta

读都读到这里了,如果觉得还不错就帮我点个star吧,你的肯定是我持续维护的动力!

如果有使用问题欢迎提交Issues ,或者加我微信一起交流,微信号在我的主页。

最后贴个Demo中的示例:

apply plugin: 'com.miqt.plugin.hookmethod'
hook_method {
    
    
    buildLog = true
    injectJar = true
    enable = true
    hookTargets {
    
    
        hook_onclick {
    
    
            //<-- 所有点击事件
            interfaces = "android/view/View\$OnClickListener"
            methodName = "onClick"
            descriptor = "(Landroid/view/View;)V"
            hookTiming = "Enter|Return"
        }
        hook_activity_lifeCycle {
    
    
            //<-- 所有activity生命周期方法
            access = 4
            superName = "android/app/Activity"
            //这里是个正则表达式
            methodName = "(onCreate)|(onResume)|(onPause)|(onStart)|(onDestroy)|(onStop)"
            hookTiming = "Enter|Return"
        }
        hook_thread_run{
    
    
            //<-- 线程run方法
            access = 1
            superName = "java/lang/Thread"
            methodName = "run"
            descriptor = "()V"
        }
        hook_Runnable_run{
    
    
            //<-- 线程run方法
            access = 1
            interfaces = "java/lang/Runnable"
            methodName = "run"
            descriptor = "()V"
        }
    }
}

demo打印结果:

I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[3]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[Thread-5]
I/MethodHookHandler: └com/asm/code/[email protected]():[1]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]

致谢

这个插件是借鉴了很多大佬的代码,并结合自己的想法进行了一些调整,在此感谢他们付出的努力。

https://github.com/novoda/bintray-release
https://github.com/JeasonWong/CostTime
https://github.com/MegatronKing/StringFog

Acho que você gosta

Origin blog.csdn.net/qq_27512671/article/details/119570908
Recomendado
Clasificación