滴滴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プロジェクトの
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構成 Activity onResumeメソッドでactivityのwindowを取得し、その後DecorViewを取得し、現在のシステム時間を取得してDecorView設定Tag を算出する. Fragment onResumeメソッドでfragmentのviewを取得し、現在のシステム時間を取得してDecorView設定Tag を算出する.
無痕埋点は無埋点、全埋点とも呼ばれ、データ収集の重要な方法である.ビジネスの更新は反復が速く、コード量が大きいため、手動埋め込みエラー率が高く、時間もかかるため、手動埋め込みは賢明な選択ではありません.この場合,開発者が手動でデータ収集のコードを書く必要はなく,コードを動的に挿入することでプログラマーの作業量を大幅に削減する痕跡のない埋め込みポイントが必要となる.
インデンテーションレス埋め込み方式
メリットとデメリット
方式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>
ページ滞留時間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>
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>