├── .gitignore ├── .idea ├── $CACHE_FILE$ ├── checkstyle-idea.xml ├── codeStyles │ └── Project.xml ├── encodings.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── aop2 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── aop2 │ │ │ ├── Animal.java │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── dialog.xml │ │ └── simple_list_item.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── aop2 │ └── ExampleUnitTest.java ├── aspectj ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── aspectj │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── example │ │ └── aspectj │ │ ├── HookAddOnScrollListenerHelper.java │ │ ├── HookOnClickListener.java │ │ ├── HookRecyclerViewOnBindViewHolder.java │ │ ├── HookTextChangedListener.java │ │ ├── SuperClassReflectionUtils.java │ │ ├── Tracker.java │ │ ├── TrackerAspect.java │ │ ├── ViewAspect.java │ │ └── ViewPath.java │ └── test │ └── java │ └── com │ └── example │ └── aspectj │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Abstraction issuesJava 10 | 11 | 12 | Android 13 | 14 | 15 | Code style issuesJava 16 | 17 | 18 | Compiler issuesJava 19 | 20 | 21 | CorrectnessLintAndroid 22 | 23 | 24 | Declaration redundancyJava 25 | 26 | 27 | GPathGroovy 28 | 29 | 30 | Groovy 31 | 32 | 33 | IconsUsabilityLintAndroid 34 | 35 | 36 | Inheritance issuesJava 37 | 38 | 39 | Java 40 | 41 | 42 | Java 9Java language level migration aidsJava 43 | 44 | 45 | Java language level migration aidsJava 46 | 47 | 48 | Kotlin 49 | 50 | 51 | LintAndroid 52 | 53 | 54 | Other problemsKotlin 55 | 56 | 57 | PerformanceJava 58 | 59 | 60 | PerformanceLintAndroid 61 | 62 | 63 | Potentially confusing code constructsGroovy 64 | 65 | 66 | Probable bugsJava 67 | 68 | 69 | Serialization issuesJava 70 | 71 | 72 | Style issuesKotlin 73 | 74 | 75 | UsabilityLintAndroid 76 | 77 | 78 | 79 | 80 | Android 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 插件使用 2 | 1. 在项目根目录的build.gradle里依赖AspectJX 3 | ``` 4 | dependencies { 5 | classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10' 6 | // 如果build:gradle在3.6.0以下,使用2.0.8版本 7 | } 8 | ``` 9 | 2. 在app目录的build.gradle里添加Aspectj的插件 10 | `apply plugin: 'android-aspectjx'` 11 | 3. 在app目录的build.gradle里去掉不必要侵入的类 12 | 不去掉可能会导致 java.util.zip.ZipException: zip file is empty 或者 classNotDefFoundException 13 | ``` 14 | aspectjx{ 15 | exclude 'com.google','com.squareup','com.alipay','org.apache' 16 | } 17 | ``` 18 | 4. 如果你使用得分组件时androidx版本则用master分支,否则使用support分支 19 | ## 文章介绍 20 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'android-aspectjx' 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.example.aop2" 9 | minSdkVersion 24 10 | targetSdkVersion 29 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: "libs", include: ["*.jar"]) 27 | implementation 'androidx.appcompat:appcompat:1.1.0' 28 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 29 | implementation 'androidx.recyclerview:recyclerview:1.1.0' 30 | testImplementation 'junit:junit:4.12' 31 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 32 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 33 | implementation project(':aspectj') 34 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/aop2/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.aop2; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.example.aop2", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/aop2/Animal.java: -------------------------------------------------------------------------------- 1 | package com.example.aop2; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * @author youer 7 | * @date 2020/8/7 8 | */ 9 | public class Animal { 10 | private static final String TAG = "Animal"; 11 | 12 | public void fly() { 13 | Log.e(TAG, "animal fly method:" + this.toString() + "#fly"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/aop2/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.aop2; 2 | 3 | import android.app.Dialog; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.text.Editable; 7 | import android.text.TextWatcher; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.EditText; 13 | import android.widget.LinearLayout; 14 | import android.widget.PopupWindow; 15 | import android.widget.TextView; 16 | 17 | import androidx.annotation.NonNull; 18 | import androidx.appcompat.app.AppCompatActivity; 19 | import androidx.recyclerview.widget.LinearLayoutManager; 20 | import androidx.recyclerview.widget.RecyclerView; 21 | 22 | public class MainActivity extends AppCompatActivity { 23 | private static final String TAG = "MainActivity"; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_main); 29 | 30 | Animal animal = new Animal(); 31 | Log.d(TAG, " onCreate fly start..."); 32 | animal.fly(); 33 | 34 | // ViewGroup viewGroup = (ViewGroup)findViewById(ID_ANDROID_CONTENT); 35 | // viewGroup.getChildCount(); 36 | // TextView textView = findViewById(R.id.text); 37 | // textView.setOnClickListener(new View.OnClickListener() { 38 | // @Override 39 | // public void onClick(View v) { 40 | // 41 | // } 42 | // }); 43 | 44 | // textView.setOnClickListener(new View.OnClickListener() { 45 | // @Override 46 | // public void onClick(View v) { 47 | // Log.d(TAG, "onClick: "); 48 | // } 49 | // }); 50 | // 51 | // textView.setOnLongClickListener(new View.OnLongClickListener() { 52 | // @Override 53 | // public boolean onLongClick(View v) { 54 | // return false; 55 | // } 56 | // }); 57 | View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog, null); 58 | final PopupWindow popWnd = new PopupWindow(this); 59 | popWnd.setContentView(contentView); 60 | 61 | EditText editText = findViewById(R.id.edit); 62 | editText.addTextChangedListener(new TextWatcher() { 63 | @Override 64 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 65 | 66 | } 67 | 68 | @Override 69 | public void onTextChanged(CharSequence s, int start, int before, int count) { 70 | Log.d(TAG, "onTextChanged: " + s.toString()); 71 | } 72 | 73 | @Override 74 | public void afterTextChanged(Editable s) { 75 | 76 | } 77 | }); 78 | 79 | RecyclerView recyclerView = findViewById(R.id.list); 80 | recyclerView.setAdapter(new RecyclerViewAdapter()); 81 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 82 | recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 83 | @Override 84 | public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { 85 | super.onScrollStateChanged(recyclerView, newState); 86 | } 87 | 88 | @Override 89 | public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { 90 | super.onScrolled(recyclerView, dx, dy); 91 | Log.d(TAG, "onScrolled: dx--" + dx + ";dy--" + dy); 92 | } 93 | }); 94 | 95 | final TextView title = findViewById(R.id.title); 96 | new Handler().postDelayed(new Runnable() { 97 | @Override 98 | public void run() { 99 | Log.d(TAG, "run: "); 100 | title.setOnClickListener(new View.OnClickListener() { 101 | @Override 102 | public void onClick(View v) { 103 | Dialog dialog = new Dialog(MainActivity.this); 104 | dialog.setContentView(R.layout.dialog); 105 | dialog.show(); 106 | // popWnd.showAsDropDown(title); 107 | } 108 | }); 109 | } 110 | }, 1500); 111 | 112 | } 113 | 114 | private class RecyclerViewAdapter extends RecyclerView.Adapter { 115 | private static final String TAG = "RecyclerViewAdapter"; 116 | 117 | @NonNull 118 | @Override 119 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 120 | View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.simple_list_item, parent, false); 121 | Log.d(TAG, "onCreateViewHolder: "); 122 | return new ViewHolder(view); 123 | } 124 | 125 | @Override 126 | public void onBindViewHolder(ViewHolder holder, int position) { 127 | Log.d(TAG, "onBindViewHolder: "); 128 | holder.textView.setText("第" + position + "行数据"); 129 | holder.textView.setOnClickListener(new View.OnClickListener() { 130 | @Override 131 | public void onClick(View v) { 132 | 133 | } 134 | }); 135 | } 136 | 137 | @Override 138 | public int getItemCount() { 139 | return 10; 140 | } 141 | 142 | class ViewHolder extends RecyclerView.ViewHolder { 143 | TextView textView; 144 | 145 | private ViewHolder(View itemView) { 146 | super(itemView); 147 | textView = (TextView) itemView.findViewById(R.id.list_title); 148 | } 149 | } 150 | } 151 | 152 | public void onTestClick(View view) { 153 | // CheckBox checkBox = findViewById(R.id.checkbox); 154 | // checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 155 | // @Override 156 | // public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 157 | // Log.d(TAG, "onCheckedChanged: "); 158 | // } 159 | // }); 160 | 161 | TextView textView = new TextView(this); 162 | textView.setText("sfdadasdas"); 163 | textView.setOnClickListener(new View.OnClickListener() { 164 | @Override 165 | public void onClick(View v) { 166 | Log.d(TAG, "onClick: "); 167 | } 168 | }); 169 | LinearLayout layout = findViewById(R.id.container); 170 | layout.addView(textView, LinearLayout.LayoutParams.WRAP_CONTENT, 200); 171 | } 172 | 173 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 |