滴滴DroidAssistプラグインに基づいて痕跡のない埋め込みスキームを実現

25788 ワード

無痕埋め込み点の概念
無痕埋点は無埋点、全埋点とも呼ばれ、データ収集の重要な方法である.ビジネスの更新は反復が速く、コード量が大きいため、手動埋め込みエラー率が高く、時間もかかるため、手動埋め込みは賢明な選択ではありません.この場合,開発者が手動でデータ収集のコードを書く必要はなく,コードを動的に挿入することでプログラマーの作業量を大幅に削減する痕跡のない埋め込みポイントが必要となる.
インデンテーションレス埋め込み方式
  • 方式一:グローバルHook AppにおけるView
  • 方式二:AOPプログラミング(Aspect-oriented Programming)、操作バイトコード動的挿入コード、常用フレームワークAspectj、ASM、javassist、三つのフレームワークの違いはこの文章
  • を参照してください.
    メリットとデメリット
    方式1:グローバルHook AppにおけるViewの方式原理は,app中のすべてのViewがOnClickListenerを動的エージェントで置き換えることで効率が低下するため,この方式を採用しない.
    方式2:AOP方式はjava->class、class->dexの過程でコードを挿入し、コンパイルの過程で実行するのはコンパイルの時間を増やすだけで、Appの効率はありません.
    DroidAssist
    私達のプロジェクトは滴滴オープンソースフレームワークDroidAssistを採用して、javassistに基づいて、1種の簡単で使いやすくて、侵入がなくて、配置化して、軽量級のJavaバイトコードの操作方式を提供して、あなたはバイトコードの関連する知識を知る必要はなくて、XMLの配置の中で簡単なJava世代コードを追加するだけでコンパイル期間のClassファイルに対する動的な修正を実現することができて、プロジェクトのアドレス
    使用方法
    rootプロジェクトのbuild.gradleに追加:
    dependencies {
        classpath "com.didichuxing.tools:droidassist:1.0.10"
    }
    
    処理が必要なモデルプロジェクトのbuild.gradleに追加:
    apply plugin: 'com.didichuxing.tools.droidassist'
    droidAssistOptions {
        config file("droidassist.xml") //      (    ,       )
    }
    
    埋込み点構成表
    Class
    AgentName
    Source
    View
    onClick
    void android.view.View$OnClickListener.onClick(android.view.View)
    DialogInterface
    onClick
    void android.content.DialogInterface$OnClickListener.onClick(android.content.DialogInterface,int)
    RadioGroup
    onCheckedChanged
    void android.widget.RadioGroup$OnCheckedChangeListener.onCheckedChanged(android.widget.RadioGroup,int)
    SeekBar
    onStopTrackingTouch
    void android.widget.SeekBar$OnSeekBarChangeListener.onStopTrackingTouch(android.widget.SeekBar)
    RecyclerView-BaseQuickAdapter
    onItemClick
    void com.chad.library.adapter.base.BaseQuickAdapter$OnItemClickListener.onItemClick(com.chad.library.adapter.base.BaseQuickAdapter,android.view.View,int)
    CompoundButton
    onCheckedChanged
    void android.widget.CompoundButton$OnCheckedChangeListener.onCheckedChanged(android.widget.CompoundButton,boolean)
    xml構成
    <BeforeMethodExecution>
                <Source>void android.view.View$OnClickListener.onClick(android.view.View)Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectClick($1);}
                Target>
    BeforeMethodExecution>
    <BeforeMethodExecution>
                <Source>void android.content.DialogInterface$OnClickListener.onClick(android.content.DialogInterface,int)Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectDialogClick($1);}
                Target>
    BeforeMethodExecution>
    <BeforeMethodExecution>
                <Source>void android.widget.RadioGroup$OnCheckedChangeListener.onCheckedChanged(android.widget.RadioGroup,int)Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectCheckedChanged($1,$2);}
                Target>
    BeforeMethodExecution>
    <BeforeMethodExecution>
                <Source>void android.widget.SeekBar$OnSeekBarChangeListener.onStopTrackingTouch(android.widget.SeekBar)Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectSeekClick($1);}
                Target>
    BeforeMethodExecution>
    <BeforeMethodExecution>
                <Source>void com.chad.library.adapter.base.BaseQuickAdapter$OnItemClickListener.onItemClick(com.chad.library.adapter.base.BaseQuickAdapter,android.view.View,int)Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectRecyclerViewClick($1,$2,$3);}
                Target>
    BeforeMethodExecution>
    <BeforeMethodExecution>
                <Source>void android.widget.CompoundButton$OnCheckedChangeListener.onCheckedChanged(android.widget.CompoundButton,boolean)Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectCheckedChanged($1,$2);}
                Target>
    BeforeMethodExecution>
    
    ページ滞留時間
  • Activity onResumeメソッドでactivityのwindowを取得し、その後DecorViewを取得し、現在のシステム時間を取得してDecorView設定Tag
    public static void injectOnResume(Activity context) {
        if(context.getWindow().getDecorView().getTag() == null){
            long startTime = System.currentTimeMillis();
            context.getWindow().getDecorView().setTag(startTime);
            Log.e("----->", "injectOnResume-"+startTime);
        }
    }
    
    onStopメソッドでTagを取得し、滞留時間
    public static void injectOnStop(Activity context) {
        if (context.getWindow().getDecorView().getTag() != null) {
            long startTime=(long)context.getWindow().getDecorView().getTag();
            long endTime = System.currentTimeMillis();
            long dTime=endTime-startTime;
            String s = TimeUtilKtKt.intervalMMSS(startTime, endTime);
            context.getWindow().getDecorView().setTag(null);
            Log.e("----->", "injectOnStop-time-"+s);
        }
    }
    
    xml構成
    <BeforeMethodExecution>
                <Source>void android.app.Activity.onResume()Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectOnResume(this);}
                Target>
            BeforeMethodExecution>
            <BeforeMethodExecution>
                <Source>void android.app.Activity.onStop()Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectOnStop(this);}
                Target>
     BeforeMethodExecution>
    
  • を算出する.
  • Fragment onResumeメソッドでfragmentのviewを取得し、現在のシステム時間を取得してDecorView設定Tag
     public static void injectFragmentOnResume(Fragment fragment) {
          if (fragment.getView() != null && fragment.getView().getTag() == null) {
              long startTime = System.currentTimeMillis();
              fragment.getView().setTag(startTime);
              Log.e("----->", "injectFragmentOnResume-" + startTime);
          }
     }
    
    onPauseメソッドでviewを取得してTagを取得し、滞留時間
    public static void injectFragmentonPause(Fragment fragment) {
          if (fragment.getView() != null && fragment.getView().getTag() != null) {
             long startTime = (long) fragment.getView().getTag();
             long endTime = System.currentTimeMillis();
             long dTime = endTime - startTime;
             String s = TimeUtilKtKt.intervalMMSS(startTime, endTime);
             fragment.getView().setTag(null);
             Log.e("----->", "injectFragmentOnStop-" + s);
        }}
    
    xml構成
    <BeforeMethodExecution>
                <Source>void androidx.fragment.app.Fragment.onResume()Source>
                <Target>
                    {com.sxbcar.demo.util.AssistUtil.injectFragmentOnResume(this);}
                Target>
            BeforeMethodExecution>
            <BeforeMethodExecution>
                <Source>void androidx.fragment.app.Fragment.onPause()Source>
                <Target>
                  {com.sxbcar.demo.util.AssistUtil.injectFragmentonPause(this);}
                Target>
     BeforeMethodExecution>
    
  • を算出する.