├── .gitignore ├── .travis.yml ├── ART ├── android_god_eye_connect.jpg └── android_god_eye_logo.png ├── AndroidGodEye-MethodCanary.js ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── README_zh.md ├── android-godeye-idea-plugin ├── AndroidGodEye_plugin.bat ├── AndroidGodEye_plugin.sh ├── README.md ├── android-godeye-idea-plugin.jar ├── resources │ ├── META-INF │ │ └── plugin.xml │ └── icons │ │ ├── android_god_eye_logo.png │ │ └── android_god_eye_logo_2.png └── src │ └── cn │ └── hikyson │ └── godeye │ └── ideaplugin │ └── OpenAction.java ├── android-godeye-monitor-dashboard ├── .eslintrc.json ├── .gitignore ├── README.md ├── deploy.py ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── MockData.js │ ├── appSizeInfo │ └── appsize.js │ ├── appinfo │ └── appInfo.js │ ├── assets │ └── logo.png │ ├── batteryinfo │ └── batteryInfo.js │ ├── block │ ├── block.js │ └── changeBlockConfigForm.js │ ├── communication │ └── websocket.js │ ├── cpu │ ├── cpu.js │ └── cpu_info.js │ ├── crash │ └── crash.js │ ├── fps │ └── fps.js │ ├── heap │ ├── heap.js │ └── heap_info.js │ ├── imagecanary │ └── imagecanary.js │ ├── index.css │ ├── index.js │ ├── libs │ └── util.js │ ├── logo.png │ ├── memoryleak │ └── memoryLeak.js │ ├── methodcanary │ ├── methodcanary.js │ ├── methodcanary_thread.js │ └── methodcanary_thread_tree.js │ ├── network │ └── network.js │ ├── notification │ └── notification_container.js │ ├── pageload │ └── pageload.js │ ├── pss │ └── pss.js │ ├── ram │ └── ram.js │ ├── refreshstatus │ └── refreshStatus.js │ ├── registerServiceWorker.js │ ├── startup │ └── startup.js │ ├── thread │ └── thread.js │ ├── traffic │ ├── traffic.js │ └── traffic_info.js │ └── viewcanary │ └── viewcanary.js ├── android-godeye-monitor ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── hikyson │ │ └── godeye │ │ └── ExampleInstrumentedTest.java │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── android-godeye-dashboard │ │ ├── asset-manifest.json │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── manifest.json │ │ ├── service-worker.js │ │ └── static │ │ ├── css │ │ ├── main.187d6dcc.css │ │ └── main.187d6dcc.css.map │ │ └── js │ │ ├── main.f223975e.js │ │ └── main.f223975e.js.map │ ├── java │ └── cn │ │ └── hikyson │ │ └── godeye │ │ └── monitor │ │ ├── GodEyeMonitor.java │ │ ├── modules │ │ ├── BlockSimpleInfo.java │ │ ├── NetworkSummaryInfo.java │ │ ├── PageLifecycleProcessedEvent.java │ │ ├── appinfo │ │ │ ├── AppInfo.java │ │ │ └── AppInfoLabel.java │ │ ├── battery │ │ │ ├── BatteryInfoFactory.java │ │ │ └── BatterySummaryInfo.java │ │ ├── leak │ │ │ ├── LeakConverter.java │ │ │ └── LeakSimpleInfo.java │ │ └── thread │ │ │ └── ThreadRunningProcessClassifier.java │ │ ├── notification │ │ └── MonitorNotificationListener.java │ │ └── server │ │ ├── ConvertServerMessageFunction.java │ │ ├── GodEyeMonitorServer.java │ │ ├── HttpStaticProcessor.java │ │ ├── Messager.java │ │ ├── ModuleDriver.java │ │ ├── SendMessageConsumer.java │ │ ├── ServerMessage.java │ │ ├── UnhandledException.java │ │ ├── WebSocketAppinfoProcessor.java │ │ ├── WebSocketBizProcessor.java │ │ ├── WebSocketBizRouter.java │ │ ├── WebSocketChangeBlockConfigProcessor.java │ │ ├── WebSocketClientOnlineProcessor.java │ │ ├── WebSocketMethodCanaryProcessor.java │ │ └── WebSocketProcessor.java │ └── res │ └── values │ └── strings.xml ├── android-godeye-sample ├── .gitignore ├── AndroidGodEye.keystore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── android-godeye-config │ │ ├── install.config │ │ └── install_release.config │ ├── java │ └── cn │ │ └── hikyson │ │ └── godeye │ │ └── sample │ │ ├── AnimationFragmentV4.java │ │ ├── AppInfoProxyImpl.java │ │ ├── ComplexLayoutActivity.java │ │ ├── ConsumeFragment.java │ │ ├── DeadLockMaker.java │ │ ├── ImageActivity.java │ │ ├── InstallFragment.java │ │ ├── LeakActivity.java │ │ ├── LeakActivityV4.java │ │ ├── LeakFragment.java │ │ ├── LeakFragmentV4.java │ │ ├── LogObserver.java │ │ ├── LogView.java │ │ ├── Loggable.java │ │ ├── Main2Activity.java │ │ ├── SampleApp.java │ │ ├── SecondActivity.java │ │ ├── SplashActivity.java │ │ ├── StartupTracer.java │ │ ├── SubProcessIntentService.java │ │ ├── ThirdActivity.java │ │ ├── ToolsFragment.java │ │ ├── fragmentlifecycle │ │ ├── BlankFragment1.java │ │ └── BlankFragment2.java │ │ ├── methodcanary │ │ ├── BaseActivity.java │ │ ├── BaseFragment.java │ │ └── Child0Fragment.java │ │ └── utils │ │ └── ThreadUtil.java │ ├── res │ ├── drawable-hdpi │ │ ├── ic_delete.png │ │ └── ic_vertical_align_bottom.png │ ├── drawable-mdpi │ │ ├── ic_delete.png │ │ └── ic_vertical_align_bottom.png │ ├── drawable-xhdpi │ │ ├── ic_delete.png │ │ └── ic_vertical_align_bottom.png │ ├── drawable-xxhdpi │ │ ├── ic_delete.png │ │ ├── ic_vertical_align_bottom.png │ │ ├── image_test1.png │ │ └── image_test2.png │ ├── drawable-xxxhdpi │ │ ├── ic_delete.png │ │ └── ic_vertical_align_bottom.png │ ├── drawable │ │ ├── ic_follow.xml │ │ ├── ic_launcher_background.xml │ │ └── shape_follow_selected.xml │ ├── layout │ │ ├── activity_complex_layout.xml │ │ ├── activity_image.xml │ │ ├── activity_leak.xml │ │ ├── activity_leak_v4.xml │ │ ├── activity_main.xml │ │ ├── activity_main2.xml │ │ ├── activity_second.xml │ │ ├── activity_splash.xml │ │ ├── activity_third.xml │ │ ├── fragment_animation_v4.xml │ │ ├── fragment_blank_fragment1.xml │ │ ├── fragment_blank_fragment2.xml │ │ ├── fragment_consume.xml │ │ ├── fragment_install.xml │ │ ├── fragment_leak.xml │ │ ├── fragment_leak_v4.xml │ │ ├── fragment_tools.xml │ │ └── view_log_layout.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 │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── web_hi_res_512.png ├── android-godeye-toolboxes ├── android-godeye-leakcanary │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── cn │ │ │ └── hikyson │ │ │ └── test │ │ │ └── android_godeye_leakcanary │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── cn │ │ │ │ └── hikyson │ │ │ │ └── android │ │ │ │ └── godeye │ │ │ │ └── leakcanary │ │ │ │ └── GodEyePluginLeakCanary.java │ │ └── res │ │ │ ├── layout │ │ │ └── leak_canary_heap_dump_toast.xml │ │ │ └── values │ │ │ └── values.xml │ │ └── test │ │ └── java │ │ └── cn │ │ └── hikyson │ │ └── test │ │ └── android_godeye_leakcanary │ │ └── ExampleUnitTest.java ├── android-godeye-okhttp │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── cn │ │ │ └── hikyson │ │ │ └── android │ │ │ └── godeye │ │ │ └── okhttp │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── cn │ │ │ │ └── hikyson │ │ │ │ └── android │ │ │ │ └── godeye │ │ │ │ └── okhttp │ │ │ │ ├── GodEyePluginOkNetwork.java │ │ │ │ ├── HttpContent.java │ │ │ │ ├── HttpContentTimeMapping.java │ │ │ │ ├── HttpRequest.java │ │ │ │ ├── HttpResponse.java │ │ │ │ ├── OkHttpNetworkContentInterceptor.java │ │ │ │ └── OkNetworkEventListener.java │ │ └── res │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── cn │ │ └── hikyson │ │ └── android │ │ └── godeye │ │ └── okhttp │ │ └── ExampleUnitTest.java └── android-godeye-xcrash │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── hikyson │ │ └── android │ │ └── godeye │ │ └── xcrash │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ └── hikyson │ │ │ └── android │ │ │ └── godeye │ │ │ └── xcrash │ │ │ └── GodEyePluginXCrash.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── cn │ └── hikyson │ └── android │ └── godeye │ └── xcrash │ └── ExampleUnitTest.java ├── android-godeye ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── gradle.properties ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── aidl │ │ └── android │ │ │ └── content │ │ │ └── pm │ │ │ ├── IPackageStatsObserver.aidl │ │ │ └── PackageStats.aidl │ ├── ic_launcher-web.png │ ├── java │ │ └── cn │ │ │ └── hikyson │ │ │ └── godeye │ │ │ └── core │ │ │ ├── GodEye.java │ │ │ ├── GodEyeConfig.java │ │ │ ├── GodEyeHelper.java │ │ │ ├── GodEyeInitContentProvider.java │ │ │ ├── exceptions │ │ │ ├── UnexpectException.java │ │ │ └── UninstallException.java │ │ │ ├── helper │ │ │ ├── AndroidDebug.java │ │ │ ├── ChoreographerInjecor.java │ │ │ ├── CrashStore.java │ │ │ ├── Notifier.java │ │ │ ├── RxModule.java │ │ │ └── SimpleActivityLifecycleCallbacks.java │ │ │ ├── internal │ │ │ ├── Engine.java │ │ │ ├── Install.java │ │ │ ├── ProduceableSubject.java │ │ │ ├── Producer.java │ │ │ ├── SubjectSupport.java │ │ │ ├── modules │ │ │ │ ├── appsize │ │ │ │ │ ├── AppSize.java │ │ │ │ │ ├── AppSizeConfig.java │ │ │ │ │ ├── AppSizeInfo.java │ │ │ │ │ └── AppSizeUtil.java │ │ │ │ ├── battery │ │ │ │ │ ├── Battery.java │ │ │ │ │ ├── BatteryChangeReceiver.java │ │ │ │ │ ├── BatteryConfig.java │ │ │ │ │ ├── BatteryEngine.java │ │ │ │ │ └── BatteryInfo.java │ │ │ │ ├── cpu │ │ │ │ │ ├── Cpu.java │ │ │ │ │ ├── CpuConfig.java │ │ │ │ │ ├── CpuEngine.java │ │ │ │ │ ├── CpuInfo.java │ │ │ │ │ ├── CpuSnapshot.java │ │ │ │ │ └── CpuUsage.java │ │ │ │ ├── crash │ │ │ │ │ ├── Crash.java │ │ │ │ │ ├── CrashConfig.java │ │ │ │ │ ├── CrashConstant.java │ │ │ │ │ └── CrashInfo.java │ │ │ │ ├── fps │ │ │ │ │ ├── Fps.java │ │ │ │ │ ├── FpsConfig.java │ │ │ │ │ ├── FpsEngine.java │ │ │ │ │ ├── FpsInfo.java │ │ │ │ │ └── FpsMonitor.java │ │ │ │ ├── imagecanary │ │ │ │ │ ├── BitmapInfo.java │ │ │ │ │ ├── BitmapInfoAnalyzer.java │ │ │ │ │ ├── DefaultBitmapInfoAnalyzer.java │ │ │ │ │ ├── DefaultImageCanaryConfigProvider.java │ │ │ │ │ ├── ImageCanary.java │ │ │ │ │ ├── ImageCanaryConfig.java │ │ │ │ │ ├── ImageCanaryConfigProvider.java │ │ │ │ │ ├── ImageCanaryInternal.java │ │ │ │ │ └── ImageIssue.java │ │ │ │ ├── leakdetector │ │ │ │ │ ├── DefaultLeakRefInfoProvider.java │ │ │ │ │ ├── Leak.java │ │ │ │ │ ├── LeakConfig.java │ │ │ │ │ ├── LeakDetector.java │ │ │ │ │ ├── LeakInfo.java │ │ │ │ │ ├── LeakQueue.java │ │ │ │ │ ├── LeakRefInfo.java │ │ │ │ │ └── LeakRefInfoProvider.java │ │ │ │ ├── memory │ │ │ │ │ ├── Heap.java │ │ │ │ │ ├── HeapConfig.java │ │ │ │ │ ├── HeapEngine.java │ │ │ │ │ ├── HeapInfo.java │ │ │ │ │ ├── MemoryUtil.java │ │ │ │ │ ├── NativeHeapInfo.java │ │ │ │ │ ├── Pss.java │ │ │ │ │ ├── PssConfig.java │ │ │ │ │ ├── PssEngine.java │ │ │ │ │ ├── PssInfo.java │ │ │ │ │ ├── Ram.java │ │ │ │ │ ├── RamConfig.java │ │ │ │ │ ├── RamEngine.java │ │ │ │ │ └── RamInfo.java │ │ │ │ ├── methodcanary │ │ │ │ │ ├── MethodCanary.java │ │ │ │ │ ├── MethodCanaryConfig.java │ │ │ │ │ ├── MethodCanaryConverter.java │ │ │ │ │ └── MethodsRecordInfo.java │ │ │ │ ├── network │ │ │ │ │ ├── Network.java │ │ │ │ │ ├── NetworkConfig.java │ │ │ │ │ ├── NetworkContent.java │ │ │ │ │ ├── NetworkInfo.java │ │ │ │ │ └── NetworkTime.java │ │ │ │ ├── pageload │ │ │ │ │ ├── ActivityLifecycleCallbacks.java │ │ │ │ │ ├── ActivityLifecycleEvent.java │ │ │ │ │ ├── DefaultPageInfoProvider.java │ │ │ │ │ ├── FragmentLifecycleCallbacks.java │ │ │ │ │ ├── FragmentLifecycleCallbacksV4.java │ │ │ │ │ ├── FragmentLifecycleEvent.java │ │ │ │ │ ├── LifecycleEvent.java │ │ │ │ │ ├── PageDrawMonitor.java │ │ │ │ │ ├── PageInfo.java │ │ │ │ │ ├── PageInfoProvider.java │ │ │ │ │ ├── PageLifecycleEventInfo.java │ │ │ │ │ ├── PageLifecycleEventWithTime.java │ │ │ │ │ ├── PageLifecycleMethodEventTypes.java │ │ │ │ │ ├── PageLifecycleRecords.java │ │ │ │ │ ├── PageType.java │ │ │ │ │ ├── Pageload.java │ │ │ │ │ ├── PageloadConfig.java │ │ │ │ │ └── PageloadUtil.java │ │ │ │ ├── sm │ │ │ │ │ ├── BlockInfo.java │ │ │ │ │ ├── Sm.java │ │ │ │ │ ├── SmConfig.java │ │ │ │ │ └── core │ │ │ │ │ │ ├── AbstractSampler.java │ │ │ │ │ │ ├── BlockListener.java │ │ │ │ │ │ ├── CpuSampler.java │ │ │ │ │ │ ├── LongBlockInfo.java │ │ │ │ │ │ ├── LooperMonitor.java │ │ │ │ │ │ ├── MemoryInfo.java │ │ │ │ │ │ ├── ShortBlockInfo.java │ │ │ │ │ │ ├── SmCore.java │ │ │ │ │ │ └── StackSampler.java │ │ │ │ ├── startup │ │ │ │ │ ├── Startup.java │ │ │ │ │ ├── StartupConfig.java │ │ │ │ │ └── StartupInfo.java │ │ │ │ ├── thread │ │ │ │ │ ├── DefaultThreadTagger.java │ │ │ │ │ ├── ExcludeSystemThreadFilter.java │ │ │ │ │ ├── SimpleThreadFilter.java │ │ │ │ │ ├── ThreadConfig.java │ │ │ │ │ ├── ThreadDump.java │ │ │ │ │ ├── ThreadEngine.java │ │ │ │ │ ├── ThreadFilter.java │ │ │ │ │ ├── ThreadInfo.java │ │ │ │ │ └── ThreadTagger.java │ │ │ │ ├── traffic │ │ │ │ │ ├── Traffic.java │ │ │ │ │ ├── TrafficConfig.java │ │ │ │ │ ├── TrafficEngine.java │ │ │ │ │ ├── TrafficInfo.java │ │ │ │ │ └── TrafficSnapshot.java │ │ │ │ └── viewcanary │ │ │ │ │ ├── ViewBgUtil.java │ │ │ │ │ ├── ViewCanary.java │ │ │ │ │ ├── ViewCanaryConfig.java │ │ │ │ │ ├── ViewCanaryInternal.java │ │ │ │ │ ├── ViewIssueInfo.java │ │ │ │ │ └── levenshtein │ │ │ │ │ ├── ViewIdWithSize.java │ │ │ │ │ ├── ViewWithSizeInsDelInterface.java │ │ │ │ │ ├── ViewWithSizeSubstitutionInterface.java │ │ │ │ │ └── WeightedLevenshtein.java │ │ │ └── notification │ │ │ │ ├── DefaultNotificationConfig.java │ │ │ │ ├── LocalNotificationListener.java │ │ │ │ ├── LocalNotificationListenerService.java │ │ │ │ ├── NotificationConfig.java │ │ │ │ ├── NotificationConsumer.java │ │ │ │ ├── NotificationContent.java │ │ │ │ ├── NotificationListener.java │ │ │ │ ├── NotificationObserver.java │ │ │ │ └── NotificationObserverManager.java │ │ │ ├── monitor │ │ │ ├── AppInfoConext.java │ │ │ └── AppInfoLabel.java │ │ │ └── utils │ │ │ ├── ActivityStackUtil.java │ │ │ ├── ImageUtil.java │ │ │ ├── IoUtil.java │ │ │ ├── IteratorUtil.java │ │ │ ├── JsonUtil.java │ │ │ ├── L.java │ │ │ ├── ProcessUtils.java │ │ │ ├── ReflectUtil.java │ │ │ ├── StacktraceUtil.java │ │ │ ├── ThreadUtil.java │ │ │ └── ViewUtil.java │ └── res │ │ ├── drawable-hdpi │ │ └── androidgodeye_ic_remove_red_eye.png │ │ ├── drawable-mdpi │ │ └── androidgodeye_ic_remove_red_eye.png │ │ ├── drawable-xhdpi │ │ └── androidgodeye_ic_remove_red_eye.png │ │ ├── drawable-xxhdpi │ │ └── androidgodeye_ic_remove_red_eye.png │ │ ├── drawable-xxxhdpi │ │ └── androidgodeye_ic_remove_red_eye.png │ │ ├── mipmap-hdpi │ │ └── androidgodeye_ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── androidgodeye_ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── androidgodeye_ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── androidgodeye_ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── androidgodeye_ic_launcher.png │ │ └── values │ │ ├── strings.xml │ │ └── values.xml │ └── test │ ├── java │ ├── android │ │ └── text │ │ │ └── TextUtils.java │ └── cn │ │ └── hikyson │ │ ├── android │ │ └── godeye │ │ │ ├── leakcanary │ │ │ └── GodEyePluginLeakCanary.java │ │ │ └── xcrash │ │ │ └── GodEyePluginXCrash.java │ │ └── godeye │ │ └── core │ │ ├── GodEyeConfigTest.java │ │ ├── GodEyeHelperTest.java │ │ ├── GodEyeInitContentProviderTest.java │ │ ├── GodEyeTest.java │ │ ├── helper │ │ ├── AndroidDebugTest.java │ │ ├── ChoreographerHelper.java │ │ ├── GodEyeConfigHelper.java │ │ ├── Log4Test.java │ │ ├── NotifierTest.java │ │ ├── RoboTestApplication.java │ │ ├── Test1Activity.java │ │ ├── Test1Fragment.java │ │ ├── Test1NotV4Fragment.java │ │ ├── Test2Activity.java │ │ ├── Test2Fragment.java │ │ ├── Test2NotV4FragmentActivity.java │ │ ├── Test3Activity.java │ │ ├── Test4ImageActivity.java │ │ ├── TestLeak0Activity.java │ │ ├── TestPageEvent.java │ │ ├── TestViewCanaryActivity.java │ │ ├── TestViewCanaryFragment.java │ │ └── ThreadHelper.java │ │ ├── internal │ │ ├── modules │ │ │ ├── appsize │ │ │ │ ├── AppSizeTest.java │ │ │ │ └── AppSizeUtilTest.java │ │ │ ├── battery │ │ │ │ └── BatteryTest.java │ │ │ ├── cpu │ │ │ │ ├── CpuTest.java │ │ │ │ └── CpuUsageTest.java │ │ │ ├── crash │ │ │ │ └── CrashTest.java │ │ │ ├── fps │ │ │ │ └── FpsTest.java │ │ │ ├── imagecanary │ │ │ │ ├── ImageCanaryInternalTest.java │ │ │ │ └── ImageCanaryTest.java │ │ │ ├── leakdetector │ │ │ │ ├── LeakDetectorTest.java │ │ │ │ └── release │ │ │ │ │ └── ReleaseGcTriggerTest.java │ │ │ ├── memory │ │ │ │ ├── HeapTest.java │ │ │ │ ├── MemoryUtilTest.java │ │ │ │ ├── PssTest.java │ │ │ │ └── RamTest.java │ │ │ ├── methodcanary │ │ │ │ ├── MethodCanaryConverterTest.java │ │ │ │ └── MethodCanaryTest.java │ │ │ ├── network │ │ │ │ └── NetworkTest.java │ │ │ ├── pageload │ │ │ │ ├── PageLifecycleMethodEventTypesTest.java │ │ │ │ └── PageloadTest.java │ │ │ ├── sm │ │ │ │ └── SmTest.java │ │ │ ├── startup │ │ │ │ └── StartupTest.java │ │ │ ├── thread │ │ │ │ └── ThreadDumpTest.java │ │ │ ├── traffic │ │ │ │ └── TrafficTest.java │ │ │ └── viewcanary │ │ │ │ ├── ViewCanaryInternalTest.java │ │ │ │ └── ViewCanaryTest.java │ │ └── notification │ │ │ ├── LocalNotificationListenerServiceTest.java │ │ │ └── NotificationConsumerTest.java │ │ └── utils │ │ ├── ImageUtilTest.java │ │ ├── LTest.java │ │ ├── ProcessUtilsTest.java │ │ ├── ReflectUtilTest.java │ │ ├── StacktraceUtilTest.java │ │ └── ThreadUtilTest.java │ └── resources │ ├── AndroidManifest.xml │ ├── install.config │ └── install2.config ├── build.gradle ├── gradle.properties ├── gradle ├── enable_alirepo.sh ├── github_release_support.sh ├── gradle-changelog-support.gradle ├── gradle-github-release-support.gradle ├── gradle-jacoco-support.gradle ├── gradle-jcenter-push.gradle ├── gradle-version-support.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pre_check_before_push.sh └── settings.gradle /ART/android_god_eye_connect.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/ART/android_god_eye_connect.jpg -------------------------------------------------------------------------------- /ART/android_god_eye_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/ART/android_god_eye_logo.png -------------------------------------------------------------------------------- /AndroidGodEye-MethodCanary.js: -------------------------------------------------------------------------------- 1 | /** 2 | classInfo 3 | {int access 4 | String name 5 | String superName 6 | String[] interfaces} 7 | 8 | methodInfo 9 | {int access 10 | String name 11 | String desc} 12 | **/ 13 | function isInclude(classInfo,methodInfo){ 14 | return classInfo.name.startsWith('cn/hikyson/godeye/sample') 15 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Build 4 | 5 | ### Build Sample APK 6 | 7 | Clone then build, then run `android android-godeye-sample` 8 | 9 | ### Build Debug Dashboard 10 | 11 | 1. `cd android-godeye-monitor-dashboard` 12 | 2. `npm install` or `cnpm install` if needed. 13 | 3. [`npm run bd`] or [`npm run build` then `npm run deploy`] 14 | 4. Build and run `android android-godeye-sample` 15 | 16 | ## Deploy 17 | 18 | 1. Exec `./gradlew generateChangelog -PchangelogVersion=3.1.12` to update CHANGELOG.md, 添加或删除模块需要更新README.md和[wiki](https://github.com/Kyson/AndroidGodEye/wiki) 19 | 2. Merge to master branch then tag with version name then push.(本地测试会使用gradle.properties文件中的版本号) 20 | 3. 查看编译状态:[AndroidGodEye-travis-ci](https://travis-ci.org/Kyson/AndroidGodEye/builds) 21 | 22 | ## Code 23 | 24 | Model数据类,包含Config类型 25 | 26 | 1. 必须实现Serializable接口 27 | 2. 必须@Keep 28 | 3. 内容必须可序列化 29 | 4. 必须添加toString方法 30 | 31 | ## Changelog 32 | 33 | Based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) 34 | 35 | - Added for new features. 36 | - Changed for changes in existing functionality. 37 | - Deprecated for soon-to-be removed features. 38 | - Removed for now removed features. 39 | - Fixed for any bug fixes. 40 | - Security in case of vulnerabilities. 41 | 42 | ### Git commit message 43 | 44 | ```text 45 | #Changed# 46 | This is first changed content 47 | This is second changed content 48 | #Deprecated# 49 | xxxx 50 | ``` -------------------------------------------------------------------------------- /android-godeye-idea-plugin/AndroidGodEye_plugin.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo "Make sure you have connected device with usb, you can exec 'adb devices' to do it." 4 | 5 | setlocal enabledelayedexpansion 6 | 7 | FOR /F "delims=" %%a in ('adb logcat -d ^| findstr /c:"AndroidGodEye monitor is running at port"') do (set port_running_logcat=%%a) 8 | echo "Parsed logcat %port_running_logcat%" 9 | FOR /F "tokens=1,2 delims=[]" %%a in ("%port_running_logcat%") do set port_running=%%b 10 | if "%port_running%"=="" (set port_running=5390 & echo "Can not find which port AndroidGodEye monitor is running at.") else (echo "AndroidGodEye monitor is running at %port_running%") 11 | 12 | SET /P MONITOR_PORT="Input monitor port, press 'Enter' for default %port_running%: " 13 | 14 | if "%MONITOR_PORT%"=="" set MONITOR_PORT=%port_running% 15 | 16 | echo "Use port %MONITOR_PORT%" 17 | 18 | adb forward tcp:%MONITOR_PORT% tcp:%MONITOR_PORT% && cmd /c start http://localhost:%MONITOR_PORT%/index.html 19 | 20 | echo "If it is always loading, try close and open the browser tab again." 21 | 22 | pause -------------------------------------------------------------------------------- /android-godeye-idea-plugin/AndroidGodEye_plugin.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "Make sure you have connected device with usb, you can exec to do it." 4 | 5 | port_running=`adb logcat -d | grep 'AndroidGodEye monitor is running at port' | tail -1 | cut -d '[' -f2|cut -d ']' -f1` 6 | 7 | if [[ ! -n "$port_running" ]] ;then 8 | echo "Can not find which port AndroidGodEye monitor is running at." 9 | port_running=5390 10 | else 11 | echo "AndroidGodEye monitor is running at ${port_running}" 12 | fi 13 | 14 | read -p "Input monitor port, press 'Enter' for default ${port_running}: " MONITOR_PORT 15 | 16 | if [[ ! -n "$MONITOR_PORT" ]] ;then 17 | MONITOR_PORT=${port_running} 18 | fi 19 | 20 | echo "Use port $MONITOR_PORT" 21 | 22 | adb forward tcp:${MONITOR_PORT} tcp:${MONITOR_PORT} && open "http://localhost:$MONITOR_PORT/index.html" && echo "If it is always loading, try close and open the browser tab again." && read -p "Press any key to continue..." -------------------------------------------------------------------------------- /android-godeye-idea-plugin/README.md: -------------------------------------------------------------------------------- 1 | prepare plugin module for deployment -------------------------------------------------------------------------------- /android-godeye-idea-plugin/android-godeye-idea-plugin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-idea-plugin/android-godeye-idea-plugin.jar -------------------------------------------------------------------------------- /android-godeye-idea-plugin/resources/icons/android_god_eye_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-idea-plugin/resources/icons/android_god_eye_logo.png -------------------------------------------------------------------------------- /android-godeye-idea-plugin/resources/icons/android_god_eye_logo_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-idea-plugin/resources/icons/android_god_eye_logo_2.png -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:react/recommended" 9 | ], 10 | "globals": { 11 | "Atomics": "readonly", 12 | "SharedArrayBuffer": "readonly" 13 | }, 14 | "parserOptions": { 15 | "ecmaFeatures": { 16 | "jsx": true 17 | }, 18 | "ecmaVersion": 2018, 19 | "sourceType": "module" 20 | }, 21 | "plugins": [ 22 | "react" 23 | ], 24 | "rules": { 25 | } 26 | } -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/README.md: -------------------------------------------------------------------------------- 1 | # AndroidGodEye Monitor Dashboard 2 | 3 | ## Run dashboard only 4 | 5 | 1. `cd android-godeye-monitor-dashboard` 6 | 2. `npm install` or `cnpm install` if needed. 7 | 3. `npm start` 8 | 9 | ## Build dashboard for app 10 | 11 | 1. `cd android-godeye-monitor-dashboard` 12 | 2. `npm install` or `cnpm install` if needed. 13 | 3. [`npm run bd`] or [`npm run build` then `npm run deploy`] 14 | 4. run android android-godeye-sample module 15 | 16 | ## Others 17 | 18 | table:https://react-table.js.org/#/story/readme 19 | charts:highcharts 20 | Page_Visibility_API:https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "android-god-eye", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "antd": "^3.19.8", 7 | "eslint": "^5.16.0", 8 | "highcharts": "^6.2.0", 9 | "npm": "^6.0.1", 10 | "react": "^16.3.2", 11 | "react-dom": "^16.3.2", 12 | "react-highcharts": "^16.0.2", 13 | "react-json-pretty": "^1.7.6", 14 | "react-page-visibility": "^3.3.0", 15 | "react-scripts": "1.1.4", 16 | "react-table": "^6.8.5", 17 | "sockette": "^2.0.0" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "deploy": "python deploy.py", 23 | "bd": "react-scripts build && python deploy.py", 24 | "test": "react-scripts test --env=jsdom", 25 | "eject": "react-scripts eject" 26 | }, 27 | "devDependencies": { 28 | "eslint-plugin-react": "^7.14.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-monitor-dashboard/public/favicon.ico -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/appSizeInfo/appsize.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import '../App.css'; 3 | // import '../../node_modules/bootstrap/dist/css/bootstrap-theme.min.css'; 4 | // import '../../node_modules/bootstrap/dist/css/bootstrap.min.css'; 5 | // import {Row, Col, Clearfix, Grid, Panel} from 'react-bootstrap' 6 | import {Card} from 'antd' 7 | 8 | /** 9 | * 存储信息 10 | */ 11 | class AppSize extends Component { 12 | 13 | constructor(props) { 14 | super(props); 15 | this.state = { 16 | appSizeInfo: {} 17 | } 18 | } 19 | 20 | refresh(appSizeInfo) { 21 | this.setState({appSizeInfo}); 22 | } 23 | 24 | render() { 25 | let info = this.state.appSizeInfo; 26 | return ( 27 | 28 |
29 | 30 | Code Size:   31 | {(info.codeSize / (1024 * 1024)).toFixed(2)}  MB 32 |       Cache Size:   33 | {(info.cacheSize / (1024 * 1024)).toFixed(2)}  MB 34 |       Data Size:   35 | {(info.dataSize / (1024 * 1024)).toFixed(2)}  MB 36 | 37 |
38 |
); 39 | } 40 | } 41 | 42 | export default AppSize; 43 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-monitor-dashboard/src/assets/logo.png -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/block/changeBlockConfigForm.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import '../App.css'; 3 | import {Button, InputNumber, Form} from 'antd' 4 | 5 | class ChangeBlockConfigForm extends Component { 6 | handleSubmit = e => { 7 | e.preventDefault(); 8 | this.props.form.validateFields((err, fieldsValue) => { 9 | if (!err) { 10 | this.props.form.resetFields(); 11 | this.props.handleChange(fieldsValue.BlockTime); 12 | } 13 | }); 14 | }; 15 | 16 | render() { 17 | const {getFieldDecorator} = this.props.form; 18 | return ( 19 |
20 | 21 | {getFieldDecorator('BlockTime', { 22 | rules: [{required: true}], 23 | })( 24 | 25 | )} 26 | 27 | 28 | 31 | 32 |
33 | ); 34 | } 35 | } 36 | 37 | const ChangeBlockConfigFormInstance = Form.create({name: 'ChangeBlockConfigForm'})(ChangeBlockConfigForm); 38 | 39 | export default ChangeBlockConfigFormInstance -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/communication/websocket.js: -------------------------------------------------------------------------------- 1 | 2 | class GlobalWs { 3 | 4 | constructor() { 5 | this._receiveMessage = this._receiveMessage.bind(this); 6 | this.wsCallbacks = new Set(); 7 | } 8 | 9 | registerCallback(callback) { 10 | if (this.ws && this.ws.readyState === WebSocket.OPEN) { 11 | callback() 12 | } 13 | this.wsCallbacks.add(callback) 14 | } 15 | 16 | unregisterCallback(callback) { 17 | this.wsCallbacks.delete(callback) 18 | } 19 | 20 | start() { 21 | this.ws = new WebSocket("ws://" + window.location.host + "/refresh"); 22 | this.ws.addEventListener('open', () => { 23 | if (this.wsCallbacks) { 24 | this.wsCallbacks.forEach((element) => { 25 | element() 26 | }) 27 | } 28 | }); 29 | this.ws.addEventListener('message', this._receiveMessage); 30 | } 31 | 32 | sendMessage(message) { 33 | this.ws.send(message); 34 | } 35 | 36 | _receiveMessage(e) { 37 | let message = JSON.parse(e.data); 38 | if (this.receiveMessageCallback) { 39 | if (message.code === 1) { 40 | this.receiveMessageCallback(message.data.moduleName, message.data.payload); 41 | } else { 42 | console.log('Error for _receiveMessage:', message) 43 | } 44 | } 45 | } 46 | 47 | setReceiveMessageCallback(callback) { 48 | this.receiveMessageCallback = callback; 49 | } 50 | } 51 | 52 | const globalWs = new GlobalWs(); 53 | 54 | export default globalWs; -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/cpu/cpu_info.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import '../App.css'; 3 | 4 | 5 | class CpuInfo extends Component { 6 | 7 | constructor(props) { 8 | super(props); 9 | this.state = { 10 | cpuInfo: {} 11 | }; 12 | } 13 | 14 | refresh(cpuInfo) { 15 | if (cpuInfo) { 16 | this.setState({ 17 | cpuInfo: { 18 | totalUseRatio: (cpuInfo.totalUseRatio * 100).toFixed(1), 19 | appCpuRatio: (cpuInfo.appCpuRatio * 100).toFixed(1) 20 | } 21 | }) 22 | } else { 23 | this.setState({ 24 | cpuInfo: { 25 | totalUseRatio: "*", 26 | appCpuRatio: "*" 27 | } 28 | }) 29 | } 30 | 31 | } 32 | 33 | render() { 34 | return ( 35 | App:  37 | {this.state.cpuInfo.appCpuRatio} %   Device:  38 | {this.state.cpuInfo.totalUseRatio} % 39 | ) 40 | } 41 | } 42 | 43 | export default CpuInfo; 44 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/heap/heap_info.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import '../App.css'; 3 | 4 | /** 5 | * Heap 6 | */ 7 | class HeapInfo extends Component { 8 | 9 | constructor(props) { 10 | super(props); 11 | this.state = { 12 | heapInfo: {} 13 | }; 14 | } 15 | 16 | refresh(heapInfo) { 17 | if (heapInfo) { 18 | this.setState({ 19 | heapInfo: { 20 | allocatedMB: (heapInfo.allocatedKb / 1024).toFixed(1), 21 | freeMemMB: (heapInfo.freeMemKb / 1024).toFixed(1), 22 | maxMemMB: (heapInfo.maxMemKb / 1024).toFixed(1) 23 | } 24 | }) 25 | } else { 26 | this.setState({ 27 | heapInfo: { 28 | allocatedMB: "*", 29 | freeMemMB: "*", 30 | maxMemMB: "*" 31 | } 32 | }) 33 | } 34 | } 35 | 36 | render() { 37 | return ( 38 | Allocated:  39 | {this.state.heapInfo.allocatedMB} 40 |    Max:  41 | {this.state.heapInfo.maxMemMB} 42 |   MB 43 | 44 | ) 45 | } 46 | } 47 | 48 | export default HeapInfo; 49 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | registerServiceWorker(); 9 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-monitor-dashboard/src/logo.png -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/refreshstatus/refreshStatus.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/prop-types */ 2 | import React, {Component} from 'react'; 3 | import '../App.css'; 4 | import {Button} from 'antd' 5 | 6 | /** 7 | * 刷新状态 8 | */ 9 | class RefreshStatus extends Component { 10 | 11 | constructor(props) { 12 | super(props); 13 | this._handleRefreshStatus = this._handleRefreshStatus.bind(this); 14 | this.setCanRefresh = props.setCanRefresh; 15 | this.state = { 16 | canRefresh: true, 17 | lastUpdateTime: new Date() 18 | } 19 | } 20 | 21 | _handleRefreshStatus() { 22 | this.setState(function (prevState, props) { 23 | this.setCanRefresh(!prevState.canRefresh); 24 | return {canRefresh: !prevState.canRefresh}; 25 | }); 26 | } 27 | 28 | refresh(time) { 29 | this.setState({lastUpdateTime: time}); 30 | } 31 | 32 | render() { 33 | return ( 34 |
35 | 36 | Status:{this.state.canRefresh ? "Refreshing..." : "Stopped."} | 37 | Last update time:{this.state.lastUpdateTime.toISOString()}       38 | 40 | 41 |
42 | ); 43 | } 44 | } 45 | 46 | export default RefreshStatus; 47 | -------------------------------------------------------------------------------- /android-godeye-monitor-dashboard/src/startup/startup.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import '../App.css'; 3 | // import '../../node_modules/bootstrap/dist/css/bootstrap-theme.min.css'; 4 | // import '../../node_modules/bootstrap/dist/css/bootstrap.min.css'; 5 | // import {Row, Col, Clearfix, Grid, Panel} from 'react-bootstrap' 6 | import {Card} from 'antd' 7 | 8 | /** 9 | * 启动信息 10 | */ 11 | class Startup extends Component { 12 | 13 | constructor(props) { 14 | super(props); 15 | this.state = { 16 | startupInfo: {} 17 | } 18 | } 19 | 20 | refresh(startupInfo) { 21 | this.setState({startupInfo}); 22 | } 23 | 24 | render() { 25 | let info = this.state.startupInfo; 26 | return ( 27 | 28 |
29 | 30 | Startup Type:   31 | {info.startupType} 32 |       Cost time:   33 | {info.startupTime}  ms 34 | 35 |
36 |
); 37 | } 38 | } 39 | 40 | export default Startup; 41 | -------------------------------------------------------------------------------- /android-godeye-monitor/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android-godeye-monitor/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION) 5 | buildToolsVersion BUILD_TOOLS_VERSION 6 | 7 | defaultConfig { 8 | minSdkVersion Integer.parseInt(MIN_SDK_VERSION) 9 | targetSdkVersion Integer.parseInt(TARGET_SDK_VERSION) 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | compileOptions { 17 | targetCompatibility = "8" 18 | sourceCompatibility = "8" 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | 27 | lintOptions { 28 | abortOnError false 29 | } 30 | } 31 | 32 | dependencies { 33 | testImplementation 'junit:junit:4.12' 34 | androidTestImplementation 'androidx.test:runner:1.2.0' 35 | implementation 'com.google.code.gson:gson:2.8.5' 36 | implementation 'io.reactivex.rxjava2:rxjava:2.2.2' 37 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' 38 | implementation project(':android-godeye') 39 | implementation 'com.squareup.leakcanary:shark:2.2' 40 | implementation 'com.koushikdutta.async:androidasync:2.2.1' 41 | implementation "com.github.nisrulz:easydeviceinfo-base:2.4.1" 42 | implementation "androidx.collection:collection:1.1.0" 43 | implementation "androidx.core:core:1.1.0" 44 | } 45 | 46 | apply from: rootProject.file('gradle/gradle-jcenter-push.gradle') -------------------------------------------------------------------------------- /android-godeye-monitor/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=godeye-monitor 2 | POM_NAME=God Eye Monitor 3 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /android-godeye-monitor/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 22 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/androidTest/java/cn/hikyson/godeye/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented 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("cn.hikyson.godeye.monitor.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/assets/android-godeye-dashboard/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "main.css": "static/css/main.187d6dcc.css", 3 | "main.css.map": "static/css/main.187d6dcc.css.map", 4 | "main.js": "static/js/main.f223975e.js", 5 | "main.js.map": "static/js/main.f223975e.js.map" 6 | } -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/assets/android-godeye-dashboard/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-monitor/src/main/assets/android-godeye-dashboard/favicon.ico -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/assets/android-godeye-dashboard/index.html: -------------------------------------------------------------------------------- 1 | AndroidGodEye
-------------------------------------------------------------------------------- /android-godeye-monitor/src/main/assets/android-godeye-dashboard/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/modules/BlockSimpleInfo.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.modules; 2 | 3 | import androidx.annotation.Keep; 4 | 5 | import java.io.Serializable; 6 | 7 | import cn.hikyson.godeye.core.internal.modules.sm.BlockInfo; 8 | import cn.hikyson.godeye.core.utils.JsonUtil; 9 | 10 | @Keep 11 | public class BlockSimpleInfo implements Serializable { 12 | public long blockTime; 13 | public String blockBaseinfo; 14 | 15 | public BlockSimpleInfo(BlockInfo blockInfo) { 16 | if (BlockInfo.BlockType.LONG.equals(blockInfo.blockType)) { 17 | this.blockTime = blockInfo.longBlockInfo.blockTime; 18 | this.blockBaseinfo = JsonUtil.toJson(blockInfo.longBlockInfo); 19 | } else if (BlockInfo.BlockType.SHORT.equals(blockInfo.blockType)) { 20 | this.blockTime = blockInfo.shortBlockInfo.blockTime; 21 | this.blockBaseinfo = JsonUtil.toJson(blockInfo.shortBlockInfo); 22 | } //do nothing 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/modules/PageLifecycleProcessedEvent.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.modules; 2 | 3 | import androidx.annotation.Keep; 4 | 5 | import java.io.Serializable; 6 | import java.util.Map; 7 | 8 | import cn.hikyson.godeye.core.internal.modules.pageload.LifecycleEvent; 9 | import cn.hikyson.godeye.core.internal.modules.pageload.PageType; 10 | 11 | @Keep 12 | public class PageLifecycleProcessedEvent implements Serializable { 13 | public PageType pageType; 14 | public String pageClassName; 15 | public int pageHashCode; 16 | public LifecycleEvent lifecycleEvent; 17 | public long startTimeMillis; 18 | public long endTimeMillis; 19 | public Map processedInfo; 20 | } 21 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/modules/appinfo/AppInfoLabel.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.modules.appinfo; 2 | 3 | import androidx.annotation.Keep; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @deprecated 9 | */ 10 | @Deprecated 11 | @Keep 12 | public class AppInfoLabel implements Serializable { 13 | public String name; 14 | public String value; 15 | public String url; 16 | 17 | public AppInfoLabel(String name, String value, String url) { 18 | this.name = name; 19 | this.value = value; 20 | this.url = url; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/modules/battery/BatterySummaryInfo.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.modules.battery; 2 | 3 | import androidx.annotation.Keep; 4 | 5 | import java.io.Serializable; 6 | 7 | @Keep 8 | public class BatterySummaryInfo implements Serializable { 9 | public String status; 10 | public String health; 11 | // boolean类型 12 | public boolean present; 13 | // int类型,电池剩余容量 14 | public int level; 15 | //int类型,电池最大值。通常为100。 16 | public int scale; 17 | //int类型,连接的电源插座,定义值是BatteryManager.BATTERY_PLUGGED_XXX。 18 | public String plugged; 19 | //int类型,电压 mV 20 | public int voltage; 21 | //int类型,温度,0.1度单位。例如 表示197的时候,意思为19.7度。 22 | public int temperature; 23 | //String类型,电池类型,例如,Li-ion等等。 24 | public String technology; 25 | 26 | @Override 27 | public String toString() { 28 | return "BatterySummaryInfo{" + 29 | "status='" + status + '\'' + 30 | ", health='" + health + '\'' + 31 | ", present=" + present + 32 | ", level=" + level + 33 | ", scale=" + scale + 34 | ", plugged='" + plugged + '\'' + 35 | ", voltage=" + voltage + 36 | ", temperature=" + temperature + 37 | ", technology='" + technology + '\'' + 38 | '}'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/modules/leak/LeakConverter.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.modules.leak; 2 | 3 | import cn.hikyson.godeye.core.internal.modules.leakdetector.LeakInfo; 4 | import io.reactivex.functions.Function; 5 | 6 | public class LeakConverter { 7 | 8 | public static Function leakConverter() { 9 | return new Function() { 10 | @Override 11 | public LeakSimpleInfo apply(LeakInfo leak) throws Exception { 12 | return new LeakSimpleInfo(leak); 13 | } 14 | }; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/modules/thread/ThreadRunningProcessClassifier.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.modules.thread; 2 | 3 | /** 4 | * @deprecated use {@link cn.hikyson.godeye.core.internal.modules.thread.ThreadTagger} to {@link cn.hikyson.godeye.core.internal.modules.thread.ThreadConfig#threadTagger} 5 | */ 6 | @Deprecated 7 | public interface ThreadRunningProcessClassifier { 8 | } 9 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/ConvertServerMessageFunction.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import cn.hikyson.godeye.core.utils.ThreadUtil; 4 | import io.reactivex.functions.Function; 5 | 6 | public class ConvertServerMessageFunction implements Function { 7 | private String mModuleName; 8 | 9 | ConvertServerMessageFunction(String moduleName) { 10 | mModuleName = moduleName; 11 | } 12 | 13 | @Override 14 | public ServerMessage apply(T input) { 15 | ThreadUtil.ensureWorkThread("ConvertServerMessageFunction:" + input.getClass().getSimpleName()); 16 | return new ServerMessage(mModuleName, input); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/Messager.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | public interface Messager { 4 | void sendMessage(String message); 5 | } 6 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/SendMessageConsumer.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import cn.hikyson.godeye.core.utils.ThreadUtil; 4 | import io.reactivex.functions.Consumer; 5 | 6 | public class SendMessageConsumer implements Consumer { 7 | private Messager mMessager; 8 | 9 | public SendMessageConsumer(Messager messager) { 10 | mMessager = messager; 11 | } 12 | 13 | @Override 14 | public void accept(ServerMessage serverMessage) throws Exception { 15 | ThreadUtil.ensureWorkThread("SendMessageConsumer accept"); 16 | if (mMessager != null) { 17 | mMessager.sendMessage(serverMessage.toString()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/UnhandledException.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | public class UnhandledException extends Exception { 4 | public UnhandledException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/WebSocketAppinfoProcessor.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import com.koushikdutta.async.http.WebSocket; 4 | 5 | import org.json.JSONObject; 6 | 7 | import cn.hikyson.godeye.monitor.modules.appinfo.AppInfo; 8 | 9 | public class WebSocketAppinfoProcessor implements WebSocketProcessor { 10 | @Override 11 | public void process(WebSocket webSocket, JSONObject msgJSONObject) { 12 | webSocket.send(new ServerMessage("appInfo", AppInfo.Factory.create()).toString()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/WebSocketBizProcessor.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import com.koushikdutta.async.http.WebSocket; 4 | 5 | import org.json.JSONObject; 6 | 7 | import cn.hikyson.godeye.core.utils.L; 8 | 9 | public class WebSocketBizProcessor { 10 | private WebSocketBizRouter mWebSocketBizRouter; 11 | 12 | public WebSocketBizProcessor() { 13 | mWebSocketBizRouter = new WebSocketBizRouter(); 14 | } 15 | 16 | public void process(WebSocket webSocket, String msg) { 17 | try { 18 | final JSONObject msgJSONObject = new JSONObject(msg); 19 | mWebSocketBizRouter.process(webSocket, msgJSONObject); 20 | } catch (Exception e) { 21 | L.e(String.valueOf(e)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/WebSocketBizRouter.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import android.text.TextUtils; 4 | 5 | import androidx.collection.ArrayMap; 6 | 7 | import com.koushikdutta.async.http.WebSocket; 8 | 9 | import org.json.JSONObject; 10 | 11 | import java.util.Map; 12 | 13 | public class WebSocketBizRouter implements WebSocketProcessor { 14 | private Map mRouterMap; 15 | 16 | WebSocketBizRouter() { 17 | mRouterMap = new ArrayMap<>(); 18 | mRouterMap.put("clientOnline", new WebSocketClientOnlineProcessor()); 19 | mRouterMap.put("appInfo", new WebSocketAppinfoProcessor()); 20 | mRouterMap.put("methodCanary", new WebSocketMethodCanaryProcessor()); 21 | mRouterMap.put("reinstallBlock", new WebSocketChangeBlockConfigProcessor()); 22 | } 23 | 24 | @Override 25 | public void process(WebSocket webSocket, JSONObject msgJSONObject) throws Exception { 26 | if (msgJSONObject == null) { 27 | throw new UnhandledException("msgJSONObject == null"); 28 | } 29 | final String moduleName = msgJSONObject.optString("moduleName"); 30 | if (TextUtils.isEmpty(moduleName)) { 31 | throw new UnhandledException("TextUtils.isEmpty(moduleName)"); 32 | } 33 | WebSocketProcessor webSocketProcessor = mRouterMap.get(moduleName); 34 | if (webSocketProcessor == null) { 35 | throw new UnhandledException("can not find module to process [" + moduleName + "]"); 36 | } 37 | webSocketProcessor.process(webSocket, msgJSONObject); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/WebSocketClientOnlineProcessor.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import com.koushikdutta.async.http.WebSocket; 4 | 5 | import org.json.JSONObject; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | import cn.hikyson.godeye.core.GodEye; 12 | import cn.hikyson.godeye.core.exceptions.UninstallException; 13 | import cn.hikyson.godeye.core.internal.Install; 14 | import cn.hikyson.godeye.core.utils.L; 15 | 16 | public class WebSocketClientOnlineProcessor implements WebSocketProcessor { 17 | 18 | @Override 19 | public void process(WebSocket webSocket, JSONObject msgJSONObject) throws Exception { 20 | try { 21 | Set installedModules = GodEye.instance().getInstalledModuleNames(); 22 | Map moduleConfigs = new HashMap<>(); 23 | for (String module : installedModules) { 24 | moduleConfigs.put(module, GodEye.instance().getModule(module).config()); 25 | } 26 | webSocket.send(new ServerMessage("installedModuleConfigs", moduleConfigs).toString()); 27 | } catch (UninstallException e) { 28 | L.e(String.valueOf(e)); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/WebSocketMethodCanaryProcessor.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import com.koushikdutta.async.http.WebSocket; 4 | 5 | import org.json.JSONObject; 6 | 7 | import java.util.Collections; 8 | 9 | import cn.hikyson.godeye.core.GodEyeHelper; 10 | import cn.hikyson.godeye.core.exceptions.UninstallException; 11 | import cn.hikyson.godeye.core.utils.L; 12 | 13 | public class WebSocketMethodCanaryProcessor implements WebSocketProcessor { 14 | @Override 15 | public void process(WebSocket webSocket, JSONObject msgJSONObject) { 16 | try { 17 | if ("start".equals(msgJSONObject.optString("payload"))) { 18 | GodEyeHelper.startMethodCanaryRecording("AndroidGodEye-Monitor-Tag"); 19 | } else if ("stop".equals(msgJSONObject.optString("payload"))) { 20 | GodEyeHelper.stopMethodCanaryRecording("AndroidGodEye-Monitor-Tag"); 21 | } 22 | webSocket.send(new ServerMessage("methodCanaryMonitorState", Collections.singletonMap("isRunning", GodEyeHelper.isMethodCanaryRecording("AndroidGodEye-Monitor-Tag"))).toString()); 23 | } catch (UninstallException e) { 24 | L.e(String.valueOf(e)); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/java/cn/hikyson/godeye/monitor/server/WebSocketProcessor.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.monitor.server; 2 | 3 | import com.koushikdutta.async.http.WebSocket; 4 | 5 | import org.json.JSONObject; 6 | 7 | public interface WebSocketProcessor { 8 | void process(WebSocket webSocket, JSONObject msgJSONObject) throws Exception; 9 | } 10 | -------------------------------------------------------------------------------- /android-godeye-monitor/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android-godeye-sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android-godeye-sample/AndroidGodEye.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/AndroidGodEye.keystore -------------------------------------------------------------------------------- /android-godeye-sample/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 22 | -dontwarn javax.annotation.** 23 | -dontwarn org.codehaus.** 24 | -dontwarn org.conscrypt.** 25 | -dontwarn javax.annotation.ParametersAreNonnullByDefault -------------------------------------------------------------------------------- /android-godeye-sample/src/main/assets/android-godeye-config/install.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 19 | 20 | 21 | 22 | 24 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/assets/android-godeye-config/install_release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 19 | 20 | 21 | 22 | 24 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/AppInfoProxyImpl.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import cn.hikyson.godeye.core.monitor.AppInfoConext; 7 | import cn.hikyson.godeye.core.monitor.AppInfoLabel; 8 | 9 | /** 10 | * Created by kysonchao on 2017/12/9. 11 | */ 12 | public class AppInfoProxyImpl implements AppInfoConext { 13 | 14 | @Override 15 | public List getAppInfo() { 16 | List appInfoLabels = new ArrayList<>(); 17 | appInfoLabels.add(new AppInfoLabel("Email", "kysonchao@gmail.com", "mailto:kysonchao@gmail.com")); 18 | appInfoLabels.add(new AppInfoLabel("ProjectUrl", "https://github.com/Kyson/AndroidGodEye", "https://github.com/Kyson/AndroidGodEye")); 19 | appInfoLabels.add(new AppInfoLabel("Blog", "tech.hikyson.cn", "https://tech.hikyson.cn")); 20 | return appInfoLabels; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/ComplexLayoutActivity.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import androidx.annotation.Nullable; 6 | 7 | import cn.hikyson.android.godeye.sample.R; 8 | 9 | public class ComplexLayoutActivity extends Activity { 10 | 11 | @Override 12 | protected void onCreate(@Nullable Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_complex_layout); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/LeakActivity.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.app.Activity; 4 | import android.os.Build; 5 | import android.os.Bundle; 6 | import android.widget.TextView; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | import cn.hikyson.android.godeye.sample.R; 11 | import io.reactivex.android.schedulers.AndroidSchedulers; 12 | 13 | 14 | public class LeakActivity extends Activity { 15 | 16 | private TextView mTv; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_leak); 22 | mTv = this.findViewById(R.id.activity_leak_test); 23 | findViewById(R.id.btn_fragment).setOnClickListener(view -> { 24 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 25 | LeakFragment fragment = new LeakFragment(); 26 | getFragmentManager().beginTransaction().replace(R.id.frame_layout, fragment).commit(); 27 | AndroidSchedulers.mainThread().scheduleDirect(() -> getFragmentManager().beginTransaction().remove(fragment).commit(), 2, TimeUnit.SECONDS); 28 | } 29 | }); 30 | } 31 | 32 | @Override 33 | protected void onDestroy() { 34 | super.onDestroy(); 35 | new Thread(() -> { 36 | try { 37 | Thread.sleep(200000); 38 | mTv.setText("Leak"); 39 | } catch (InterruptedException e) { 40 | } 41 | }).start(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/LeakActivityV4.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.fragment.app.FragmentActivity; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | import cn.hikyson.android.godeye.sample.R; 10 | import io.reactivex.android.schedulers.AndroidSchedulers; 11 | 12 | 13 | public class LeakActivityV4 extends FragmentActivity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_leak_v4); 19 | LeakFragmentV4 fragmentV4 = new LeakFragmentV4(); 20 | getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout, fragmentV4).commit(); 21 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 22 | try { 23 | getSupportFragmentManager().beginTransaction().remove(fragmentV4).commit(); 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | } 27 | }, 2, TimeUnit.SECONDS); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/LeakFragment.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.app.Fragment; 4 | import android.os.Bundle; 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.TextView; 11 | 12 | import cn.hikyson.android.godeye.sample.R; 13 | 14 | 15 | public class LeakFragment extends Fragment { 16 | private TextView mTv; 17 | 18 | @Override 19 | public void onCreate(@Nullable Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | } 22 | 23 | @Override 24 | public void onDestroy() { 25 | super.onDestroy(); 26 | new Thread(() -> { 27 | try { 28 | Thread.sleep(100000); 29 | mTv.setText("Leak"); 30 | } catch (InterruptedException e) { 31 | } 32 | }).start(); 33 | } 34 | 35 | @Nullable 36 | @Override 37 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 38 | View view = inflater.inflate(R.layout.fragment_leak, container, false); 39 | mTv = view.findViewById(R.id.fragment_leak_test); 40 | return view; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/LeakFragmentV4.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.os.Bundle; 4 | import androidx.annotation.NonNull; 5 | import androidx.annotation.Nullable; 6 | import androidx.fragment.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import cn.hikyson.android.godeye.sample.R; 12 | 13 | public class LeakFragmentV4 extends Fragment { 14 | 15 | @Override 16 | public void onCreate(@Nullable Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | } 19 | 20 | @Override 21 | public void onDestroy() { 22 | super.onDestroy(); 23 | new Thread(new Runnable() { 24 | @Override 25 | public void run() { 26 | try { 27 | Thread.sleep(100000); 28 | } catch (InterruptedException e) { 29 | } 30 | } 31 | }).start(); 32 | } 33 | 34 | @Nullable 35 | @Override 36 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 37 | return inflater.inflate(R.layout.fragment_leak_v4, container, false); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/LogObserver.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import io.reactivex.functions.Consumer; 4 | 5 | /** 6 | * Created by kysonchao on 2017/12/9. 7 | */ 8 | 9 | public class LogObserver implements Consumer { 10 | private String mName; 11 | private Loggable mLoggable; 12 | 13 | public LogObserver(String name, Loggable loggable) { 14 | this.mName = name; 15 | this.mLoggable = loggable; 16 | } 17 | 18 | @Override 19 | public void accept(T t) throws Exception { 20 | mLoggable.log(mName + " , " + t); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/Loggable.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | /** 4 | * Created by kysonchao on 2017/11/24. 5 | */ 6 | interface Loggable { 7 | void log(String msg); 8 | } 9 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/SampleApp.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.app.Application; 4 | 5 | import java.text.SimpleDateFormat; 6 | import java.util.Locale; 7 | 8 | /** 9 | * Created by kysonchao on 2017/11/30. 10 | */ 11 | public class SampleApp extends Application { 12 | private static final SimpleDateFormat FORMATTER_2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US); 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | StartupTracer.get().onApplicationCreate(); 18 | SubProcessIntentService.startActionFoo(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import cn.hikyson.android.godeye.sample.R; 8 | 9 | public class SplashActivity extends Activity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_splash); 15 | StartupTracer.get().onSplashCreate(); 16 | Intent intent = new Intent(SplashActivity.this, Main2Activity.class); 17 | startActivity(intent); 18 | finish(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/SubProcessIntentService.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample; 2 | 3 | import android.app.IntentService; 4 | import android.content.Intent; 5 | import android.content.Context; 6 | 7 | 8 | public class SubProcessIntentService extends IntentService { 9 | 10 | private static final String ACTION_FOO = "cn.hikyson.godeye.sample.action.FOO"; 11 | 12 | public SubProcessIntentService() { 13 | super("SubProcessIntentService"); 14 | } 15 | 16 | public static void startActionFoo(Context context) { 17 | Intent intent = new Intent(context, SubProcessIntentService.class); 18 | intent.setAction(ACTION_FOO); 19 | context.startService(intent); 20 | } 21 | 22 | @Override 23 | protected void onHandleIntent(Intent intent) { 24 | if (intent != null) { 25 | final String action = intent.getAction(); 26 | if (ACTION_FOO.equals(action)) { 27 | handleActionFoo(); 28 | } 29 | } 30 | } 31 | 32 | private void handleActionFoo() { 33 | try { 34 | Thread.sleep(1000000); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/methodcanary/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample.methodcanary; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | 10 | public class BaseActivity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(@Nullable Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | } 16 | 17 | @Override 18 | protected void onStart() { 19 | super.onStart(); 20 | } 21 | 22 | @Override 23 | protected void onResume() { 24 | super.onResume(); 25 | } 26 | 27 | @Override 28 | protected void onPause() { 29 | super.onPause(); 30 | } 31 | 32 | @Override 33 | protected void onStop() { 34 | super.onStop(); 35 | } 36 | 37 | @Override 38 | protected void onSaveInstanceState(@NonNull Bundle outState) { 39 | super.onSaveInstanceState(outState); 40 | } 41 | 42 | @Override 43 | protected void onDestroy() { 44 | super.onDestroy(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/methodcanary/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample.methodcanary; 2 | 3 | import android.app.Fragment; 4 | 5 | 6 | public class BaseFragment extends Fragment { 7 | 8 | public void test() { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/methodcanary/Child0Fragment.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample.methodcanary; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.annotation.Nullable; 12 | 13 | import cn.hikyson.android.godeye.sample.R; 14 | 15 | public class Child0Fragment extends BaseFragment { 16 | private TextView mTv; 17 | 18 | @Override 19 | public void onCreate(@Nullable Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | int i = 1; 22 | } 23 | 24 | @Override 25 | public void onAttach(Activity activity) { 26 | super.onAttach(activity); 27 | } 28 | 29 | @Override 30 | public void onSaveInstanceState(Bundle outState) { 31 | super.onSaveInstanceState(outState); 32 | } 33 | 34 | @Nullable 35 | @Override 36 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 37 | View view = inflater.inflate(R.layout.fragment_blank_fragment1, container, false); 38 | return view; 39 | } 40 | 41 | @Override 42 | public void onDestroyView() { 43 | super.onDestroyView(); 44 | } 45 | 46 | @Override 47 | public void onPause() { 48 | super.onPause(); 49 | } 50 | 51 | @Override 52 | public void onDetach() { 53 | super.onDetach(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/java/cn/hikyson/godeye/sample/utils/ThreadUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hikyson.godeye.sample.utils; 2 | 3 | public class ThreadUtil { 4 | public static void sleep(long time) { 5 | try { 6 | Thread.sleep(time); 7 | } catch (InterruptedException e) { 8 | e.printStackTrace(); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-hdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-hdpi/ic_delete.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-hdpi/ic_vertical_align_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-hdpi/ic_vertical_align_bottom.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-mdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-mdpi/ic_delete.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-mdpi/ic_vertical_align_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-mdpi/ic_vertical_align_bottom.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xhdpi/ic_delete.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xhdpi/ic_vertical_align_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xhdpi/ic_vertical_align_bottom.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xxhdpi/ic_delete.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xxhdpi/ic_vertical_align_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xxhdpi/ic_vertical_align_bottom.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xxhdpi/image_test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xxhdpi/image_test1.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xxhdpi/image_test2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xxhdpi/image_test2.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xxxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xxxhdpi/ic_delete.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable-xxxhdpi/ic_vertical_align_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kyson/AndroidGodEye/459f5cb5a2a4d176ff63f27322644a8191df2af9/android-godeye-sample/src/main/res/drawable-xxxhdpi/ic_vertical_align_bottom.png -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable/ic_follow.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/drawable/shape_follow_selected.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /android-godeye-sample/src/main/res/layout/activity_leak.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 |