├── .buildscript └── test.sh ├── .travis.yml ├── LICENSE ├── README.md ├── Sample ├── .gitignore ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── hackerli │ │ │ └── sample │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── hackerli │ │ │ │ └── sample │ │ │ │ └── MainActivity.java │ │ └── res │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── hackerli │ │ └── sample │ │ └── ExampleUnitTest.java ├── build.gradle ├── com.hackerli.sample.trace.html ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── method-tracking ├── .gitignore ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── repo │ └── com │ │ └── uniquestudio │ │ └── method-tracking │ │ ├── 1.0.5 │ │ ├── method-tracking-1.0.5-groovydoc.jar │ │ ├── method-tracking-1.0.5-groovydoc.jar.md5 │ │ ├── method-tracking-1.0.5-groovydoc.jar.sha1 │ │ ├── method-tracking-1.0.5-javadoc.jar │ │ ├── method-tracking-1.0.5-javadoc.jar.md5 │ │ ├── method-tracking-1.0.5-javadoc.jar.sha1 │ │ ├── method-tracking-1.0.5-sources.jar │ │ ├── method-tracking-1.0.5-sources.jar.md5 │ │ ├── method-tracking-1.0.5-sources.jar.sha1 │ │ ├── method-tracking-1.0.5.jar │ │ ├── method-tracking-1.0.5.jar.md5 │ │ ├── method-tracking-1.0.5.jar.sha1 │ │ ├── method-tracking-1.0.5.pom │ │ ├── method-tracking-1.0.5.pom.md5 │ │ └── method-tracking-1.0.5.pom.sha1 │ │ ├── 1.0.6 │ │ ├── method-tracking-1.0.6-groovydoc.jar │ │ ├── method-tracking-1.0.6-groovydoc.jar.md5 │ │ ├── method-tracking-1.0.6-groovydoc.jar.sha1 │ │ ├── method-tracking-1.0.6-javadoc.jar │ │ ├── method-tracking-1.0.6-javadoc.jar.md5 │ │ ├── method-tracking-1.0.6-javadoc.jar.sha1 │ │ ├── method-tracking-1.0.6-sources.jar │ │ ├── method-tracking-1.0.6-sources.jar.md5 │ │ ├── method-tracking-1.0.6-sources.jar.sha1 │ │ ├── method-tracking-1.0.6.jar │ │ ├── method-tracking-1.0.6.jar.md5 │ │ ├── method-tracking-1.0.6.jar.sha1 │ │ ├── method-tracking-1.0.6.pom │ │ ├── method-tracking-1.0.6.pom.md5 │ │ └── method-tracking-1.0.6.pom.sha1 │ │ ├── 1.0 │ │ ├── method-tracking-1.0.jar │ │ ├── method-tracking-1.0.jar.md5 │ │ ├── method-tracking-1.0.jar.sha1 │ │ ├── method-tracking-1.0.pom │ │ ├── method-tracking-1.0.pom.md5 │ │ └── method-tracking-1.0.pom.sha1 │ │ ├── maven-metadata.xml │ │ ├── maven-metadata.xml.md5 │ │ └── maven-metadata.xml.sha1 ├── settings.gradle └── src │ ├── main │ ├── groovy │ │ └── com │ │ │ └── uniquestudio │ │ │ ├── HtmlGenerator.groovy │ │ │ ├── MethodInfo.groovy │ │ │ ├── MethodPlugin.groovy │ │ │ ├── MethodTrackingTask.groovy │ │ │ ├── TrackExtension.groovy │ │ │ └── Utils.groovy │ └── resources │ │ └── META-INF │ │ └── gradle-plugins │ │ └── com.uniquestudio.method-tracking.properties │ └── test │ └── groovy │ └── com.uniquestudio │ └── MethodTrackingTest.groovy └── screenshot ├── s_0.png └── s_1.png /.buildscript/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Start testing" 3 | 4 | cd method-tracking 5 | echo "Into method-tracking folder" 6 | ls 7 | 8 | ./gradlew --stacktrace test 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: groovy 4 | groovy: 5 | - 2.3.6 6 | - 2.3.9 7 | jdk: 8 | - oraclejdk8 9 | 10 | script: 11 | - ./.buildscript/test.sh 12 | 13 | 14 | before_cache: 15 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 16 | cache: 17 | directories: 18 | - $HOME/.gradle/caches/ 19 | - $HOME/.gradle/wrapper/ 20 | 21 | notifications: 22 | email: false 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | opyright 2017 coxier. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Method Tracking 2 | 3 | # ![building](https://travis-ci.org/CoXier/AppMethodTracking.svg?branch=master) 4 | 5 | A plugin to display how methods are called in application. 6 | 7 | [Live Demo](http://coxier.github.io/AppMethodTracking.html) 8 | 9 | # Usage 10 | 11 | ## Stpe1 12 | Add these to your root `build.gradle`. 13 | 14 | ```groovy 15 | buildscript { 16 | repositories { 17 | maven { 18 | url "https://plugins.gradle.org/m2/" 19 | } 20 | } 21 | dependencies { 22 | classpath "gradle.plugin.com.uniquestudio:method-tracking:1.0.6" 23 | } 24 | } 25 | ``` 26 | Don't forget : 27 | 28 | ```groovy 29 | apply plugin: "com.uniquestudio.method-tracking" 30 | ``` 31 | 32 | ## Step2 33 | First find where you want to debug.In my demo I care about how to wear cloth,so I add two lines around `wearCloth` like this: 34 | 35 | ```groovy 36 | Debug.startMethodTracing(getPackageName()); 37 | wearCloth(); 38 | Debug.stopMethodTracing(); 39 | 40 | public void wearCloth() { 41 | putOnCoat(); 42 | putOnPants(); 43 | putOnShoes(); 44 | putOnHat(); 45 | } 46 | 47 | 48 | private void putOnPants() { 49 | 50 | } 51 | 52 | private void putOnCoat() { 53 | 54 | } 55 | 56 | private void putOnHat() { 57 | // Put on hat 58 | } 59 | 60 | 61 | public void putOnShoes() { 62 | putOnSocks(); 63 | // Put on shoes 64 | } 65 | 66 | public void putOnSocks() { 67 | // Put on socks 68 | } 69 | ``` 70 | ## Step3 71 | Now let's start configure this plugin.In your app module, add `method-tracking` closure. 72 | 73 | ```groovy 74 | methodTracking{ 75 | traceName = 'com.hackerli.sample.trace' 76 | filterList = ['com.hackerli.sample'] 77 | } 78 | ``` 79 | * `traceName` is from the method `Debug.startMethodTracing(traceName)` 80 | * `filterList` is used to filter some extra methods.We usually use package name. 81 | 82 | ## Step4 83 | ```groovy 84 | ./gradlew track 85 | ``` 86 | After above steps,[traceName.html](http://coxier.github.io/AppMethodTracking.html) is created. 87 | 88 | Its output like this: 89 | 90 | 91 | 92 | The digit is `useces`. 93 | 94 | 95 | In html,I add click event that means you can toggle these elements that have children.For example if I click `com.hackerli.sample.MainActivity.putOnShoes` above line,I will get: 96 | 97 | 98 | 99 | 100 | # THANKS 101 | I am inspired by [AppMethodOrder](https://github.com/zjw-swun/AppMethodOrder),espically how to compatible Windows os in groovy script or gradle script. 102 | 103 | # LICENSE 104 | ``` 105 | Copyright 2017 coxier. 106 | 107 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 108 | 109 | http://www.apache.org/licenses/LICENSE-2.0 110 | 111 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 112 | ``` 113 | -------------------------------------------------------------------------------- /Sample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .DS_Store 5 | /build 6 | /captures 7 | .externalNativeBuild 8 | .idea 9 | *.trace -------------------------------------------------------------------------------- /Sample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Sample/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.uniquestudio.method-tracking' 3 | 4 | android { 5 | compileSdkVersion 25 6 | buildToolsVersion "25.0.2" 7 | defaultConfig { 8 | applicationId "com.hackerli.sample" 9 | minSdkVersion 15 10 | targetSdkVersion 25 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | compile fileTree(dir: 'libs', include: ['*.jar']) 25 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 26 | exclude group: 'com.android.support', module: 'support-annotations' 27 | }) 28 | compile 'com.android.support:appcompat-v7:25.1.1' 29 | testCompile 'junit:junit:4.12' 30 | } 31 | 32 | methodTracking{ 33 | traceName = 'com.hackerli.sample.trace' 34 | filterList = ['com.hackerli.sample'] 35 | } -------------------------------------------------------------------------------- /Sample/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/coxier/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /Sample/app/src/androidTest/java/com/hackerli/sample/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.hackerli.sample; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.hackerli.sample", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Sample/app/src/main/java/com/hackerli/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.hackerli.sample; 2 | 3 | import android.Manifest; 4 | import android.content.pm.PackageManager; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.os.Debug; 8 | import android.support.annotation.RequiresApi; 9 | import android.support.v4.content.ContextCompat; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.view.View; 12 | 13 | public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_main); 19 | findViewById(R.id.bt_wear_cloth).setOnClickListener(this); 20 | } 21 | 22 | 23 | @RequiresApi(api = Build.VERSION_CODES.M) 24 | @Override 25 | public void onClick(View v) { 26 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 27 | requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); 28 | }else{ 29 | Debug.startMethodTracing(getPackageName()); 30 | wearCloth(); 31 | Debug.stopMethodTracing(); 32 | } 33 | } 34 | 35 | 36 | public void wearCloth() { 37 | putOnCoat(); 38 | putOnPants(); 39 | putOnShoes(); 40 | putOnHat(); 41 | } 42 | 43 | private void putOnPants() { 44 | 45 | } 46 | 47 | private void putOnCoat() { 48 | 49 | } 50 | 51 | private void putOnHat() { 52 | // Put on hat 53 | } 54 | 55 | 56 | public void putOnShoes() { 57 | putOnSocks(); 58 | // Put on shoes 59 | } 60 | 61 | public void putOnSocks() { 62 | // Put on socks 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Sample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 |