├── .gitignore ├── LICENSE ├── QPM_SDK ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── collector.js │ ├── java │ └── com │ │ └── zk │ │ └── qpm │ │ ├── QPMConstant.java │ │ ├── QPMException.java │ │ ├── QPMRAnalysisResult.java │ │ ├── activity │ │ ├── QPMActivityListActivity.java │ │ ├── QPMBasicInfoActivity.java │ │ ├── QPMFunctionBaseActivity.java │ │ ├── QPMMainMenuActivity.java │ │ ├── QPMManifestInfoActivity.java │ │ ├── QPMNetworkAPIActivity.java │ │ ├── QPMPrefInfoActivity.java │ │ ├── QPMProviderListActivity.java │ │ ├── QPMReceiverListActivity.java │ │ ├── QPMScreenRecorderActivity.java │ │ ├── QPMServiceListActivity.java │ │ └── QPMSwitchActivity.java │ │ ├── adapter │ │ ├── CommonAdapter.java │ │ └── CommonRecyclerAdapter.java │ │ ├── analysis │ │ ├── QPMActivityStackAnalysis.java │ │ ├── QPMAppAnalysis.java │ │ ├── QPMAutoAddAnalysis.java │ │ ├── QPMBaseAnalysis.java │ │ ├── QPMCPUAnalysis.java │ │ ├── QPMDeviceAnalysis.java │ │ ├── QPMFPSAnalysis.java │ │ ├── QPMFlowAnalysis.java │ │ ├── QPMH5MonitorAnalysis.java │ │ ├── QPMMemoryAnalysis.java │ │ ├── QPMNetworkAnalysis.java │ │ ├── QPMScreenRecorderStatusAnalysis.java │ │ ├── QPMThreadAnalysis.java │ │ └── QPMTopActivityAnalysis.java │ │ ├── callback │ │ ├── IAnalysisCallback.java │ │ └── ICallback.java │ │ ├── dialog │ │ └── JumpActivityWithParamDialog.java │ │ ├── executor │ │ ├── IExecutor.java │ │ ├── QPMGetActivityStackExecutor.java │ │ ├── QPMGetAppInfoExecutor.java │ │ ├── QPMGetAutoAddExecutor.java │ │ ├── QPMGetCPUInfoExecutor.java │ │ ├── QPMGetFPSInfoExecutor.java │ │ ├── QPMGetFlowInfoExecutor.java │ │ ├── QPMGetH5MonitorInfoExecutor.java │ │ ├── QPMGetMemoryInfoExecutor.java │ │ ├── QPMGetNetworkInfoExecutor.java │ │ ├── QPMGetThreadCountExecutor.java │ │ ├── QPMGetTopActivityExecutor.java │ │ └── QPMScreenRecorderStatusExecutor.java │ │ ├── floatview │ │ ├── QPMFloatViewBean.java │ │ ├── QPMFloatViewType.java │ │ └── renderer │ │ │ ├── BaseRenderer.java │ │ │ ├── BaseTemplateRenderer.java │ │ │ ├── IFloatViewRenderer.java │ │ │ ├── QPMGetActivityStackRenderer.java │ │ │ ├── QPMGetAppInfoRenderer.java │ │ │ ├── QPMGetAutoAddRenderer.java │ │ │ ├── QPMGetCPUInfoRenderer.java │ │ │ ├── QPMGetFPSInfoRenderer.java │ │ │ ├── QPMGetFlowInfoRenderer.java │ │ │ ├── QPMGetH5MonitorRenderer.java │ │ │ ├── QPMGetMemoryInfoRenderer.java │ │ │ ├── QPMGetNetworkInfoRenderer.java │ │ │ ├── QPMGetThreadCountRenderer.java │ │ │ ├── QPMGetTopActivityRenderer.java │ │ │ ├── QPMScreenRecorderStatusRenderer.java │ │ │ ├── QPMTemplateBigTextRenderer.java │ │ │ ├── QPMTemplateCustomRenderer.java │ │ │ ├── QPMTemplateKeyPicRenderer.java │ │ │ ├── QPMTemplateKeyValueRenderer.java │ │ │ └── QPMTemplatePicValueRenderer.java │ │ ├── function │ │ ├── ActivityFunction.java │ │ ├── BasicInfoFunction.java │ │ ├── FloatViewSwitchFunction.java │ │ ├── FourModuleFunction.java │ │ ├── IFunction.java │ │ ├── MainMenuFunction.java │ │ ├── ManifestFunction.java │ │ ├── NetworkAPIFunction.java │ │ ├── PrefInfoFunction.java │ │ ├── ProviderFunction.java │ │ ├── ReceiverFunction.java │ │ ├── ServiceFunction.java │ │ └── TitleFunction.java │ │ ├── manager │ │ ├── QPMApiTemplateManager.java │ │ ├── QPMCallBackManager.java │ │ ├── QPMDBManager.java │ │ ├── QPMFloatViewManager.java │ │ ├── QPMManager.java │ │ ├── QPMModeManager.java │ │ ├── QPMPluginManager.java │ │ ├── QPMRAnalysisManager.java │ │ ├── QPMScreenRecorderManager.java │ │ ├── QPMSortManager.java │ │ ├── QPMSwitchManager.java │ │ └── QPMThreadManager.java │ │ ├── plugin │ │ ├── QPMBaseServiceConnection.java │ │ ├── QPMPluginControler.java │ │ ├── QPMPluginItem.java │ │ ├── QPMPluginService.java │ │ └── QPMPluginTaskExecutor.java │ │ ├── service │ │ ├── QPMBaseService.java │ │ ├── QPMDaemonComponent.java │ │ ├── QPMFPSComponent.java │ │ ├── QPMFloatViewBaseComponent.java │ │ ├── QPMFloatViewCustomComponent.java │ │ └── QPMFloatViewSimpleComponent.java │ │ └── utils │ │ ├── ApplicationUtils.java │ │ ├── BasicInfoUtils.java │ │ ├── ClipboardUtils.java │ │ ├── DecimalFormatUtil.java │ │ ├── DeviceUtils.java │ │ ├── FloatViewUtils.java │ │ ├── FuzzyMatchUtil.java │ │ ├── ImageLoadUtil.java │ │ ├── ManifestParser.java │ │ ├── PermissionTool.java │ │ ├── PopupWindowMenus.java │ │ ├── PrefsParser.java │ │ ├── ReflectUtils.java │ │ ├── RomUtils.java │ │ ├── StatusBarColorUtils.java │ │ ├── StatusBarImmersiveUtils.java │ │ ├── SystemProperties.java │ │ └── XMLParser.java │ └── res │ ├── drawable-xxhdpi │ ├── jm_gt_activity_background.png │ ├── jm_gt_back.png │ ├── jm_gt_expand.PNG │ ├── jm_gt_fold_arrow.png │ ├── jm_gt_ic_app_info_package_name.png │ ├── jm_gt_ic_app_info_top_activity.png │ ├── jm_gt_ic_fps.png │ ├── jm_gt_icon.png │ ├── jm_gt_input_cancel.9.png │ ├── jm_gt_recorder_start.png │ ├── jm_gt_recorder_stop.png │ ├── jm_gt_switch_off.png │ ├── jm_gt_switch_on.png │ └── jm_gt_unfold_arrow.png │ ├── drawable │ ├── jm_gt_selector_btn.xml │ ├── jm_gt_selector_switch.xml │ ├── jm_gt_shape_activity_content.xml │ ├── jm_gt_shape_floatview.xml │ ├── jm_gt_shape_fps_green.xml │ └── jm_gt_shape_fps_red.xml │ ├── layout │ ├── jm_gt_activity_basic_info.xml │ ├── jm_gt_activity_four_module.xml │ ├── jm_gt_activity_main_menu.xml │ ├── jm_gt_activity_manifest_info.xml │ ├── jm_gt_activity_network_api.xml │ ├── jm_gt_activity_pref_info.xml │ ├── jm_gt_activity_switch.xml │ ├── jm_gt_dialog_jump_with_param.xml │ ├── jm_gt_float_view_item.xml │ ├── jm_gt_item_floatview_fps.xml │ ├── jm_gt_item_floatview_keylinevalue.xml │ ├── jm_gt_item_floatview_keyvalue.xml │ ├── jm_gt_item_floatview_screenrecorder.xml │ ├── jm_gt_item_floatview_template_bigtext.xml │ ├── jm_gt_item_floatview_template_keypic.xml │ ├── jm_gt_item_floatview_template_keyvalue.xml │ ├── jm_gt_item_floatview_template_picvalue.xml │ ├── jm_gt_item_four_module.xml │ ├── jm_gt_item_jump_param.xml │ ├── jm_gt_item_key_value.xml │ ├── jm_gt_item_manifest_jump.xml │ ├── jm_gt_item_network_api.xml │ ├── jm_gt_item_simple_listview.xml │ ├── jm_gt_item_switch.xml │ ├── jm_gt_item_title.xml │ ├── jm_gt_item_title_arrow.xml │ ├── jm_gt_item_type_key_value.xml │ ├── jm_gt_item_type_key_value_edit.xml │ ├── jm_gt_layout_basic_info.xml │ ├── jm_gt_layout_float_view.xml │ ├── jm_gt_layout_float_view_simple.xml │ ├── jm_gt_layout_function_title.xml │ ├── jm_gt_layout_main_menu.xml │ ├── jm_gt_layout_manifest_info.xml │ ├── jm_gt_layout_module.xml │ ├── jm_gt_layout_network_api.xml │ ├── jm_gt_layout_pref_info.xml │ ├── jm_gt_layout_switch.xml │ └── jm_gt_popup_listview.xml │ └── values │ ├── dimens.xml │ ├── jm_gt_color.xml │ ├── jm_gt_styles.xml │ └── strings.xml ├── README.md ├── app ├── .gitignore ├── 2024-08-30_wq_release_old_key.jks ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zk │ │ └── qpm │ │ └── demo │ │ ├── MainActivity.java │ │ ├── NewMainActivity.java │ │ ├── WebViewActivity.java │ │ └── webview │ │ ├── JMJSObject.java │ │ ├── JMWebChromeClient.java │ │ ├── JMWebViewClient.java │ │ └── ZKWebView.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_main.xml │ ├── jm_custom.xml │ ├── jm_float_view.xml │ ├── layout_other_ui.xml │ └── layout_webview.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── qpm_icon.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── network_security_config.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pic ├── screen_QPM_home_pic.png └── screen_QPM_home_pic_s.png ├── release └── qpm_release_v100.apk ├── settings.gradle ├── 添加OKHTTP网络监控.md └── 添加新监控项的步骤.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | #*.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # IntelliJ 36 | *.iml 37 | .idea/ 38 | .idea/workspace.xml 39 | .idea/tasks.xml 40 | .idea/gradle.xml 41 | .idea/assetWizardSettings.xml 42 | .idea/dictionaries 43 | .idea/libraries 44 | .idea/caches 45 | 46 | # Keystore files 47 | # Uncomment the following line if you do not want to check your keystore files in. 48 | #*.jks 49 | 50 | # External native build folder generated in Android Studio 2.2 and later 51 | .externalNativeBuild 52 | 53 | # Google Services (e.g. APIs or Firebase) 54 | google-services.json 55 | 56 | # Freeline 57 | freeline.py 58 | freeline/ 59 | freeline_project_description.json 60 | 61 | # fastlane 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | fastlane/readme.md 67 | -------------------------------------------------------------------------------- /QPM_SDK/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /QPM_SDK/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | //apply plugin: 'maven' 3 | 4 | def ARTIFACT_ID = 'qpm' 5 | def GROUP_ID = 'com.zk.qpm' 6 | 7 | android { 8 | 9 | namespace 'com.zk.qpm' 10 | 11 | 12 | compileSdkVersion rootProject.ext.compileSdkVersion 13 | buildToolsVersion rootProject.ext.buildToolsVersion 14 | 15 | defaultConfig { 16 | minSdkVersion rootProject.ext.minSdkVersion 17 | targetSdkVersion rootProject.ext.targetSdkVersion 18 | versionCode 10006 19 | versionName '1.0.6' 20 | 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | 30 | lintOptions { 31 | checkReleaseBuilds false 32 | abortOnError false 33 | } 34 | } 35 | 36 | dependencies { 37 | implementation fileTree(dir: 'libs', include: ['*.jar']) 38 | 39 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 40 | implementation 'com.blankj:utilcodex:1.31.1' 41 | // implementation 'androidx.appcompat:appcompat:1.7.0' 42 | implementation "com.squareup.okhttp3:okhttp:4.12.0" 43 | implementation 'androidx.annotation:annotation-experimental:1.4.1' 44 | implementation 'androidx.recyclerview:recyclerview:1.3.2' 45 | } 46 | -------------------------------------------------------------------------------- /QPM_SDK/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 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/QPMConstant.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm; 2 | 3 | public class QPMConstant { 4 | 5 | public static final String ACTION_GTR_BROADCAST = "GTR.GTRBroadcastReceiver"; 6 | 7 | public static final String PATH_SCREEN_RECORDER = "/jmgt/screenrecorder"; 8 | } 9 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/QPMException.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm; 2 | 3 | 4 | import androidx.annotation.IntDef; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | 9 | public class QPMException extends Exception { 10 | 11 | public @ExceptionType int type; 12 | 13 | public QPMException(@ExceptionType int type, String message) { 14 | super(message); 15 | this.type = type; 16 | } 17 | 18 | @IntDef({ExceptionType.TYPE_STOP_THREAD}) 19 | @Retention(RetentionPolicy.SOURCE) 20 | public @interface ExceptionType { 21 | int TYPE_STOP_THREAD = 1; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/QPMRAnalysisResult.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * GTR分析结果数据类 8 | */ 9 | public class QPMRAnalysisResult { 10 | 11 | public static final Object SYNCHRONIZED_NETWORKINFO = new Object(); 12 | 13 | public AppInfo appInfo = new AppInfo(); 14 | public OtherInfo otherInfo = new OtherInfo(); 15 | public DeviceInfo deviceInfo = new DeviceInfo(); 16 | public FrameInfo frameInfo = new FrameInfo(); 17 | public CMNTInfo cmntInfo = new CMNTInfo(); 18 | public List networkInfos = new ArrayList<>(); 19 | public ActivityStackInfo activityStackInfos = new ActivityStackInfo(); 20 | public ScreenRecorderStatusInfo screenRecorderStatusInfo = new ScreenRecorderStatusInfo(); 21 | public H5MonitorInfo h5MonitorInfo = new H5MonitorInfo(); 22 | 23 | public static class OtherInfo { 24 | public int pId = -1; 25 | public int threadCount = 0; 26 | } 27 | 28 | public static class AppInfo { 29 | //APP信息 30 | public String appName = null; 31 | public String packageName = null; 32 | public String versionName = null; 33 | public int versionCode = -1; 34 | public int gtrVersionCode = -1; 35 | public long startTestTime = -1; 36 | public int mainThreadId = -1; 37 | } 38 | 39 | public static class DeviceInfo { 40 | //Device信息: 41 | public String vendor = null; 42 | public String model = null; 43 | public String sdkName = null; 44 | public int sdkInt = -1; 45 | } 46 | 47 | public static class FrameInfo { 48 | // 帧率信息 49 | public List drawTimeInSecond = new ArrayList<>(); 50 | public int fps; 51 | // 大卡顿次数 52 | public int bigBlockTime; 53 | // 低流畅次数 54 | public int lowSMTime; 55 | // 是否处于卡顿期间 56 | public boolean isLowSM; 57 | } 58 | 59 | public static class CMNTInfo { 60 | public double cpu; 61 | public double memory; 62 | public double flowUp; 63 | public double flowDown; 64 | public double flowUpSpeed; 65 | public double flowDownSpeed; 66 | public int threadCount; 67 | public int gtThreadCount; 68 | } 69 | 70 | public static class NetworkInfo { 71 | public String originUrl; 72 | public String method; 73 | public long requestSize; 74 | public long requestTime; 75 | public String requestHeader; 76 | public String requestContent; 77 | public long responseSize; 78 | public String responseHeader; 79 | public String responseContent; 80 | public String responseCode; 81 | public long currentTime; 82 | } 83 | 84 | public static class ActivityStackInfo { 85 | public String topActivityName = null; 86 | public List activityNames = new ArrayList<>(); 87 | } 88 | 89 | public static class ScreenRecorderStatusInfo { 90 | public boolean startStatus; 91 | public long startTime; 92 | } 93 | 94 | public static class H5MonitorInfo { 95 | public String url = ""; 96 | public long whitePageTime; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMActivityListActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | 4 | import com.zk.qpm.R; 5 | import com.zk.qpm.function.ActivityFunction; 6 | import com.zk.qpm.function.TitleFunction; 7 | 8 | public class QPMActivityListActivity extends QPMFunctionBaseActivity { 9 | 10 | @Override 11 | protected int contentViewId() { 12 | return R.layout.jm_gt_activity_four_module; 13 | } 14 | 15 | @Override 16 | protected void initAllFunction() { 17 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_activity_list))); 18 | functions.add(new ActivityFunction(this)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMBasicInfoActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | 4 | import com.zk.qpm.R; 5 | import com.zk.qpm.function.BasicInfoFunction; 6 | import com.zk.qpm.function.TitleFunction; 7 | 8 | public class QPMBasicInfoActivity extends QPMFunctionBaseActivity { 9 | 10 | @Override 11 | protected int contentViewId() { 12 | return R.layout.jm_gt_activity_basic_info; 13 | } 14 | 15 | @Override 16 | protected void initAllFunction() { 17 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_basic_info))); 18 | functions.add(new BasicInfoFunction(this)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMFunctionBaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.ViewStub; 6 | import android.view.Window; 7 | import android.view.WindowManager; 8 | 9 | import com.zk.qpm.function.IFunction; 10 | import com.zk.qpm.utils.StatusBarImmersiveUtils; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public abstract class QPMFunctionBaseActivity extends Activity{ 16 | 17 | protected List functions = new ArrayList<>(); 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 22 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 23 | requestWindowFeature(Window.FEATURE_NO_TITLE); 24 | super.onCreate(savedInstanceState); 25 | StatusBarImmersiveUtils.setLightIcon(this); 26 | setContentView(contentViewId()); 27 | initAllFunction(); 28 | inflateView(); 29 | } 30 | 31 | protected abstract int contentViewId(); 32 | 33 | protected abstract void initAllFunction(); 34 | 35 | private void inflateView() { 36 | for (IFunction function : functions) { 37 | ViewStub viewStub = findViewById(function.viewStubId()); 38 | viewStub.setOnInflateListener(function.getCallback()); 39 | function.renderer(viewStub.inflate()); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMMainMenuActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | 4 | import android.Manifest; 5 | import android.content.pm.PackageManager; 6 | import android.os.Bundle; 7 | import android.widget.Toast; 8 | 9 | import androidx.annotation.RequiresApi; 10 | 11 | import com.zk.qpm.R; 12 | import com.zk.qpm.function.MainMenuFunction; 13 | import com.zk.qpm.function.TitleFunction; 14 | import com.zk.qpm.manager.QPMManager; 15 | import com.zk.qpm.utils.PermissionTool; 16 | 17 | public class QPMMainMenuActivity extends QPMFunctionBaseActivity { 18 | 19 | @Override 20 | protected int contentViewId() { 21 | return R.layout.jm_gt_activity_main_menu; 22 | } 23 | 24 | @Override 25 | protected void initAllFunction() { 26 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_main_menu))); 27 | functions.add(new MainMenuFunction(this)); 28 | } 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | QPMManager.getInstance().init(this.getApplication()); 34 | // 请求权限 35 | requestPermission(); 36 | } 37 | 38 | private void requestPermission(){ 39 | String[] permissions = new String[] { 40 | Manifest.permission.READ_PHONE_STATE, 41 | Manifest.permission.READ_EXTERNAL_STORAGE, 42 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 43 | Manifest.permission.RECORD_AUDIO 44 | }; 45 | PermissionTool.applyPermissions(permissions, this); 46 | } 47 | 48 | @RequiresApi(api = 23) 49 | @Override 50 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 51 | //申请所有权限的回调结果: 52 | if (requestCode == PermissionTool.APPLY_PERMISSIONS) { 53 | for (int i = 0; i < permissions.length; i++) { 54 | if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {//如果有权限被拒绝 55 | Toast.makeText(this, R.string.jm_gt_without_permission, Toast.LENGTH_SHORT).show(); 56 | return; 57 | } 58 | } 59 | //如果全部都同意了就进行配置加载 60 | return; 61 | } 62 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMManifestInfoActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | 4 | import com.zk.qpm.R; 5 | import com.zk.qpm.function.ManifestFunction; 6 | import com.zk.qpm.function.TitleFunction; 7 | 8 | public class QPMManifestInfoActivity extends QPMFunctionBaseActivity { 9 | 10 | @Override 11 | protected int contentViewId() { 12 | return R.layout.jm_gt_activity_manifest_info; 13 | } 14 | 15 | @Override 16 | protected void initAllFunction() { 17 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_manifest_info))); 18 | functions.add(new ManifestFunction(this)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMNetworkAPIActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | import com.zk.qpm.R; 4 | import com.zk.qpm.function.NetworkAPIFunction; 5 | import com.zk.qpm.function.TitleFunction; 6 | 7 | public class QPMNetworkAPIActivity extends QPMFunctionBaseActivity { 8 | 9 | @Override 10 | protected int contentViewId() { 11 | return R.layout.jm_gt_activity_network_api; 12 | } 13 | 14 | @Override 15 | protected void initAllFunction() { 16 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_network_api))); 17 | functions.add(new NetworkAPIFunction(this)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMPrefInfoActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | import com.zk.qpm.R; 4 | import com.zk.qpm.function.PrefInfoFunction; 5 | import com.zk.qpm.function.TitleFunction; 6 | 7 | public class QPMPrefInfoActivity extends QPMFunctionBaseActivity { 8 | 9 | @Override 10 | protected int contentViewId() { 11 | return R.layout.jm_gt_activity_pref_info; 12 | } 13 | 14 | @Override 15 | protected void initAllFunction() { 16 | TitleFunction titleFunction = new TitleFunction(this, getString(R.string.jm_gt_pref_info)); 17 | functions.add(titleFunction); 18 | functions.add(new PrefInfoFunction(this, titleFunction)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMProviderListActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | import com.zk.qpm.R; 4 | import com.zk.qpm.function.ProviderFunction; 5 | import com.zk.qpm.function.TitleFunction; 6 | 7 | public class QPMProviderListActivity extends QPMFunctionBaseActivity { 8 | 9 | @Override 10 | protected int contentViewId() { 11 | return R.layout.jm_gt_activity_four_module; 12 | } 13 | 14 | @Override 15 | protected void initAllFunction() { 16 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_provider_list))); 17 | functions.add(new ProviderFunction(this)); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMReceiverListActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | import com.zk.qpm.R; 4 | import com.zk.qpm.function.ReceiverFunction; 5 | import com.zk.qpm.function.TitleFunction; 6 | 7 | public class QPMReceiverListActivity extends QPMFunctionBaseActivity { 8 | 9 | @Override 10 | protected int contentViewId() { 11 | return R.layout.jm_gt_activity_four_module; 12 | } 13 | 14 | @Override 15 | protected void initAllFunction() { 16 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_receiver_list))); 17 | functions.add(new ReceiverFunction(this)); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMScreenRecorderActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | 9 | import androidx.annotation.Nullable; 10 | 11 | import com.zk.qpm.manager.QPMManager; 12 | import com.zk.qpm.manager.QPMScreenRecorderManager; 13 | 14 | public class QPMScreenRecorderActivity extends Activity { 15 | 16 | @Override 17 | protected void onCreate(@Nullable Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | 20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 21 | QPMScreenRecorderManager.getInstance().startRecorder(this); 22 | } 23 | } 24 | 25 | @Override 26 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 27 | super.onActivityResult(requestCode, resultCode, data); 28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 29 | QPMScreenRecorderManager.getInstance().onActivityResult(this, requestCode, resultCode, data); 30 | } 31 | } 32 | 33 | public static void startRecorder(){ 34 | Context context = QPMManager.getInstance().getContext(); 35 | Intent intent = new Intent(context, QPMScreenRecorderActivity.class); 36 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 37 | context.startActivity(intent); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMServiceListActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | 4 | import com.zk.qpm.R; 5 | import com.zk.qpm.function.ServiceFunction; 6 | import com.zk.qpm.function.TitleFunction; 7 | 8 | public class QPMServiceListActivity extends QPMFunctionBaseActivity { 9 | 10 | @Override 11 | protected int contentViewId() { 12 | return R.layout.jm_gt_activity_four_module; 13 | } 14 | 15 | @Override 16 | protected void initAllFunction() { 17 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_service_list))); 18 | functions.add(new ServiceFunction(this)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/activity/QPMSwitchActivity.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.activity; 2 | 3 | import com.zk.qpm.R; 4 | import com.zk.qpm.function.FloatViewSwitchFunction; 5 | import com.zk.qpm.function.TitleFunction; 6 | 7 | public class QPMSwitchActivity extends QPMFunctionBaseActivity { 8 | 9 | @Override 10 | protected int contentViewId() { 11 | return R.layout.jm_gt_activity_switch; 12 | } 13 | 14 | @Override 15 | protected void initAllFunction() { 16 | functions.add(new TitleFunction(this, getString(R.string.jm_gt_floatview_switch))); 17 | functions.add(new FloatViewSwitchFunction(this)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMActivityStackAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | import java.util.List; 7 | 8 | public class QPMActivityStackAnalysis extends QPMBaseAnalysis{ 9 | 10 | public void onCollectActivityStack(List activityNames){ 11 | analysisResult.activityStackInfos.activityNames = activityNames; 12 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_ACTIVITY_STACK_INFO, analysisResult); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMAppAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMAppAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectAppInfo(String packageName, String appName, 9 | String versionName, int versionCode, 10 | int gtrVersionCode, long startTestTime, int mainThreadId) { 11 | analysisResult.appInfo.packageName = packageName; 12 | analysisResult.appInfo.appName = appName; 13 | analysisResult.appInfo.versionName = versionName; 14 | analysisResult.appInfo.versionCode = versionCode; 15 | analysisResult.appInfo.gtrVersionCode = gtrVersionCode; 16 | analysisResult.appInfo.startTestTime = startTestTime; 17 | analysisResult.appInfo.mainThreadId = mainThreadId; 18 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_APP_INFO, analysisResult); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMAutoAddAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMAutoAddAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectInfo(int pid, int threadCount) { 9 | analysisResult.otherInfo.pId = pid; 10 | analysisResult.otherInfo.threadCount = threadCount; 11 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_AUTO_ADD_INFO, analysisResult); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMBaseAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | import com.zk.qpm.QPMRAnalysisResult; 4 | import com.zk.qpm.manager.QPMCallBackManager; 5 | import com.zk.qpm.manager.QPMRAnalysisManager; 6 | 7 | public abstract class QPMBaseAnalysis { 8 | 9 | protected QPMRAnalysisResult analysisResult = null; 10 | protected QPMCallBackManager callBackManager = null; 11 | 12 | public QPMBaseAnalysis() { 13 | this.analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 14 | this.callBackManager = QPMCallBackManager.getInstance(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMCPUAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMCPUAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectCPUInfo(double cpuPercent) { 9 | analysisResult.cmntInfo.cpu = cpuPercent; 10 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_CPU_INFO, analysisResult); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMDeviceAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMDeviceAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectDeviceInfo(String vendor, String model, String sdkName, int sdkInt) { 9 | analysisResult.deviceInfo.vendor = vendor; 10 | analysisResult.deviceInfo.model = model; 11 | analysisResult.deviceInfo.sdkName = sdkName; 12 | analysisResult.deviceInfo.sdkInt = sdkInt; 13 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_DEVICE_INFO, analysisResult); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMFPSAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMFPSAnalysis extends QPMBaseAnalysis { 7 | 8 | private static final int ONE_SECOND = 1000; 9 | private static final int FPS_LOW_LIMIT = 40; 10 | private static final int BIG_BLOCK_LIMIT = 70; 11 | 12 | private long lastFrameTime = -1; 13 | private long lastNotifyTime = -1; 14 | 15 | public void onCollectFrameInfo(long nowTime) { 16 | analysisResult.frameInfo.drawTimeInSecond.add(nowTime); 17 | while (!analysisResult.frameInfo.drawTimeInSecond.isEmpty() && 18 | analysisResult.frameInfo.drawTimeInSecond.get(0) < nowTime - ONE_SECOND) { 19 | analysisResult.frameInfo.drawTimeInSecond.remove(0); 20 | } 21 | 22 | analysisResult.frameInfo.fps = analysisResult.frameInfo.drawTimeInSecond.size(); 23 | if (nowTime - lastNotifyTime >= ONE_SECOND) { 24 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_FPS_INFO, analysisResult); 25 | lastNotifyTime = nowTime; 26 | } 27 | 28 | //检测大卡顿: 29 | if (lastFrameTime != -1) { 30 | if (nowTime - lastFrameTime > BIG_BLOCK_LIMIT) { 31 | analysisResult.frameInfo.bigBlockTime++; 32 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_BIG_BLOCK_INFO, analysisResult); 33 | } 34 | } 35 | lastFrameTime = nowTime; 36 | 37 | //检测低流畅值区间: 38 | if (analysisResult.frameInfo.fps < FPS_LOW_LIMIT) { 39 | if (!analysisResult.frameInfo.isLowSM) { 40 | analysisResult.frameInfo.isLowSM = true; 41 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_LOW_SM_INFO, analysisResult); 42 | } 43 | } else { 44 | if (analysisResult.frameInfo.isLowSM) { 45 | analysisResult.frameInfo.lowSMTime++; 46 | analysisResult.frameInfo.isLowSM = false; 47 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_LOW_SM_INFO, analysisResult); 48 | } 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMFlowAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMFlowAnalysis extends QPMBaseAnalysis { 7 | 8 | private long lastTime = 0; 9 | private long lastFlowUpload = 0; 10 | private long lastFlowDownload = 0; 11 | 12 | public void onCollectFlowInfo(long time, long flowUp, long flowDown) { 13 | if (lastTime != 0) { 14 | analysisResult.cmntInfo.flowUp += (flowUp - lastFlowUpload) * 1.0 / 1024; 15 | analysisResult.cmntInfo.flowDown += (flowDown - lastFlowDownload) * 1.0 / 1024; 16 | analysisResult.cmntInfo.flowUpSpeed = (flowUp - lastFlowUpload) * 1000.0 / 1024 / (time - lastTime); 17 | analysisResult.cmntInfo.flowDownSpeed = (flowDown - lastFlowDownload) * 1000.0 / 1024 / (time - lastTime); 18 | } 19 | 20 | lastTime = time; 21 | lastFlowUpload = flowUp; 22 | lastFlowDownload = flowDown; 23 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_FLOW_INFO, analysisResult); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMH5MonitorAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMH5MonitorAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectH5MonitorInfo(String url, long whitePageTime) { 9 | analysisResult.h5MonitorInfo.url = url; 10 | analysisResult.h5MonitorInfo.whitePageTime = whitePageTime; 11 | 12 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_H5_MONITOR_INFO, analysisResult); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMMemoryAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMMemoryAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectMemoryInfo(int memory) { 9 | analysisResult.cmntInfo.memory = memory * 1.0 / 1024; 10 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_MEMORY_INFO, analysisResult); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMNetworkAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.QPMRAnalysisResult; 5 | import com.zk.qpm.callback.IAnalysisCallback; 6 | 7 | public class QPMNetworkAnalysis extends QPMBaseAnalysis { 8 | 9 | private static final int MAX_CAPACITY = 300; 10 | 11 | public void onCollectNetworkInfo(String originUrl, 12 | String method, 13 | long requestSize, 14 | long requestTime, 15 | String requestHeader, 16 | String requestContent, 17 | long responseSize, 18 | String responseHeader, 19 | String responseContent, 20 | String responseCode, 21 | long currentTime) { 22 | synchronized (QPMRAnalysisResult.SYNCHRONIZED_NETWORKINFO) { 23 | QPMRAnalysisResult.NetworkInfo networkInfo = new QPMRAnalysisResult.NetworkInfo(); 24 | networkInfo.originUrl = originUrl; 25 | networkInfo.method = method; 26 | networkInfo.requestSize = requestSize; 27 | networkInfo.requestTime = requestTime; 28 | networkInfo.requestHeader = requestHeader; 29 | networkInfo.requestContent = requestContent; 30 | networkInfo.responseSize = responseSize; 31 | networkInfo.responseHeader = responseHeader; 32 | networkInfo.responseContent = responseContent; 33 | networkInfo.responseCode = responseCode; 34 | networkInfo.currentTime = currentTime; 35 | analysisResult.networkInfos.add(networkInfo); 36 | // 大于阈值,删除 37 | while (analysisResult.networkInfos.size() > MAX_CAPACITY) { 38 | analysisResult.networkInfos.remove(0); 39 | } 40 | } 41 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_NETWORK_INFO, analysisResult); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMScreenRecorderStatusAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMScreenRecorderStatusAnalysis extends QPMBaseAnalysis{ 7 | 8 | public void onCollectAppInfo(boolean startStatus, long startTime){ 9 | analysisResult.screenRecorderStatusInfo.startStatus = startStatus; 10 | analysisResult.screenRecorderStatusInfo.startTime = startTime; 11 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_SCREEN_RECORDER_STATUS_INFO, analysisResult); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMThreadAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMThreadAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectThreadInfo(int threadCount, int gtThreadCount) { 9 | analysisResult.cmntInfo.threadCount = threadCount; 10 | analysisResult.cmntInfo.gtThreadCount = gtThreadCount; 11 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_THREAD_INFO, analysisResult); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/analysis/QPMTopActivityAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.analysis; 2 | 3 | 4 | import com.zk.qpm.callback.IAnalysisCallback; 5 | 6 | public class QPMTopActivityAnalysis extends QPMBaseAnalysis { 7 | 8 | public void onCollectTopActivityInfo(String topActivity) { 9 | analysisResult.activityStackInfos.topActivityName = topActivity; 10 | 11 | callBackManager.refreshInfo(IAnalysisCallback.TYPE_REFRESH_TOP_ACTIVITY, analysisResult); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/callback/IAnalysisCallback.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.callback; 2 | 3 | 4 | import androidx.annotation.StringDef; 5 | 6 | import com.zk.qpm.QPMRAnalysisResult; 7 | 8 | import java.lang.annotation.Documented; 9 | import java.lang.annotation.ElementType; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.RetentionPolicy; 12 | import java.lang.annotation.Target; 13 | 14 | /** 15 | * 回调方法有可能来自子线程,如果在主界面要修改 UI,请使用 handler。 16 | */ 17 | public interface IAnalysisCallback { 18 | @Documented 19 | @StringDef({TYPE_REFRESH_PID, 20 | TYPE_REFRESH_APP_INFO, 21 | TYPE_REFRESH_DEVICE_INFO, 22 | TYPE_REFRESH_AUTO_ADD_INFO, 23 | TYPE_REFRESH_TOP_ACTIVITY, 24 | TYPE_REFRESH_FPS_INFO, 25 | TYPE_REFRESH_BIG_BLOCK_INFO, 26 | TYPE_REFRESH_LOW_SM_INFO, 27 | TYPE_REFRESH_CPU_INFO, 28 | TYPE_REFRESH_MEMORY_INFO, 29 | TYPE_REFRESH_FLOW_INFO, 30 | TYPE_REFRESH_THREAD_INFO, 31 | TYPE_REFRESH_NETWORK_INFO, 32 | TYPE_REFRESH_ACTIVITY_STACK_INFO, 33 | TYPE_REFRESH_SCREEN_RECORDER_STATUS_INFO, 34 | TYPE_REFRESH_H5_MONITOR_INFO 35 | }) 36 | @Target({ 37 | ElementType.PARAMETER, 38 | ElementType.FIELD, 39 | ElementType.METHOD, 40 | }) 41 | @Retention(RetentionPolicy.SOURCE) 42 | @interface CallbackType { 43 | String key() default TYPE_REFRESH_PID; 44 | } 45 | 46 | String TYPE_REFRESH_PID = "type_refresh_pid"; 47 | String TYPE_REFRESH_APP_INFO = "type_refresh_app_info"; 48 | String TYPE_REFRESH_DEVICE_INFO = "type_refresh_device_info"; 49 | String TYPE_REFRESH_AUTO_ADD_INFO = "type_refresh_test_info"; 50 | String TYPE_REFRESH_TOP_ACTIVITY = "type_refresh_top_activity_info"; 51 | String TYPE_REFRESH_FPS_INFO = "type_refresh_fps_info"; 52 | String TYPE_REFRESH_BIG_BLOCK_INFO = "type_refresh_big_block_info"; 53 | String TYPE_REFRESH_LOW_SM_INFO = "type_refresh_low_sm_info"; 54 | String TYPE_REFRESH_CPU_INFO = "type_refresh_cpu_info"; 55 | String TYPE_REFRESH_MEMORY_INFO = "type_refresh_memory_info"; 56 | String TYPE_REFRESH_FLOW_INFO = "type_refresh_flow_info"; 57 | String TYPE_REFRESH_THREAD_INFO = "type_refresh_thread_info"; 58 | String TYPE_REFRESH_NETWORK_INFO = "type_refresh_network_info"; 59 | String TYPE_REFRESH_ACTIVITY_STACK_INFO = "type_refresh_activity_stack_info"; 60 | String TYPE_REFRESH_SCREEN_RECORDER_STATUS_INFO = "type_refresh_screen_recorder_status_info"; 61 | String TYPE_REFRESH_H5_MONITOR_INFO = "type_refresh_h5_monitor_info"; 62 | 63 | void refreshInfo(@CallbackType String type, QPMRAnalysisResult analysisResult); 64 | } 65 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/callback/ICallback.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.callback; 2 | 3 | public interface ICallback { 4 | 5 | void callback(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/IExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.content.Context; 4 | 5 | import com.zk.qpm.QPMException; 6 | import com.zk.qpm.floatview.QPMFloatViewType; 7 | 8 | public interface IExecutor { 9 | 10 | @QPMFloatViewType.Type String type(); 11 | 12 | void createShowView(Context context); 13 | 14 | void destoryShowView(); 15 | 16 | void exec() throws QPMException; 17 | 18 | void stop(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetActivityStackExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import com.blankj.utilcode.util.ActivityUtils; 7 | import com.zk.qpm.QPMException; 8 | import com.zk.qpm.analysis.QPMActivityStackAnalysis; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 11 | import com.zk.qpm.floatview.renderer.QPMGetActivityStackRenderer; 12 | import com.zk.qpm.manager.QPMFloatViewManager; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public class QPMGetActivityStackExecutor implements IExecutor { 18 | 19 | private QPMActivityStackAnalysis activityStackAnalysis; 20 | 21 | public QPMGetActivityStackExecutor() { 22 | activityStackAnalysis = new QPMActivityStackAnalysis(); 23 | } 24 | 25 | @Override 26 | public String type() { 27 | return QPMFloatViewType.TYPE_FLOAT_VIEW_ACTIVITY_STACK; 28 | } 29 | 30 | @Override 31 | public void createShowView(Context context) { 32 | IFloatViewRenderer activityBean = new QPMGetActivityStackRenderer(); 33 | QPMFloatViewManager.getInstance().addItem(activityBean); 34 | } 35 | 36 | 37 | @Override 38 | public void destoryShowView() { 39 | QPMFloatViewManager.getInstance().removeItem(type()); 40 | } 41 | 42 | 43 | @Override 44 | public void exec() throws QPMException { 45 | List activityNames = getRunningActivityNames(); 46 | activityStackAnalysis.onCollectActivityStack(activityNames); 47 | } 48 | 49 | @Override 50 | public void stop() { 51 | 52 | } 53 | 54 | private List getRunningActivityNames() { 55 | List activityList = ActivityUtils.getActivityList(); 56 | List activitiNames = new ArrayList<>(); 57 | for (Activity activity : activityList) { 58 | activitiNames.add(activity.getLocalClassName()); 59 | } 60 | return activitiNames; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetAppInfoExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.content.Context; 4 | 5 | import com.blankj.utilcode.util.AppUtils; 6 | import com.zk.qpm.QPMException; 7 | import com.zk.qpm.analysis.QPMAppAnalysis; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 10 | import com.zk.qpm.floatview.renderer.QPMGetAppInfoRenderer; 11 | import com.zk.qpm.manager.QPMFloatViewManager; 12 | 13 | public class QPMGetAppInfoExecutor implements IExecutor { 14 | 15 | private QPMAppAnalysis jmAppAnalysis; 16 | 17 | public QPMGetAppInfoExecutor() { 18 | this.jmAppAnalysis = new QPMAppAnalysis(); 19 | } 20 | 21 | 22 | @Override 23 | public String type() { 24 | return QPMFloatViewType.TYPE_FLOAT_VIEW_PACKAGE; 25 | } 26 | 27 | @Override 28 | public void createShowView(Context context) { 29 | IFloatViewRenderer packageBean = new QPMGetAppInfoRenderer(); 30 | QPMFloatViewManager.getInstance().addItem(packageBean); 31 | } 32 | 33 | @Override 34 | public void destoryShowView() { 35 | QPMFloatViewManager.getInstance().removeItem(type()); 36 | } 37 | 38 | @Override 39 | public void exec() throws QPMException { 40 | jmAppAnalysis.onCollectAppInfo(AppUtils.getAppPackageName(), 41 | AppUtils.getAppName(), 42 | AppUtils.getAppVersionName(), 43 | AppUtils.getAppVersionCode(), 44 | 10005, 45 | System.currentTimeMillis(), 46 | 0); 47 | } 48 | 49 | @Override 50 | public void stop() { 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetAutoAddExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.content.Context; 4 | import android.os.Process; 5 | 6 | import com.zk.qpm.QPMException; 7 | import com.zk.qpm.analysis.QPMAutoAddAnalysis; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 10 | import com.zk.qpm.floatview.renderer.QPMGetAutoAddRenderer; 11 | import com.zk.qpm.manager.QPMFloatViewManager; 12 | 13 | public class QPMGetAutoAddExecutor implements IExecutor { 14 | 15 | private QPMAutoAddAnalysis analysis; 16 | private int count = 1; 17 | 18 | public QPMGetAutoAddExecutor() { 19 | analysis = new QPMAutoAddAnalysis(); 20 | } 21 | 22 | @Override 23 | public String type() { 24 | return QPMFloatViewType.TYPE_FLOAT_VIEW_THREAD_AUTO_ADD; 25 | } 26 | 27 | @Override 28 | public void createShowView(Context context) { 29 | IFloatViewRenderer autoAddBean = new QPMGetAutoAddRenderer(); 30 | QPMFloatViewManager.getInstance().addItem(autoAddBean); 31 | } 32 | 33 | @Override 34 | public void destoryShowView() { 35 | QPMFloatViewManager.getInstance().removeItem(type()); 36 | } 37 | 38 | @Override 39 | public void exec() throws QPMException { 40 | int pid = Process.myPid(); 41 | analysis.onCollectInfo(pid, ++count); 42 | } 43 | 44 | @Override 45 | public void stop() { 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetFPSInfoExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.view.Choreographer; 7 | 8 | import com.zk.qpm.QPMException; 9 | import com.zk.qpm.analysis.QPMFPSAnalysis; 10 | import com.zk.qpm.floatview.QPMFloatViewType; 11 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 12 | import com.zk.qpm.floatview.renderer.QPMGetFPSInfoRenderer; 13 | import com.zk.qpm.manager.QPMFloatViewManager; 14 | 15 | public class QPMGetFPSInfoExecutor implements IExecutor { 16 | 17 | private QPMFPSAnalysis fpsAnalysis; 18 | private boolean isStop; 19 | 20 | public QPMGetFPSInfoExecutor() { 21 | fpsAnalysis = new QPMFPSAnalysis(); 22 | } 23 | 24 | @Override 25 | public String type() { 26 | return QPMFloatViewType.TYPE_FLOAT_VIEW_FPS_VIEW; 27 | } 28 | 29 | @Override 30 | public void createShowView(Context context) { 31 | IFloatViewRenderer fpsBean = new QPMGetFPSInfoRenderer(); 32 | QPMFloatViewManager.getInstance().addItem(fpsBean); 33 | } 34 | 35 | @Override 36 | public void destoryShowView() { 37 | QPMFloatViewManager.getInstance().removeItem(type()); 38 | } 39 | 40 | @Override 41 | public void exec() throws QPMException { 42 | Choreographer.getInstance().postFrameCallback(frameCallback); 43 | } 44 | 45 | @Override 46 | public void stop() { 47 | isStop = true; 48 | } 49 | 50 | private Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() { 51 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 52 | public void doFrame(long frameTimeNanos) { 53 | long nowTime = System.currentTimeMillis(); 54 | fpsAnalysis.onCollectFrameInfo(nowTime); 55 | 56 | if (!isStop) { 57 | Choreographer.getInstance().postFrameCallback(this); 58 | } 59 | } 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetFlowInfoExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.content.Context; 4 | import android.net.TrafficStats; 5 | import android.os.Process; 6 | 7 | import com.zk.qpm.QPMException; 8 | import com.zk.qpm.analysis.QPMFlowAnalysis; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 11 | import com.zk.qpm.floatview.renderer.QPMGetFlowInfoRenderer; 12 | import com.zk.qpm.manager.QPMFloatViewManager; 13 | 14 | import java.io.BufferedReader; 15 | import java.io.File; 16 | import java.io.FileReader; 17 | import java.io.FilenameFilter; 18 | 19 | 20 | public class QPMGetFlowInfoExecutor implements IExecutor { 21 | 22 | private QPMFlowAnalysis flowAnalysis; 23 | 24 | public QPMGetFlowInfoExecutor() { 25 | flowAnalysis = new QPMFlowAnalysis(); 26 | } 27 | 28 | @Override 29 | public String type() { 30 | return QPMFloatViewType.TYPE_FLOAT_VIEW_FLOW_DATA; 31 | } 32 | 33 | @Override 34 | public void createShowView(Context context) { 35 | IFloatViewRenderer flowBean = new QPMGetFlowInfoRenderer(); 36 | QPMFloatViewManager.getInstance().addItem(flowBean); 37 | } 38 | 39 | @Override 40 | public void destoryShowView() { 41 | QPMFloatViewManager.getInstance().removeItem(type()); 42 | } 43 | 44 | @Override 45 | public void exec() throws QPMException { 46 | long time = System.currentTimeMillis(); 47 | long[] flow = getFlowInfo(); 48 | flowAnalysis.onCollectFlowInfo(time, flow[0], flow[1]); 49 | } 50 | 51 | @Override 52 | public void stop() { 53 | 54 | } 55 | 56 | private long[] getFlowInfo() { 57 | int uid = Process.myUid(); 58 | return getFlowByAPI(uid); 59 | /*try { 60 | return getFlowByFile(uid); 61 | } catch (Exception e) { 62 | return getFlowByAPI(uid); 63 | }*/ 64 | } 65 | 66 | private long[] getFlowByFile(final int uid) throws Exception { 67 | File dir = new File("/proc/uid_stat/"); 68 | String[] children = dir.list(new FilenameFilter() { 69 | @Override 70 | public boolean accept(File dir, String name) { 71 | return name.contains(String.valueOf(uid)); 72 | } 73 | }); 74 | if (children.length == 0) { 75 | throw new IllegalAccessException("without uid file"); 76 | } 77 | 78 | File uidFileDir = new File(dir, String.valueOf(uid)); 79 | File uidActualFileReceived = new File(uidFileDir, "tcp_rcv"); 80 | File uidActualFileSent = new File(uidFileDir, "tcp_snd"); 81 | String textReceived = new BufferedReader(new FileReader(uidActualFileReceived)).readLine(); 82 | String textSent = new BufferedReader(new FileReader(uidActualFileSent)).readLine(); 83 | return new long[]{Long.parseLong(textSent), Long.parseLong(textReceived)}; 84 | } 85 | 86 | private long[] getFlowByAPI(int uid) { 87 | long flowUpload = TrafficStats.getUidTxBytes(uid); 88 | long flowDownload = TrafficStats.getUidRxBytes(uid); 89 | return new long[]{flowUpload, flowDownload}; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetH5MonitorInfoExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.content.Context; 4 | 5 | import com.zk.qpm.QPMException; 6 | import com.zk.qpm.QPMRAnalysisResult; 7 | import com.zk.qpm.analysis.QPMH5MonitorAnalysis; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 10 | import com.zk.qpm.floatview.renderer.QPMGetH5MonitorRenderer; 11 | import com.zk.qpm.manager.QPMFloatViewManager; 12 | import com.zk.qpm.manager.QPMRAnalysisManager; 13 | 14 | 15 | public class QPMGetH5MonitorInfoExecutor implements IExecutor { 16 | 17 | private QPMH5MonitorAnalysis analysis; 18 | private QPMRAnalysisResult.H5MonitorInfo h5MonitorInfo; 19 | 20 | public QPMGetH5MonitorInfoExecutor() { 21 | analysis = new QPMH5MonitorAnalysis(); 22 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 23 | h5MonitorInfo = analysisResult.h5MonitorInfo; 24 | } 25 | 26 | @Override 27 | public String type() { 28 | return QPMFloatViewType.TYPE_FLOAT_VIEW_H5_MONITOR; 29 | } 30 | 31 | @Override 32 | public void createShowView(Context context) { 33 | IFloatViewRenderer h5Monitor = new QPMGetH5MonitorRenderer(); 34 | QPMFloatViewManager.getInstance().addItem(h5Monitor); 35 | } 36 | 37 | @Override 38 | public void destoryShowView() { 39 | QPMFloatViewManager.getInstance().removeItem(type()); 40 | } 41 | 42 | @Override 43 | public void exec() throws QPMException { 44 | analysis.onCollectH5MonitorInfo(h5MonitorInfo.url, h5MonitorInfo.whitePageTime); 45 | } 46 | 47 | @Override 48 | public void stop() { 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetMemoryInfoExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Context; 5 | import android.os.Debug; 6 | import android.os.Process; 7 | 8 | import com.zk.qpm.QPMException; 9 | import com.zk.qpm.analysis.QPMMemoryAnalysis; 10 | import com.zk.qpm.floatview.QPMFloatViewType; 11 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 12 | import com.zk.qpm.floatview.renderer.QPMGetMemoryInfoRenderer; 13 | import com.zk.qpm.manager.QPMFloatViewManager; 14 | 15 | import java.lang.reflect.Method; 16 | 17 | public class QPMGetMemoryInfoExecutor implements IExecutor { 18 | 19 | private QPMMemoryAnalysis memoryAnalysis; 20 | private ActivityManager am; 21 | 22 | public QPMGetMemoryInfoExecutor(ActivityManager am) { 23 | memoryAnalysis = new QPMMemoryAnalysis(); 24 | this.am = am; 25 | } 26 | 27 | @Override 28 | public String type() { 29 | return QPMFloatViewType.TYPE_FLOAT_VIEW_MEMORY_VIEW; 30 | } 31 | 32 | @Override 33 | public void createShowView(Context context) { 34 | IFloatViewRenderer memoryBean = new QPMGetMemoryInfoRenderer(); 35 | QPMFloatViewManager.getInstance().addItem(memoryBean); 36 | } 37 | 38 | @Override 39 | public void destoryShowView() { 40 | QPMFloatViewManager.getInstance().removeItem(type()); 41 | } 42 | 43 | @Override 44 | public void exec() throws QPMException { 45 | int pid = Process.myPid(); 46 | int memory = getMemoryForProcess(pid); 47 | memoryAnalysis.onCollectMemoryInfo(memory); 48 | } 49 | 50 | @Override 51 | public void stop() { 52 | 53 | } 54 | 55 | // 进程总内存 56 | private int getMemoryForProcess(int pid) { 57 | if (am == null) { 58 | return 0; 59 | } 60 | int[] myMempid = new int[]{pid}; 61 | Debug.MemoryInfo memoryInfo = am.getProcessMemoryInfo(myMempid)[0]; 62 | // 首先用反射拿uss的值 63 | Class clazz = memoryInfo.getClass(); 64 | try { 65 | Method getTotalUssMethod = clazz.getDeclaredMethod("getTotalUss", new Class[]{}); 66 | getTotalUssMethod.setAccessible(true); 67 | Integer totalUss = (Integer) getTotalUssMethod.invoke(memoryInfo, new Object[]{}); 68 | return totalUss; 69 | } catch (Exception e) { 70 | // 因为getTotalUss方法是hide的,也许部分手机反射会出问题,所以这里套一个public的获取 71 | // 经过测试pss 会比uss 高出几M到十M左右 72 | return memoryInfo.getTotalPss(); 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetThreadCountExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.content.Context; 4 | import android.os.Process; 5 | 6 | import com.zk.qpm.QPMException; 7 | import com.zk.qpm.analysis.QPMThreadAnalysis; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 10 | import com.zk.qpm.floatview.renderer.QPMGetThreadCountRenderer; 11 | import com.zk.qpm.manager.QPMFloatViewManager; 12 | import com.zk.qpm.manager.QPMThreadManager; 13 | 14 | import java.io.BufferedReader; 15 | import java.io.File; 16 | import java.io.FileInputStream; 17 | import java.io.IOException; 18 | import java.io.InputStreamReader; 19 | 20 | public class QPMGetThreadCountExecutor implements IExecutor { 21 | 22 | private static final int BUFFER_SIZE = 1000; 23 | private QPMThreadAnalysis threadAnalysis; 24 | 25 | public QPMGetThreadCountExecutor() { 26 | threadAnalysis = new QPMThreadAnalysis(); 27 | } 28 | 29 | @Override 30 | public String type() { 31 | return QPMFloatViewType.TYPE_FLOAT_VIEW_THREAD_COUNT; 32 | } 33 | 34 | @Override 35 | public void createShowView(Context context) { 36 | IFloatViewRenderer threadCountBean = new QPMGetThreadCountRenderer(); 37 | QPMFloatViewManager.getInstance().addItem(threadCountBean); 38 | } 39 | 40 | @Override 41 | public void destoryShowView() { 42 | QPMFloatViewManager.getInstance().removeItem(type()); 43 | } 44 | 45 | @Override 46 | public void exec() throws QPMException { 47 | int pid = Process.myPid(); 48 | int threadCount = getThreadsCount(pid); 49 | // 计算本GT所占用的线程数 50 | int gtThreadCount = getGTConsumeThreadCount(); 51 | threadAnalysis.onCollectThreadInfo(threadCount, gtThreadCount); 52 | } 53 | 54 | @Override 55 | public void stop() { 56 | 57 | } 58 | 59 | private int getThreadsCount(int pid) { 60 | int threadCount = 0; 61 | File threadDir = new File("/proc/" + pid + "/task"); 62 | if (!threadDir.exists()) { 63 | return threadCount; 64 | } 65 | 66 | File[] threadFiles = threadDir.listFiles(); 67 | threadCount = threadFiles.length; 68 | return threadCount; 69 | } 70 | 71 | private int getThreadsCountByProcess(int pid){ 72 | int threadCount = 0; 73 | File progressFile = new File("/proc/" + pid + "/stat"); 74 | BufferedReader reader = null; 75 | try { 76 | reader = new BufferedReader(new InputStreamReader( 77 | new FileInputStream(progressFile)), BUFFER_SIZE); 78 | String line = reader.readLine(); 79 | String[] fields = line.split(" "); 80 | threadCount = Integer.parseInt(fields[19]); 81 | } catch (Exception e) { 82 | e.printStackTrace(); 83 | } finally { 84 | try { 85 | reader.close(); 86 | } catch (IOException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | return threadCount; 91 | } 92 | 93 | private int getGTConsumeThreadCount() { 94 | return QPMThreadManager.getInstance().getAllThreadCount(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMGetTopActivityExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import com.blankj.utilcode.util.ActivityUtils; 7 | import com.zk.qpm.QPMException; 8 | import com.zk.qpm.analysis.QPMTopActivityAnalysis; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 11 | import com.zk.qpm.floatview.renderer.QPMGetTopActivityRenderer; 12 | import com.zk.qpm.manager.QPMFloatViewManager; 13 | 14 | public class QPMGetTopActivityExecutor implements IExecutor { 15 | 16 | private QPMTopActivityAnalysis analysys; 17 | 18 | public QPMGetTopActivityExecutor() { 19 | analysys = new QPMTopActivityAnalysis(); 20 | } 21 | 22 | @Override 23 | public String type() { 24 | return QPMFloatViewType.TYPE_FLOAT_VIEW_TOP_ACTIVITY; 25 | } 26 | 27 | @Override 28 | public void createShowView(Context context) { 29 | IFloatViewRenderer topActivityBean = new QPMGetTopActivityRenderer(); 30 | QPMFloatViewManager.getInstance().addItem(topActivityBean); 31 | } 32 | 33 | @Override 34 | public void destoryShowView() { 35 | QPMFloatViewManager.getInstance().removeItem(type()); 36 | } 37 | 38 | @Override 39 | public void exec() throws QPMException { 40 | Activity topActivity = ActivityUtils.getTopActivity(); 41 | if (topActivity != null) { 42 | analysys.onCollectTopActivityInfo(topActivity.getLocalClassName()); 43 | } 44 | } 45 | 46 | @Override 47 | public void stop() { 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/executor/QPMScreenRecorderStatusExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.executor; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | 6 | import com.zk.qpm.QPMException; 7 | import com.zk.qpm.analysis.QPMScreenRecorderStatusAnalysis; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 10 | import com.zk.qpm.floatview.renderer.QPMScreenRecorderStatusRenderer; 11 | import com.zk.qpm.manager.QPMFloatViewManager; 12 | import com.zk.qpm.manager.QPMScreenRecorderManager; 13 | 14 | public class QPMScreenRecorderStatusExecutor implements IExecutor { 15 | 16 | private QPMScreenRecorderStatusAnalysis analysis; 17 | 18 | public QPMScreenRecorderStatusExecutor() { 19 | analysis = new QPMScreenRecorderStatusAnalysis(); 20 | } 21 | 22 | @Override 23 | public String type() { 24 | return QPMFloatViewType.TYPE_FLOAT_VIEW_SCREEN_RECORDER; 25 | } 26 | 27 | @Override 28 | public void createShowView(Context context) { 29 | IFloatViewRenderer renderer = new QPMScreenRecorderStatusRenderer(); 30 | QPMFloatViewManager.getInstance().addItem(renderer); 31 | } 32 | 33 | @Override 34 | public void destoryShowView() { 35 | QPMFloatViewManager.getInstance().removeItem(type()); 36 | } 37 | 38 | @Override 39 | public void exec() throws QPMException { 40 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ 41 | analysis.onCollectAppInfo(QPMScreenRecorderManager.getInstance().isStart(), 42 | QPMScreenRecorderManager.getInstance().getStartTime()); 43 | } 44 | } 45 | 46 | @Override 47 | public void stop() { 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/QPMFloatViewBean.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview; 2 | 3 | public class QPMFloatViewBean { 4 | 5 | public @QPMFloatViewType.Type String type; 6 | // 开关显示的名字 7 | public String switchName; 8 | // 开关的提示内容,不需要可为空 9 | public String switchTip; 10 | // 是否默认开启这个开关 11 | public boolean switchDefault; 12 | // 开关默认的排序 13 | public int switchSort; 14 | 15 | public QPMFloatViewBean(String type, String switchName, String switchTip, boolean switchDefault, int switchSort) { 16 | this.type = type; 17 | this.switchName = switchName; 18 | this.switchTip = switchTip; 19 | this.switchDefault = switchDefault; 20 | this.switchSort = switchSort; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/QPMFloatViewType.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview; 2 | 3 | 4 | import androidx.annotation.StringDef; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | 9 | public interface QPMFloatViewType { 10 | 11 | @Retention(RetentionPolicy.SOURCE) 12 | @StringDef({TYPE_FLOAT_VIEW_PACKAGE, 13 | TYPE_FLOAT_VIEW_TOP_ACTIVITY, 14 | TYPE_FLOAT_VIEW_FPS_VIEW, 15 | TYPE_FLOAT_VIEW_THREAD_AUTO_ADD, 16 | TYPE_FLOAT_VIEW_CPU_VIEW, 17 | TYPE_FLOAT_VIEW_MEMORY_VIEW, 18 | TYPE_FLOAT_VIEW_ACTIVITY_STACK, 19 | TYPE_FLOAT_VIEW_THREAD_COUNT, 20 | TYPE_FLOAT_VIEW_FLOW_DATA, 21 | TYPE_FLOAT_VIEW_NETWORK_API, 22 | TYPE_FLOAT_VIEW_SCREEN_RECORDER, 23 | TYPE_FLOAT_VIEW_H5_MONITOR, 24 | TYPE_FLOAT_VIEW_TEMPLATE_BIG_TEXT, 25 | TYPE_FLOAT_VIEW_TEMPLATE_KEY_VALUE, 26 | TYPE_FLOAT_VIEW_TEMPLATE_KEY_PIC, 27 | TYPE_FLOAT_VIEW_TEMPLATE_PIC_VALUE, 28 | TYPE_FLOAT_VIEW_TEMPLATE_CUSTOM 29 | }) 30 | @interface Type { 31 | String key() default TYPE_FLOAT_VIEW_PACKAGE; 32 | } 33 | 34 | 35 | String TYPE_FLOAT_VIEW_PACKAGE = "type_float_view_package"; 36 | String TYPE_FLOAT_VIEW_TOP_ACTIVITY = "type_float_view_top_activity"; 37 | String TYPE_FLOAT_VIEW_FPS_VIEW = "type_float_view_fps_view"; 38 | String TYPE_FLOAT_VIEW_THREAD_AUTO_ADD = "type_float_view_thread_auto_add"; 39 | String TYPE_FLOAT_VIEW_CPU_VIEW = "type_float_view_cpu_view"; 40 | String TYPE_FLOAT_VIEW_MEMORY_VIEW = "type_float_view_memory_view"; 41 | String TYPE_FLOAT_VIEW_ACTIVITY_STACK = "type_float_view_activity_stack"; 42 | String TYPE_FLOAT_VIEW_THREAD_COUNT = "type_float_view_thread_count"; 43 | String TYPE_FLOAT_VIEW_FLOW_DATA = "type_float_view_flow_data"; 44 | String TYPE_FLOAT_VIEW_NETWORK_API = "type_float_view_network_api"; 45 | String TYPE_FLOAT_VIEW_SCREEN_RECORDER = "type_float_view_screen_recorder"; 46 | String TYPE_FLOAT_VIEW_H5_MONITOR = "type_float_view_h5_monitor"; 47 | String TYPE_FLOAT_VIEW_TEMPLATE_BIG_TEXT = "type_float_view_template_big_text"; 48 | String TYPE_FLOAT_VIEW_TEMPLATE_KEY_VALUE = "type_float_view_template_key_value"; 49 | String TYPE_FLOAT_VIEW_TEMPLATE_KEY_PIC = "type_float_view_template_key_pic"; 50 | String TYPE_FLOAT_VIEW_TEMPLATE_PIC_VALUE = "type_float_view_template_pic_value"; 51 | String TYPE_FLOAT_VIEW_TEMPLATE_CUSTOM = "type_float_view_template_custom"; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/BaseRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | 6 | import com.zk.qpm.manager.QPMManager; 7 | import com.zk.qpm.manager.QPMSwitchManager; 8 | 9 | public abstract class BaseRenderer implements IFloatViewRenderer { 10 | 11 | protected View mView; 12 | 13 | @Override 14 | public boolean isShow() { 15 | return QPMSwitchManager.getInstance().isSwitchOpen(QPMManager.getInstance().getContext(), type()); 16 | } 17 | 18 | @Override 19 | public View getView() { 20 | if (mView == null) { 21 | LayoutInflater inflater = LayoutInflater.from(QPMManager.getInstance().getContext()); 22 | mView = inflater.inflate(getLayoutId(), null, false); 23 | } 24 | return mView; 25 | } 26 | 27 | @Override 28 | public void renderer() { 29 | if (mView == null) { 30 | return; 31 | } 32 | renderer(mView); 33 | } 34 | 35 | protected abstract int getLayoutId(); 36 | 37 | protected abstract void renderer(View mView); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/BaseTemplateRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | 6 | import com.zk.qpm.manager.QPMManager; 7 | import com.zk.qpm.manager.QPMSwitchManager; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | public abstract class BaseTemplateRenderer implements IFloatViewRenderer { 13 | 14 | protected View mView; 15 | protected Map mParam; 16 | 17 | public BaseTemplateRenderer(Map mParam) { 18 | this.mParam = mParam; 19 | if (this.mParam == null) { 20 | this.mParam = new HashMap<>(); 21 | } 22 | } 23 | 24 | public void update(Map param) { 25 | mParam.clear(); 26 | if (param != null && !param.isEmpty()) { 27 | mParam.putAll(param); 28 | } 29 | } 30 | 31 | @Override 32 | public boolean isShow() { 33 | return QPMSwitchManager.getInstance().isSwitchOpen(QPMManager.getInstance().getContext(), type()); 34 | } 35 | 36 | @Override 37 | public View getView() { 38 | if (mView == null) { 39 | LayoutInflater inflater = LayoutInflater.from(QPMManager.getInstance().getContext()); 40 | mView = inflater.inflate(getLayoutId(), null, false); 41 | } 42 | return mView; 43 | } 44 | 45 | @Override 46 | public void renderer() { 47 | if (mView == null) { 48 | return; 49 | } 50 | renderer(mView, mParam); 51 | } 52 | 53 | protected abstract int getLayoutId(); 54 | 55 | protected abstract void renderer(View mView, Map mParam); 56 | } 57 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/IFloatViewRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.view.View; 4 | 5 | public interface IFloatViewRenderer { 6 | 7 | String type(); 8 | 9 | boolean isShow(); 10 | 11 | View getView(); 12 | 13 | void renderer(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetActivityStackRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.text.TextUtils; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.QPMRAnalysisResult; 8 | import com.zk.qpm.R; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.manager.QPMRAnalysisManager; 11 | 12 | 13 | public class QPMGetActivityStackRenderer extends BaseRenderer { 14 | 15 | @Override 16 | public String type() { 17 | return QPMFloatViewType.TYPE_FLOAT_VIEW_ACTIVITY_STACK; 18 | } 19 | 20 | @Override 21 | protected int getLayoutId() { 22 | return R.layout.jm_gt_item_floatview_keylinevalue; 23 | } 24 | 25 | @Override 26 | protected void renderer(View mView) { 27 | TextView keyView = mView.findViewById(R.id.tv_key); 28 | TextView valueView = mView.findViewById(R.id.tv_value); 29 | keyView.setText(R.string.jm_gt_floatview_activitystack); 30 | 31 | final StringBuilder stringBuilder = new StringBuilder(); 32 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 33 | if (analysisResult.activityStackInfos.activityNames != null 34 | && !analysisResult.activityStackInfos.activityNames.isEmpty()) { 35 | for (String activityNames : analysisResult.activityStackInfos.activityNames) { 36 | stringBuilder.append(activityNames).append("\n"); 37 | } 38 | if (stringBuilder.length() != 0) { 39 | stringBuilder.setLength(stringBuilder.length() - "\n".length()); 40 | } 41 | } 42 | String data = stringBuilder.toString(); 43 | if (!TextUtils.isEmpty(data)) { 44 | valueView.setText(data); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetAppInfoRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.text.TextUtils; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.QPMRAnalysisResult; 8 | import com.zk.qpm.R; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.manager.QPMRAnalysisManager; 11 | 12 | 13 | public class QPMGetAppInfoRenderer extends BaseRenderer { 14 | 15 | @Override 16 | public String type() { 17 | return QPMFloatViewType.TYPE_FLOAT_VIEW_PACKAGE; 18 | } 19 | 20 | @Override 21 | protected int getLayoutId() { 22 | return R.layout.jm_gt_item_floatview_keyvalue; 23 | } 24 | 25 | @Override 26 | protected void renderer(View mView) { 27 | TextView keyView = mView.findViewById(R.id.tv_key); 28 | TextView valueView = mView.findViewById(R.id.tv_value); 29 | 30 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 31 | String data = analysisResult.appInfo.packageName; 32 | if (!TextUtils.isEmpty(data) && !valueView.getText().toString().equals(data)) { 33 | keyView.setText(R.string.jm_gt_floatview_package); 34 | valueView.setText(data); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetAutoAddRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.text.TextUtils; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.QPMRAnalysisResult; 8 | import com.zk.qpm.R; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.manager.QPMRAnalysisManager; 11 | 12 | public class QPMGetAutoAddRenderer extends BaseRenderer { 13 | 14 | @Override 15 | public String type() { 16 | return QPMFloatViewType.TYPE_FLOAT_VIEW_THREAD_AUTO_ADD; 17 | } 18 | 19 | @Override 20 | protected int getLayoutId() { 21 | return R.layout.jm_gt_item_floatview_keyvalue; 22 | } 23 | 24 | @Override 25 | protected void renderer(View mView) { 26 | TextView keyView = mView.findViewById(R.id.tv_key); 27 | TextView valueView = mView.findViewById(R.id.tv_value); 28 | keyView.setText(R.string.jm_gt_floatview_auto_add); 29 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 30 | String data = String.valueOf(analysisResult.otherInfo.threadCount); 31 | if (!TextUtils.isEmpty(data)) { 32 | valueView.setText(data); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetCPUInfoRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.text.TextUtils; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.QPMRAnalysisResult; 8 | import com.zk.qpm.R; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.manager.QPMRAnalysisManager; 11 | import com.zk.qpm.utils.DecimalFormatUtil; 12 | 13 | public class QPMGetCPUInfoRenderer extends BaseRenderer { 14 | 15 | @Override 16 | public String type() { 17 | return QPMFloatViewType.TYPE_FLOAT_VIEW_CPU_VIEW; 18 | } 19 | 20 | @Override 21 | protected int getLayoutId() { 22 | return R.layout.jm_gt_item_floatview_keyvalue; 23 | } 24 | 25 | @Override 26 | protected void renderer(View mView) { 27 | TextView keyView = mView.findViewById(R.id.tv_key); 28 | TextView valueView = mView.findViewById(R.id.tv_value); 29 | keyView.setText(R.string.jm_gt_floatview_cpu); 30 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 31 | String data = DecimalFormatUtil.setScale(analysisResult.cmntInfo.cpu, 1) + "%"; 32 | if (!TextUtils.isEmpty(data)) { 33 | valueView.setText(data); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetFPSInfoRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.zk.qpm.QPMRAnalysisResult; 9 | import com.zk.qpm.R; 10 | import com.zk.qpm.floatview.QPMFloatViewType; 11 | import com.zk.qpm.manager.QPMManager; 12 | import com.zk.qpm.manager.QPMRAnalysisManager; 13 | 14 | 15 | public class QPMGetFPSInfoRenderer extends BaseRenderer { 16 | 17 | @Override 18 | public String type() { 19 | return QPMFloatViewType.TYPE_FLOAT_VIEW_FPS_VIEW; 20 | } 21 | 22 | @Override 23 | protected int getLayoutId() { 24 | return R.layout.jm_gt_item_floatview_fps; 25 | } 26 | 27 | @Override 28 | protected void renderer(View mView) { 29 | TextView keyView = mView.findViewById(R.id.tv_key); 30 | TextView valueView = mView.findViewById(R.id.tv_value); 31 | View statusView = mView.findViewById(R.id.v_status); 32 | keyView.setText(R.string.jm_gt_floatview_fps); 33 | Context context = QPMManager.getInstance().getContext(); 34 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 35 | final QPMRAnalysisResult.FrameInfo frameInfo = analysisResult.frameInfo; 36 | final StringBuilder sb = new StringBuilder(); 37 | sb.append(context.getString(R.string.jm_gt_floatview_bigblock)).append(frameInfo.bigBlockTime).append("\n") 38 | .append(context.getString(R.string.jm_gt_floatview_lowsm)).append(frameInfo.lowSMTime); 39 | String data = "" + analysisResult.frameInfo.fps + "\n" + sb.toString(); 40 | if (!TextUtils.isEmpty(data)) { 41 | valueView.setText(data); 42 | } 43 | 44 | if (frameInfo.isLowSM) { 45 | statusView.setBackgroundResource(R.drawable.jm_gt_shape_fps_red); 46 | } else { 47 | statusView.setBackgroundResource(R.drawable.jm_gt_shape_fps_green); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetFlowInfoRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.zk.qpm.QPMRAnalysisResult; 9 | import com.zk.qpm.R; 10 | import com.zk.qpm.floatview.QPMFloatViewType; 11 | import com.zk.qpm.manager.QPMManager; 12 | import com.zk.qpm.manager.QPMRAnalysisManager; 13 | import com.zk.qpm.utils.DecimalFormatUtil; 14 | 15 | 16 | public class QPMGetFlowInfoRenderer extends BaseRenderer { 17 | 18 | @Override 19 | public String type() { 20 | return QPMFloatViewType.TYPE_FLOAT_VIEW_FLOW_DATA; 21 | } 22 | 23 | @Override 24 | protected int getLayoutId() { 25 | return R.layout.jm_gt_item_floatview_keylinevalue; 26 | } 27 | 28 | @Override 29 | protected void renderer(View mView) { 30 | TextView keyView = mView.findViewById(R.id.tv_key); 31 | TextView valueView = mView.findViewById(R.id.tv_value); 32 | keyView.setText(R.string.jm_gt_floatview_flow); 33 | Context context = QPMManager.getInstance().getContext(); 34 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 35 | final StringBuilder flowSB = new StringBuilder(); 36 | flowSB.append(context.getString(R.string.jm_gt_upload_flow)) 37 | .append(DecimalFormatUtil.setScale(analysisResult.cmntInfo.flowUp, 1)) 38 | .append(context.getString(R.string.jm_gt_flow_unit)).append("\n") 39 | 40 | .append(context.getString(R.string.jm_gt_upload_speed)) 41 | .append(DecimalFormatUtil.setScale(analysisResult.cmntInfo.flowUpSpeed, 1)) 42 | .append(context.getString(R.string.jm_gt_speed_unit)).append("\n") 43 | 44 | .append(context.getString(R.string.jm_gt_download_flow)) 45 | .append(DecimalFormatUtil.setScale(analysisResult.cmntInfo.flowDown, 1)) 46 | .append(context.getString(R.string.jm_gt_flow_unit)).append("\n") 47 | 48 | .append(context.getString(R.string.jm_gt_download_speed)) 49 | .append(DecimalFormatUtil.setScale(analysisResult.cmntInfo.flowDownSpeed, 1)) 50 | .append(context.getString(R.string.jm_gt_speed_unit)); 51 | 52 | String data = flowSB.toString(); 53 | if (!TextUtils.isEmpty(data)) { 54 | valueView.setText(data); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetH5MonitorRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.view.View; 4 | import android.widget.TextView; 5 | 6 | import com.zk.qpm.QPMRAnalysisResult; 7 | import com.zk.qpm.R; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.manager.QPMRAnalysisManager; 10 | 11 | 12 | public class QPMGetH5MonitorRenderer extends BaseRenderer { 13 | 14 | @Override 15 | public String type() { 16 | return QPMFloatViewType.TYPE_FLOAT_VIEW_H5_MONITOR; 17 | } 18 | 19 | @Override 20 | protected int getLayoutId() { 21 | return R.layout.jm_gt_item_floatview_keyvalue; 22 | } 23 | 24 | @Override 25 | protected void renderer(View mView) { 26 | TextView keyView = mView.findViewById(R.id.tv_key); 27 | TextView valueView = mView.findViewById(R.id.tv_value); 28 | keyView.setText(R.string.jm_gt_floatview_h5_monitor); 29 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 30 | String url = analysisResult.h5MonitorInfo.url; 31 | long whitePageTime = analysisResult.h5MonitorInfo.whitePageTime; 32 | valueView.setText("白屏时间:" + whitePageTime + " ms\n\n主页地址:" + url); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetMemoryInfoRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.text.TextUtils; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.QPMRAnalysisResult; 8 | import com.zk.qpm.R; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.manager.QPMRAnalysisManager; 11 | import com.zk.qpm.utils.DecimalFormatUtil; 12 | 13 | public class QPMGetMemoryInfoRenderer extends BaseRenderer { 14 | 15 | @Override 16 | public String type() { 17 | return QPMFloatViewType.TYPE_FLOAT_VIEW_MEMORY_VIEW; 18 | } 19 | 20 | @Override 21 | protected int getLayoutId() { 22 | return R.layout.jm_gt_item_floatview_keyvalue; 23 | } 24 | 25 | @Override 26 | protected void renderer(View mView) { 27 | TextView keyView = mView.findViewById(R.id.tv_key); 28 | TextView valueView = mView.findViewById(R.id.tv_value); 29 | keyView.setText(R.string.jm_gt_floatview_memory); 30 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 31 | String data = DecimalFormatUtil.setScale(analysisResult.cmntInfo.memory, 1) + "MB"; 32 | if (!TextUtils.isEmpty(data)) { 33 | valueView.setText(data); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetNetworkInfoRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.net.Uri; 4 | import android.text.TextUtils; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.zk.qpm.QPMRAnalysisResult; 9 | import com.zk.qpm.R; 10 | import com.zk.qpm.floatview.QPMFloatViewType; 11 | import com.zk.qpm.manager.QPMRAnalysisManager; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | public class QPMGetNetworkInfoRenderer extends BaseRenderer { 17 | 18 | @Override 19 | public String type() { 20 | return QPMFloatViewType.TYPE_FLOAT_VIEW_NETWORK_API; 21 | } 22 | 23 | @Override 24 | protected int getLayoutId() { 25 | return R.layout.jm_gt_item_floatview_keylinevalue; 26 | } 27 | 28 | @Override 29 | protected void renderer(View mView) { 30 | TextView keyView = mView.findViewById(R.id.tv_key); 31 | TextView valueView = mView.findViewById(R.id.tv_value); 32 | keyView.setText(R.string.jm_gt_floatview_api); 33 | 34 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 35 | final StringBuilder networkSB = new StringBuilder(); 36 | List networkInfos = new ArrayList<>(); 37 | synchronized (QPMRAnalysisResult.SYNCHRONIZED_NETWORKINFO) { 38 | if (!analysisResult.networkInfos.isEmpty()) { 39 | for (int i = analysisResult.networkInfos.size() - 1; i >= 0; i--) { 40 | networkInfos.add(analysisResult.networkInfos.get(i)); 41 | if (networkInfos.size() >= 3) { 42 | break; 43 | } 44 | } 45 | } 46 | } 47 | if (networkInfos.isEmpty()) { 48 | return; 49 | } 50 | for (QPMRAnalysisResult.NetworkInfo networkInfo : networkInfos) { 51 | try { 52 | networkSB.append(Uri.parse(networkInfo.originUrl).getPath()).append("\n"); 53 | } catch (Exception e) { 54 | networkSB.append(networkInfo.originUrl).append("\n"); 55 | } 56 | } 57 | if (networkSB.length() != 0) { 58 | networkSB.setLength(networkSB.length() - "\n".length()); 59 | } 60 | String data = networkSB.toString(); 61 | 62 | if (!TextUtils.isEmpty(data)) { 63 | valueView.setText(data); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetThreadCountRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.zk.qpm.QPMRAnalysisResult; 9 | import com.zk.qpm.R; 10 | import com.zk.qpm.floatview.QPMFloatViewType; 11 | import com.zk.qpm.manager.QPMManager; 12 | import com.zk.qpm.manager.QPMRAnalysisManager; 13 | 14 | public class QPMGetThreadCountRenderer extends BaseRenderer { 15 | 16 | @Override 17 | public String type() { 18 | return QPMFloatViewType.TYPE_FLOAT_VIEW_THREAD_COUNT; 19 | } 20 | 21 | @Override 22 | protected int getLayoutId() { 23 | return R.layout.jm_gt_item_floatview_keylinevalue; 24 | } 25 | 26 | @Override 27 | protected void renderer(View mView) { 28 | TextView keyView = mView.findViewById(R.id.tv_key); 29 | TextView valueView = mView.findViewById(R.id.tv_value); 30 | keyView.setText(R.string.jm_gt_floatview_threadcount); 31 | Context context = QPMManager.getInstance().getContext(); 32 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 33 | final StringBuilder threadSB = new StringBuilder(); 34 | threadSB.append(context.getString(R.string.jm_gt_floatview_all_thread)).append(analysisResult.cmntInfo.threadCount).append("\n") 35 | .append(context.getString(R.string.jm_gt_floatview_gt_thread)).append(analysisResult.cmntInfo.gtThreadCount); 36 | 37 | String data = threadSB.toString(); 38 | if (!TextUtils.isEmpty(data)) { 39 | valueView.setText(data); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMGetTopActivityRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.text.TextUtils; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.QPMRAnalysisResult; 8 | import com.zk.qpm.R; 9 | import com.zk.qpm.floatview.QPMFloatViewType; 10 | import com.zk.qpm.manager.QPMRAnalysisManager; 11 | 12 | public class QPMGetTopActivityRenderer extends BaseRenderer { 13 | 14 | @Override 15 | public String type() { 16 | return QPMFloatViewType.TYPE_FLOAT_VIEW_TOP_ACTIVITY; 17 | } 18 | 19 | @Override 20 | protected int getLayoutId() { 21 | return R.layout.jm_gt_item_floatview_keyvalue; 22 | } 23 | 24 | @Override 25 | protected void renderer(View mView) { 26 | TextView keyView = mView.findViewById(R.id.tv_key); 27 | TextView valueView = mView.findViewById(R.id.tv_value); 28 | keyView.setText(R.string.jm_gt_floatview_topactivity); 29 | QPMRAnalysisResult analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 30 | String data = analysisResult.activityStackInfos.topActivityName; 31 | if (!TextUtils.isEmpty(data)) { 32 | valueView.setText(data); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMTemplateBigTextRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.os.Build; 4 | import android.text.Html; 5 | import android.text.SpannableString; 6 | import android.text.Spanned; 7 | import android.text.TextUtils; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | 11 | import com.zk.qpm.R; 12 | import com.zk.qpm.floatview.QPMFloatViewType; 13 | 14 | import java.util.Map; 15 | 16 | public class QPMTemplateBigTextRenderer extends BaseTemplateRenderer { 17 | 18 | public static final String PARAM_BIG_TEXT = "param_big_text"; 19 | 20 | public QPMTemplateBigTextRenderer(Map mParam) { 21 | super(mParam); 22 | } 23 | 24 | @Override 25 | public String type() { 26 | return QPMFloatViewType.TYPE_FLOAT_VIEW_TEMPLATE_BIG_TEXT; 27 | } 28 | 29 | @Override 30 | protected int getLayoutId() { 31 | return R.layout.jm_gt_item_floatview_template_bigtext; 32 | } 33 | 34 | @Override 35 | protected void renderer(View mView, Map mParam) { 36 | TextView valueView = mView.findViewById(R.id.tv_value); 37 | Object o = mParam.get(PARAM_BIG_TEXT); 38 | if (o == null) { 39 | return; 40 | } 41 | String content = o.toString(); 42 | if (!TextUtils.isEmpty(content)) { 43 | valueView.setText(formatContent(content)); 44 | } 45 | } 46 | 47 | private Spanned formatContent(String content) { 48 | try { 49 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 50 | return Html.fromHtml(content, Html.FROM_HTML_MODE_COMPACT); 51 | } else { 52 | return Html.fromHtml(content); 53 | } 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | return new SpannableString(content); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMTemplateCustomRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import com.zk.qpm.floatview.QPMFloatViewType; 4 | 5 | import java.util.Map; 6 | 7 | public abstract class QPMTemplateCustomRenderer extends BaseTemplateRenderer { 8 | 9 | public QPMTemplateCustomRenderer(Map mParam) { 10 | super(mParam); 11 | } 12 | 13 | @Override 14 | public String type() { 15 | return QPMFloatViewType.TYPE_FLOAT_VIEW_TEMPLATE_CUSTOM; 16 | } 17 | 18 | public Map getParam() { 19 | return mParam; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMTemplateKeyPicRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.view.View; 4 | import android.widget.ImageView; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.R; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.manager.QPMManager; 10 | import com.zk.qpm.utils.ImageLoadUtil; 11 | 12 | import java.util.Map; 13 | 14 | public class QPMTemplateKeyPicRenderer extends BaseTemplateRenderer { 15 | 16 | public static final String PARAM_KEY = "param_key"; 17 | public static final String PARAM_PIC_ID = "param_pic_id"; 18 | 19 | public QPMTemplateKeyPicRenderer(Map mParam) { 20 | super(mParam); 21 | } 22 | 23 | @Override 24 | public String type() { 25 | return QPMFloatViewType.TYPE_FLOAT_VIEW_TEMPLATE_KEY_PIC; 26 | } 27 | 28 | @Override 29 | protected int getLayoutId() { 30 | return R.layout.jm_gt_item_floatview_template_keypic; 31 | } 32 | 33 | @Override 34 | protected void renderer(View mView, Map mParam) { 35 | TextView keyView = mView.findViewById(R.id.tv_key); 36 | ImageView valueView = mView.findViewById(R.id.iv_value); 37 | 38 | Object key = mParam.get(PARAM_KEY); 39 | Object picId = mParam.get(PARAM_PIC_ID); 40 | 41 | if (key != null) { 42 | keyView.setText(key.toString()); 43 | } 44 | if (picId != null && picId instanceof Integer) { 45 | ImageLoadUtil.load(QPMManager.getInstance().getContext(), valueView, (Integer) picId); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMTemplateKeyValueRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.view.View; 4 | import android.widget.TextView; 5 | 6 | import com.zk.qpm.R; 7 | import com.zk.qpm.floatview.QPMFloatViewType; 8 | 9 | import java.util.Map; 10 | 11 | public class QPMTemplateKeyValueRenderer extends BaseTemplateRenderer { 12 | 13 | public static final String PARAM_KEY = "param_key"; 14 | public static final String PARAM_VALUE = "param_value"; 15 | 16 | public QPMTemplateKeyValueRenderer(Map mParam) { 17 | super(mParam); 18 | } 19 | 20 | @Override 21 | public String type() { 22 | return QPMFloatViewType.TYPE_FLOAT_VIEW_TEMPLATE_KEY_VALUE; 23 | } 24 | 25 | @Override 26 | protected int getLayoutId() { 27 | return R.layout.jm_gt_item_floatview_template_keyvalue; 28 | } 29 | 30 | @Override 31 | protected void renderer(View mView, Map mParam) { 32 | TextView keyView = mView.findViewById(R.id.tv_key); 33 | TextView valueView = mView.findViewById(R.id.tv_value); 34 | 35 | Object key = mParam.get(PARAM_KEY); 36 | Object value = mParam.get(PARAM_VALUE); 37 | if (key != null) { 38 | keyView.setText(key.toString()); 39 | } 40 | if (value != null) { 41 | valueView.setText(value.toString()); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/floatview/renderer/QPMTemplatePicValueRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.floatview.renderer; 2 | 3 | import android.view.View; 4 | import android.widget.ImageView; 5 | import android.widget.TextView; 6 | 7 | import com.zk.qpm.R; 8 | import com.zk.qpm.floatview.QPMFloatViewType; 9 | import com.zk.qpm.manager.QPMManager; 10 | import com.zk.qpm.utils.ImageLoadUtil; 11 | 12 | import java.util.Map; 13 | 14 | public class QPMTemplatePicValueRenderer extends BaseTemplateRenderer { 15 | 16 | public static final String PARAM_PIC_ID = "param_pic_id"; 17 | public static final String PARAM_VALUE = "param_value"; 18 | 19 | public QPMTemplatePicValueRenderer(Map mParam) { 20 | super(mParam); 21 | } 22 | 23 | @Override 24 | public String type() { 25 | return QPMFloatViewType.TYPE_FLOAT_VIEW_TEMPLATE_PIC_VALUE; 26 | } 27 | 28 | @Override 29 | protected int getLayoutId() { 30 | return R.layout.jm_gt_item_floatview_template_picvalue; 31 | } 32 | 33 | @Override 34 | protected void renderer(View mView, Map mParam) { 35 | ImageView keyView = mView.findViewById(R.id.iv_key); 36 | TextView valueView = mView.findViewById(R.id.tv_value); 37 | 38 | Object picId = mParam.get(PARAM_PIC_ID); 39 | Object value = mParam.get(PARAM_VALUE); 40 | 41 | if (picId != null && picId instanceof Integer) { 42 | ImageLoadUtil.load(QPMManager.getInstance().getContext(), keyView, (Integer) picId); 43 | } 44 | if (value != null) { 45 | valueView.setText(value.toString()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/function/ActivityFunction.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.function; 2 | 3 | import android.app.Activity; 4 | import android.app.FragmentManager; 5 | import android.view.View; 6 | import android.view.ViewStub; 7 | 8 | import com.zk.qpm.R; 9 | import com.zk.qpm.dialog.JumpActivityWithParamDialog; 10 | 11 | 12 | public class ActivityFunction extends FourModuleFunction { 13 | 14 | private FragmentManager mFragmentManager; 15 | 16 | public ActivityFunction(Activity mContext) { 17 | super(mContext); 18 | this.mFragmentManager = mContext.getFragmentManager(); 19 | } 20 | 21 | @Override 22 | public int viewStubId() { 23 | return R.id.vs_module; 24 | } 25 | 26 | @Override 27 | public ViewStub.OnInflateListener getCallback() { 28 | return null; 29 | } 30 | 31 | @Override 32 | protected String moduleName() { 33 | return "activity"; 34 | } 35 | 36 | @Override 37 | protected void onItemClick(View view, int position, Item data) { 38 | if (data.xmlInfo.getAttributeMap().containsKey("name")) { 39 | JumpActivityWithParamDialog.showDialog(mFragmentManager, data.xmlInfo.getAttributeMap().get("name")); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/function/IFunction.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.function; 2 | 3 | import android.view.View; 4 | import android.view.ViewStub; 5 | 6 | public interface IFunction { 7 | 8 | int viewStubId(); 9 | 10 | void renderer(View layout); 11 | 12 | ViewStub.OnInflateListener getCallback(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/function/ProviderFunction.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.function; 2 | 3 | import android.app.Activity; 4 | import android.view.View; 5 | import android.view.ViewStub; 6 | 7 | import com.zk.qpm.R; 8 | 9 | 10 | public class ProviderFunction extends FourModuleFunction { 11 | 12 | public ProviderFunction(Activity mContext) { 13 | super(mContext); 14 | } 15 | 16 | @Override 17 | public int viewStubId() { 18 | return R.id.vs_module; 19 | } 20 | 21 | @Override 22 | public ViewStub.OnInflateListener getCallback() { 23 | return null; 24 | } 25 | 26 | @Override 27 | protected String moduleName() { 28 | return "provider"; 29 | } 30 | 31 | @Override 32 | protected void onItemClick(View view, int position, Item data) { 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/function/ReceiverFunction.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.function; 2 | 3 | import android.app.Activity; 4 | import android.view.View; 5 | import android.view.ViewStub; 6 | 7 | import com.zk.qpm.R; 8 | 9 | 10 | public class ReceiverFunction extends FourModuleFunction { 11 | 12 | public ReceiverFunction(Activity mContext) { 13 | super(mContext); 14 | } 15 | 16 | @Override 17 | public int viewStubId() { 18 | return R.id.vs_module; 19 | } 20 | 21 | @Override 22 | public ViewStub.OnInflateListener getCallback() { 23 | return null; 24 | } 25 | 26 | @Override 27 | protected String moduleName() { 28 | return "receiver"; 29 | } 30 | 31 | @Override 32 | protected void onItemClick(View view, int position, Item data) { 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/function/ServiceFunction.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.function; 2 | 3 | import android.app.Activity; 4 | import android.view.View; 5 | import android.view.ViewStub; 6 | 7 | import com.zk.qpm.R; 8 | 9 | 10 | public class ServiceFunction extends FourModuleFunction { 11 | 12 | public ServiceFunction(Activity mContext) { 13 | super(mContext); 14 | } 15 | 16 | @Override 17 | public int viewStubId() { 18 | return R.id.vs_module; 19 | } 20 | 21 | @Override 22 | public ViewStub.OnInflateListener getCallback() { 23 | return null; 24 | } 25 | 26 | @Override 27 | protected String moduleName() { 28 | return "service"; 29 | } 30 | 31 | @Override 32 | protected void onItemClick(View view, int position, Item data) { 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/function/TitleFunction.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.function; 2 | 3 | import android.app.Activity; 4 | import android.view.View; 5 | import android.view.ViewStub; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import com.zk.qpm.R; 10 | 11 | 12 | public class TitleFunction implements IFunction { 13 | 14 | private Activity activity; 15 | private ImageView backView; 16 | private TextView titleView; 17 | private TextView operateView; 18 | private String title; 19 | 20 | public TitleFunction(Activity activity, String title) { 21 | this.activity = activity; 22 | this.title = title; 23 | } 24 | 25 | @Override 26 | public int viewStubId() { 27 | return R.id.vs_title; 28 | } 29 | 30 | @Override 31 | public void renderer(View layout) { 32 | backView = layout.findViewById(R.id.iv_back); 33 | titleView = layout.findViewById(R.id.tv_title); 34 | operateView = layout.findViewById(R.id.tv_operate); 35 | titleView.setText(title); 36 | backView.setOnClickListener(new View.OnClickListener() { 37 | @Override 38 | public void onClick(View v) { 39 | activity.finish(); 40 | } 41 | }); 42 | } 43 | 44 | @Override 45 | public ViewStub.OnInflateListener getCallback() { 46 | return null; 47 | } 48 | 49 | public void initOperateButton(String operateName, View.OnClickListener onClickListener, boolean defaultShow) { 50 | operateView.setText(operateName); 51 | operateView.setOnClickListener(onClickListener); 52 | refreshOperateView(defaultShow); 53 | } 54 | 55 | public void refreshOperateView(boolean show) { 56 | operateView.setVisibility(show ? View.VISIBLE : View.GONE); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/manager/QPMCallBackManager.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.manager; 2 | 3 | 4 | import com.zk.qpm.QPMRAnalysisResult; 5 | import com.zk.qpm.callback.IAnalysisCallback; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class QPMCallBackManager { 10 | 11 | private static QPMCallBackManager instance = null; 12 | 13 | private final ArrayList callBacks = new ArrayList<>(); 14 | 15 | private QPMCallBackManager() { 16 | 17 | } 18 | 19 | public static QPMCallBackManager getInstance() { 20 | if (instance == null) { 21 | synchronized (QPMCallBackManager.class) { 22 | QPMCallBackManager temp = instance; 23 | if (temp == null) { 24 | temp = new QPMCallBackManager(); 25 | instance = temp; 26 | } 27 | } 28 | } 29 | return instance; 30 | } 31 | 32 | public void addCallBack(IAnalysisCallback callBack) { 33 | synchronized (callBacks) { 34 | callBacks.remove(callBack); 35 | callBacks.add(callBack); 36 | } 37 | } 38 | 39 | public void removeCallBack(IAnalysisCallback callBack) { 40 | synchronized (callBacks) { 41 | callBacks.remove(callBack); 42 | } 43 | } 44 | 45 | public void removeAllCallBack() { 46 | synchronized (callBacks) { 47 | callBacks.clear(); 48 | } 49 | } 50 | 51 | public void refreshInfo(@IAnalysisCallback.CallbackType String type, QPMRAnalysisResult analysisResult) { 52 | synchronized (callBacks) { 53 | for (int i = 0; i < callBacks.size(); i++) { 54 | IAnalysisCallback callback = callBacks.get(i); 55 | 56 | if (analysisResult == null) { 57 | analysisResult = QPMRAnalysisManager.getInstance().getJMGTRAnalysisResult(); 58 | } 59 | 60 | callback.refreshInfo(type, analysisResult); 61 | } 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/manager/QPMModeManager.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.manager; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.zk.qpm.utils.PrefsParser; 6 | 7 | import java.util.List; 8 | 9 | 10 | public class QPMModeManager { 11 | 12 | private static final String SP_NAME_MODE = "jmgt_mode"; 13 | private static final String KEY_MODE = "mode"; 14 | 15 | public static final int MODE_SIMPLE = 1; 16 | public static final int MODE_CUSTOM = 2; 17 | 18 | private static volatile QPMModeManager instance; 19 | 20 | private QPMModeManager() { 21 | } 22 | 23 | public static QPMModeManager getInstance() { 24 | if (instance == null) { 25 | synchronized (QPMModeManager.class) { 26 | if (instance == null) { 27 | instance = new QPMModeManager(); 28 | } 29 | } 30 | } 31 | return instance; 32 | } 33 | 34 | public void init() { 35 | List prefs = getPrefItem(); 36 | initMode(prefs, KEY_MODE, MODE_CUSTOM); 37 | } 38 | 39 | private void initMode(List prefs, String key, int defaultValue) { 40 | for (PrefsParser.PrefItem item : prefs) { 41 | if (TextUtils.equals(item.key, key)) { 42 | return; 43 | } 44 | } 45 | PrefsParser.PrefItem item = new PrefsParser.PrefItem(PrefsParser.IPrefTypeDefine.TYPE_INT, key, String.valueOf(defaultValue)); 46 | PrefsParser.writePrefs(QPMManager.getInstance().getContext(), SP_NAME_MODE, item); 47 | prefs.add(item); 48 | } 49 | 50 | public boolean isSimpleMode() { 51 | List prefs = getPrefItem(); 52 | try { 53 | for (PrefsParser.PrefItem item : prefs) { 54 | if (TextUtils.equals(item.key, KEY_MODE)) { 55 | return Integer.parseInt(item.value) == MODE_SIMPLE; 56 | } 57 | } 58 | } catch (Exception e) { 59 | } 60 | return false; 61 | } 62 | 63 | public void writeMode(boolean isSimpleMode) { 64 | PrefsParser.PrefItem item = new PrefsParser.PrefItem(PrefsParser.IPrefTypeDefine.TYPE_INT, 65 | KEY_MODE, String.valueOf(isSimpleMode ? MODE_SIMPLE : MODE_CUSTOM)); 66 | PrefsParser.writePrefs(QPMManager.getInstance().getContext(), SP_NAME_MODE, item); 67 | } 68 | 69 | private List getPrefItem() { 70 | return PrefsParser.getPrefs(QPMManager.getInstance().getContext(), SP_NAME_MODE, PrefsParser.PARSER_SP); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/manager/QPMPluginManager.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.manager; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.zk.qpm.plugin.QPMPluginControler; 6 | import com.zk.qpm.plugin.QPMPluginItem; 7 | 8 | import java.util.LinkedHashSet; 9 | import java.util.Map; 10 | 11 | public class QPMPluginManager { 12 | 13 | private LinkedHashSet pluginList; 14 | private Map piMap; 15 | private static QPMPluginItem[] EMPTY = {}; 16 | private QPMPluginControler mPluginControler; 17 | 18 | 19 | private static QPMPluginManager instance = null; 20 | 21 | private QPMPluginManager() { 22 | } 23 | 24 | public static QPMPluginManager getInstance() { 25 | if (instance == null) { 26 | synchronized (QPMPluginManager.class) { 27 | QPMPluginManager temp = instance; 28 | if (temp == null) { 29 | temp = new QPMPluginManager(); 30 | instance = temp; 31 | } 32 | } 33 | } 34 | return instance; 35 | } 36 | 37 | public QPMPluginItem[] getPlugins() { 38 | return pluginList.toArray(EMPTY); 39 | } 40 | 41 | 42 | public void register(QPMPluginItem item) { 43 | if (null != item.name && item.name.length() > 0) { 44 | pluginList.add(item); 45 | piMap.put(item.name, item); 46 | } 47 | } 48 | 49 | public void addPlugin(QPMPluginItem item) { 50 | synchronized (instance) { 51 | pluginList.add(item); 52 | piMap.put(item.name, item); 53 | } 54 | } 55 | 56 | public void removePlugin(String name) { 57 | synchronized (instance) { 58 | QPMPluginItem item = piMap.remove(name); 59 | if (null != item) { 60 | pluginList.remove(item); 61 | } 62 | } 63 | } 64 | 65 | 66 | public QPMPluginControler getPluginControler() { 67 | if (null == mPluginControler) { 68 | mPluginControler = new QPMPluginControler(); 69 | } 70 | return mPluginControler; 71 | } 72 | 73 | 74 | public void dispatchCommand(String sReceiver, Bundle bundle) { 75 | QPMPluginItem item = piMap.get(sReceiver); 76 | if (item != null) { 77 | // 加入任务队列,由插件自己决定如何执行 78 | item.addTask(bundle); 79 | } 80 | } 81 | 82 | public void dispatchCommandSync(String sReceiver, Bundle bundle) { 83 | QPMPluginItem item = piMap.get(sReceiver); 84 | if (item != null) { 85 | // 加入任务队列,由插件自己决定如何执行 86 | item.doTask(bundle); 87 | } 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/manager/QPMThreadManager.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.manager; 2 | 3 | import android.os.HandlerThread; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | 9 | /** 10 | * 注意:本类不是线程池,不能当做线程池来用 11 | */ 12 | public class QPMThreadManager { 13 | 14 | private static volatile QPMThreadManager instance; 15 | 16 | private Object SYNC_OBJECT = new Object(); 17 | private final List threads = new ArrayList<>(); 18 | 19 | private QPMThreadManager() { 20 | } 21 | 22 | public static QPMThreadManager getInstance() { 23 | if (instance == null) { 24 | synchronized (QPMThreadManager.class) { 25 | if (instance == null) { 26 | instance = new QPMThreadManager(); 27 | } 28 | } 29 | } 30 | return instance; 31 | } 32 | 33 | private void excludeAllDiedThread() { 34 | Iterator iterator = threads.iterator(); 35 | while (iterator.hasNext()) { 36 | Thread eachThread = iterator.next(); 37 | if (!eachThread.isAlive()) { 38 | iterator.remove(); 39 | } 40 | } 41 | } 42 | 43 | private void addThread(Thread thread) { 44 | synchronized (SYNC_OBJECT) { 45 | // 排除已经结束的线程 46 | excludeAllDiedThread(); 47 | threads.add(thread); 48 | } 49 | } 50 | 51 | public int getAllThreadCount() { 52 | synchronized (SYNC_OBJECT) { 53 | // 排除已经结束的线程 54 | excludeAllDiedThread(); 55 | return threads.size(); 56 | } 57 | } 58 | 59 | public void clearAllThread() { 60 | synchronized (SYNC_OBJECT) { 61 | threads.clear(); 62 | } 63 | } 64 | 65 | public Thread createCommonThread() { 66 | Thread thread = new Thread(); 67 | addThread(thread); 68 | return thread; 69 | } 70 | 71 | public Thread createCommonThread(String threadName) { 72 | Thread thread = new Thread(threadName); 73 | addThread(thread); 74 | return thread; 75 | } 76 | 77 | public Thread createCommonThread(Runnable runnable) { 78 | Thread thread = new Thread(runnable); 79 | addThread(thread); 80 | return thread; 81 | } 82 | 83 | public HandlerThread createHandlerThread(String threadName) { 84 | HandlerThread thread = new HandlerThread(threadName); 85 | addThread(thread); 86 | return thread; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/plugin/QPMBaseServiceConnection.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.plugin; 2 | 3 | public class QPMBaseServiceConnection { 4 | 5 | public Class mClass; 6 | private String key; 7 | 8 | public QPMBaseServiceConnection(Class claxx){ 9 | this.mClass = claxx; 10 | } 11 | 12 | public QPMBaseServiceConnection(String key){ 13 | this.key = key; 14 | } 15 | 16 | public String getKey() { 17 | return this.key; 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/plugin/QPMPluginControler.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.plugin; 2 | 3 | import android.content.Intent; 4 | import android.os.IBinder; 5 | 6 | import com.zk.qpm.service.QPMBaseService; 7 | 8 | 9 | public class QPMPluginControler { 10 | protected QPMBaseServiceConnection mServiceConn = new QPMBaseServiceConnection(QPMPluginControler.class); 11 | 12 | /** 13 | * 启动插件服务 14 | * @param service 插件服务 15 | * @return 插件服务对象(即传进去的参数) 16 | */ 17 | public final QPMBaseService startService(QPMBaseService service) { 18 | return QPMPluginService.startService(service); 19 | } 20 | 21 | /** 22 | * 启动插件服务 23 | * @param service 插件服务 24 | * @param intent 传入的intent 25 | * @return 插件服务对象(即传进去的参数) 26 | */ 27 | public final QPMBaseService startService(QPMBaseService service, Intent intent) { 28 | return QPMPluginService.startService(service, intent); 29 | } 30 | 31 | /** 32 | * 停止插件服务,之前要先调用unBindService方法断开服务 33 | * @param service 插件服务 34 | */ 35 | public final void stopService(QPMBaseService service){ 36 | QPMPluginService.stopService(service.getClass()); 37 | } 38 | 39 | /** 40 | * 断开插件服务 41 | * @param claxx 插件服务的类 42 | */ 43 | public final void unBindService(Class claxx) { 44 | QPMPluginService.unBindService(claxx, mServiceConn); 45 | mServiceConn = null; 46 | } 47 | 48 | /** 49 | * 绑定插件服务 50 | * @param claxx 插件服务的类 51 | * @return 绑定接口 52 | */ 53 | public final IBinder bindService(Class claxx) { 54 | return QPMPluginService.bindService(claxx, mServiceConn); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/plugin/QPMPluginTaskExecutor.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.plugin; 2 | 3 | import android.os.Bundle; 4 | 5 | /** 6 | * 每个插件都可以接收从被测应用传递过来的命令(任务), 7 | * 具体命令的实现需要实现该接口,并注册到插件对应的PluginItem类 8 | */ 9 | public interface QPMPluginTaskExecutor { 10 | void execute(Bundle bundle); 11 | } 12 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/service/QPMBaseService.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.service; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.IBinder; 6 | 7 | import com.zk.qpm.QPMException; 8 | import com.zk.qpm.executor.IExecutor; 9 | import com.zk.qpm.manager.QPMSwitchManager; 10 | import com.zk.qpm.plugin.QPMPluginService; 11 | import com.zk.qpm.utils.PrefsParser; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | 17 | public abstract class QPMBaseService { 18 | protected IBinder mBinder; 19 | protected List executors = new ArrayList<>(); 20 | 21 | public synchronized IBinder getBinder(Context context) { 22 | if (this.mBinder == null) { 23 | this.mBinder = onBind(context); 24 | } 25 | 26 | return this.mBinder; 27 | } 28 | 29 | public abstract IBinder onBind(Context context); 30 | 31 | protected void createShowView(Context context) { 32 | for (IExecutor executor : executors) { 33 | executor.createShowView(context); 34 | } 35 | } 36 | 37 | protected void destoryShowView() { 38 | for (IExecutor executor : executors) { 39 | executor.destoryShowView(); 40 | } 41 | } 42 | 43 | public void onCreate(Context context) { 44 | createShowView(context); 45 | } 46 | 47 | public void onStart(Context context, Intent intent) { 48 | } 49 | 50 | public void onDestroy(Context context) { 51 | destoryShowView(); 52 | } 53 | 54 | protected final void stopSelf() { 55 | QPMPluginService.stopService(this); 56 | } 57 | 58 | public final boolean equals(Object o) { 59 | return (o != null) && (getClass() == o.getClass()); 60 | } 61 | 62 | protected void exec() throws QPMException { 63 | List switchs = QPMSwitchManager.getInstance().getSwitchs(); 64 | for (IExecutor executor : executors) { 65 | if (QPMSwitchManager.getInstance().isSwitchOpen(switchs, executor)) { 66 | executor.exec(); 67 | } 68 | } 69 | } 70 | 71 | protected void stopExec() { 72 | for (IExecutor executor : executors) { 73 | executor.stop(); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/service/QPMFPSComponent.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.service; 2 | 3 | import android.content.Context; 4 | import android.os.IBinder; 5 | 6 | import com.zk.qpm.QPMException; 7 | import com.zk.qpm.executor.QPMGetFPSInfoExecutor; 8 | 9 | public class QPMFPSComponent extends QPMBaseService { 10 | 11 | public QPMFPSComponent() { 12 | executors.clear(); 13 | executors.add(new QPMGetFPSInfoExecutor()); 14 | } 15 | 16 | @Override 17 | public void onCreate(Context context) { 18 | super.onCreate(context); 19 | try { 20 | exec(); 21 | } catch (QPMException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | @Override 27 | public void onDestroy(Context context) { 28 | super.onDestroy(context); 29 | stopExec(); 30 | } 31 | 32 | @Override 33 | public IBinder onBind(Context context) { 34 | return null; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/service/QPMFloatViewCustomComponent.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.service; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Handler; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.LinearLayout; 11 | 12 | import com.zk.qpm.QPMRAnalysisResult; 13 | import com.zk.qpm.R; 14 | import com.zk.qpm.activity.QPMMainMenuActivity; 15 | import com.zk.qpm.callback.IAnalysisCallback; 16 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 17 | import com.zk.qpm.manager.QPMFloatViewManager; 18 | import com.zk.qpm.manager.QPMCallBackManager; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * 自定义模式 24 | */ 25 | public class QPMFloatViewCustomComponent extends QPMFloatViewBaseComponent { 26 | 27 | private LinearLayout containerLayout; 28 | @SuppressLint("HandlerLeak") 29 | private Handler mHandler = new Handler(); 30 | 31 | @Override 32 | public void onCreate(final Context context) { 33 | super.onCreate(context); 34 | addCallback(); 35 | } 36 | 37 | private void addCallback() { 38 | QPMCallBackManager.getInstance().addCallBack(new IAnalysisCallback() { 39 | @Override 40 | public void refreshInfo(String type, final QPMRAnalysisResult analysisResult) { 41 | refreshItemViewToFloatView(); 42 | } 43 | }); 44 | } 45 | 46 | private void refreshItemViewToFloatView() { 47 | mHandler.post(new Runnable() { 48 | @Override 49 | public void run() { 50 | QPMFloatViewManager.getInstance().rendererFloatViewBean(); 51 | } 52 | }); 53 | } 54 | 55 | @Override 56 | public void refreshContainerLayout() { 57 | containerLayout.removeAllViews(); 58 | List items = QPMFloatViewManager.getInstance().getItems(); 59 | for (IFloatViewRenderer item : items) { 60 | if (item.isShow()) { 61 | containerLayout.addView(item.getView()); 62 | } 63 | } 64 | } 65 | 66 | @Override 67 | public void onDestroy(Context context) { 68 | super.onDestroy(context); 69 | containerLayout.removeAllViews(); 70 | mHandler.removeCallbacksAndMessages(null); 71 | QPMCallBackManager.getInstance().removeAllCallBack(); 72 | } 73 | 74 | @Override 75 | protected View getLayout(final Context context) { 76 | View view = LayoutInflater.from(context).inflate( 77 | R.layout.jm_gt_layout_float_view, null); 78 | ImageView jmIcon = view.findViewById(R.id.jm_icon); 79 | 80 | jmIcon.setOnClickListener(new View.OnClickListener() { 81 | @Override 82 | public void onClick(View v) { 83 | Intent intent = new Intent(context, QPMMainMenuActivity.class); 84 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 85 | context.startActivity(intent); 86 | } 87 | }); 88 | 89 | containerLayout = view.findViewById(R.id.ll_container); 90 | return view; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/service/QPMFloatViewSimpleComponent.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.service; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Handler; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.widget.LinearLayout; 10 | 11 | import com.zk.qpm.QPMRAnalysisResult; 12 | import com.zk.qpm.R; 13 | import com.zk.qpm.activity.QPMMainMenuActivity; 14 | import com.zk.qpm.callback.IAnalysisCallback; 15 | import com.zk.qpm.floatview.renderer.IFloatViewRenderer; 16 | import com.zk.qpm.manager.QPMFloatViewManager; 17 | import com.zk.qpm.manager.QPMCallBackManager; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * 精简模式 23 | */ 24 | public class QPMFloatViewSimpleComponent extends QPMFloatViewBaseComponent { 25 | 26 | private LinearLayout containerLayout; 27 | @SuppressLint("HandlerLeak") 28 | private Handler mHandler = new Handler(); 29 | 30 | @Override 31 | public void onCreate(final Context context) { 32 | super.onCreate(context); 33 | addCallback(); 34 | } 35 | 36 | private void addCallback() { 37 | QPMCallBackManager.getInstance().addCallBack(new IAnalysisCallback() { 38 | @Override 39 | public void refreshInfo(String type, final QPMRAnalysisResult analysisResult) { 40 | refreshItemViewToFloatView(); 41 | } 42 | }); 43 | } 44 | 45 | private void refreshItemViewToFloatView() { 46 | mHandler.post(new Runnable() { 47 | @Override 48 | public void run() { 49 | QPMFloatViewManager.getInstance().rendererFloatViewBean(); 50 | } 51 | }); 52 | } 53 | 54 | @Override 55 | public void refreshContainerLayout() { 56 | containerLayout.removeAllViews(); 57 | List items = QPMFloatViewManager.getInstance().getItems(); 58 | for (IFloatViewRenderer item : items) { 59 | if (item.isShow()) { 60 | containerLayout.addView(item.getView()); 61 | } 62 | } 63 | } 64 | 65 | @Override 66 | public void onDestroy(Context context) { 67 | super.onDestroy(context); 68 | containerLayout.removeAllViews(); 69 | mHandler.removeCallbacksAndMessages(null); 70 | QPMCallBackManager.getInstance().removeAllCallBack(); 71 | } 72 | 73 | @Override 74 | protected View getLayout(final Context context) { 75 | View view = LayoutInflater.from(context).inflate( 76 | R.layout.jm_gt_layout_float_view_simple, null); 77 | containerLayout = view.findViewById(R.id.ll_container); 78 | view.setOnClickListener(new View.OnClickListener() { 79 | @Override 80 | public void onClick(View v) { 81 | Intent intent = new Intent(context, QPMMainMenuActivity.class); 82 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 83 | context.startActivity(intent); 84 | } 85 | }); 86 | return view; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/utils/ClipboardUtils.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.utils; 2 | 3 | import android.content.ClipData; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.net.Uri; 8 | 9 | import com.blankj.utilcode.util.Utils; 10 | 11 | public class ClipboardUtils { 12 | private ClipboardUtils() { 13 | throw new UnsupportedOperationException("u can't instantiate me..."); 14 | } 15 | 16 | /** 17 | * 复制文本到剪贴板 18 | * 19 | * @param text 文本 20 | */ 21 | public static void copyText(final CharSequence text) { 22 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 23 | //noinspection ConstantConditions 24 | cm.setPrimaryClip(ClipData.newPlainText("text", text)); 25 | } 26 | 27 | /** 28 | * 获取剪贴板的文本 29 | * 30 | * @return 剪贴板的文本 31 | */ 32 | public static CharSequence getText() { 33 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 34 | //noinspection ConstantConditions 35 | ClipData clip = cm.getPrimaryClip(); 36 | if (clip != null && clip.getItemCount() > 0) { 37 | return clip.getItemAt(0).coerceToText(Utils.getApp()); 38 | } 39 | return null; 40 | } 41 | 42 | /** 43 | * 复制uri到剪贴板 44 | * 45 | * @param uri uri 46 | */ 47 | public static void copyUri(final Uri uri) { 48 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 49 | //noinspection ConstantConditions 50 | cm.setPrimaryClip(ClipData.newUri(Utils.getApp().getContentResolver(), "uri", uri)); 51 | } 52 | 53 | /** 54 | * 获取剪贴板的uri 55 | * 56 | * @return 剪贴板的uri 57 | */ 58 | public static Uri getUri() { 59 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 60 | //noinspection ConstantConditions 61 | ClipData clip = cm.getPrimaryClip(); 62 | if (clip != null && clip.getItemCount() > 0) { 63 | return clip.getItemAt(0).getUri(); 64 | } 65 | return null; 66 | } 67 | 68 | /** 69 | * 复制意图到剪贴板 70 | * 71 | * @param intent 意图 72 | */ 73 | public static void copyIntent(final Intent intent) { 74 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 75 | //noinspection ConstantConditions 76 | cm.setPrimaryClip(ClipData.newIntent("intent", intent)); 77 | } 78 | 79 | /** 80 | * 获取剪贴板的意图 81 | * 82 | * @return 剪贴板的意图 83 | */ 84 | public static Intent getIntent() { 85 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 86 | //noinspection ConstantConditions 87 | ClipData clip = cm.getPrimaryClip(); 88 | if (clip != null && clip.getItemCount() > 0) { 89 | return clip.getItemAt(0).getIntent(); 90 | } 91 | return null; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/utils/DecimalFormatUtil.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.utils; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.RoundingMode; 5 | import java.text.DecimalFormat; 6 | 7 | public class DecimalFormatUtil { 8 | 9 | private static final String SCALE_ZERO = "0"; 10 | private static final String SCALE_ONE = "0.#"; 11 | private static final String SCALE_TWO = "0.##"; 12 | private static final String SCALE_THREE = "0.###"; 13 | 14 | public static String setScale(double d, int scale) { 15 | if (scale < 0) { 16 | return String.valueOf(d); 17 | } 18 | String scaleStr = null; 19 | if (scale == 0) { 20 | scaleStr = SCALE_ZERO; 21 | } else if (scale == 1) { 22 | scaleStr = SCALE_ONE; 23 | } else if (scale == 2) { 24 | scaleStr = SCALE_TWO; 25 | } else if (scale == 3) { 26 | scaleStr = SCALE_THREE; 27 | } else { 28 | StringBuilder sb = new StringBuilder(); 29 | sb.append("0."); 30 | for (int i = 0; i < scale; i++) { 31 | sb.append("#"); 32 | } 33 | scaleStr = sb.toString(); 34 | } 35 | 36 | DecimalFormat df = new DecimalFormat(scaleStr); 37 | return df.format(d); 38 | } 39 | 40 | public static String divider(long one, long two, int scale) { 41 | if (one == -1) { 42 | return "-1"; 43 | } 44 | return new BigDecimal(one).divide(new BigDecimal(two), scale, RoundingMode.HALF_UP).toPlainString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/utils/ImageLoadUtil.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.utils; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.widget.ImageView; 6 | 7 | public class ImageLoadUtil { 8 | 9 | public static void load(Context context, ImageView imageView, int imgId) { 10 | if (context == null || imageView == null || imgId <= 0) { 11 | return; 12 | } 13 | 14 | // Picasso.with(context) 15 | // .load(imgId) 16 | // .into(imageView); 17 | 18 | imageView.setImageResource(imgId); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/utils/ManifestParser.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.utils; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * 比较耗时,请在子线程中进行操作 11 | */ 12 | public class ManifestParser { 13 | 14 | private static XMLParser manifestInfo; 15 | 16 | public static synchronized XMLParser parseManifestInfoByRecursion(Context context) { 17 | if (context == null) { 18 | return null; 19 | } 20 | if (manifestInfo != null) { 21 | return manifestInfo; 22 | } 23 | XMLParser manifestInfo = new XMLParser(); 24 | manifestInfo.register("manifest#uses-sdk"); 25 | manifestInfo.register("manifest#instrumentation"); 26 | manifestInfo.register("manifest#uses-permission"); 27 | manifestInfo.register("manifest#supports-screens"); 28 | 29 | manifestInfo.register("manifest#application#uses-library"); 30 | manifestInfo.register("manifest#application#meta-data"); 31 | 32 | manifestInfo.register("manifest#application#activity#intent-filter#data"); 33 | manifestInfo.register("manifest#application#activity#intent-filter#action"); 34 | manifestInfo.register("manifest#application#activity#intent-filter#category"); 35 | 36 | manifestInfo.register("manifest#application#receiver#intent-filter#data"); 37 | manifestInfo.register("manifest#application#receiver#intent-filter#action"); 38 | manifestInfo.register("manifest#application#receiver#intent-filter#category"); 39 | 40 | manifestInfo.register("manifest#application#provider#intent-filter#data"); 41 | manifestInfo.register("manifest#application#provider#intent-filter#action"); 42 | manifestInfo.register("manifest#application#provider#intent-filter#category"); 43 | 44 | manifestInfo.register("manifest#application#service#intent-filter#data"); 45 | manifestInfo.register("manifest#application#service#intent-filter#action"); 46 | manifestInfo.register("manifest#application#service#intent-filter#category"); 47 | try { 48 | XMLParser.parseBinary(context, manifestInfo, context.getApplicationInfo().sourceDir, "AndroidManifest.xml"); 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | ManifestParser.manifestInfo = manifestInfo; 53 | return manifestInfo; 54 | } 55 | 56 | public static synchronized List getModule(Context context, String moduleName) { 57 | List modules = new ArrayList<>(); 58 | if (TextUtils.isEmpty(moduleName)) { 59 | return modules; 60 | } 61 | XMLParser manifest = parseManifestInfoByRecursion(context); 62 | if (!manifest.getSonTagMap().containsKey("application")) { 63 | return modules; 64 | } 65 | List applications = manifest.getSonTagMap().get("application"); 66 | if (applications.size() != 1) { 67 | return modules; 68 | } 69 | XMLParser application = applications.get(0); 70 | if (!application.getSonTagMap().containsKey(moduleName)) { 71 | return modules; 72 | } 73 | modules.addAll(application.getSonTagMap().get(moduleName)); 74 | return modules; 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/java/com/zk/qpm/utils/SystemProperties.java: -------------------------------------------------------------------------------- 1 | package com.zk.qpm.utils; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | public class SystemProperties { 8 | private static final Method getStringProperty = getMethod(getClass("android.os.SystemProperties")); 9 | 10 | private static Class getClass(String name) { 11 | try { 12 | Class cls = Class.forName(name); 13 | if (cls == null) { 14 | throw new ClassNotFoundException(); 15 | } 16 | return cls; 17 | } catch (ClassNotFoundException e) { 18 | try { 19 | return ClassLoader.getSystemClassLoader().loadClass(name); 20 | } catch (ClassNotFoundException e1) { 21 | return null; 22 | } 23 | } 24 | } 25 | 26 | private static Method getMethod(Class clz) { 27 | if (clz == null) return null; 28 | try { 29 | return clz.getMethod("get", String.class); 30 | } catch (Exception e) { 31 | return null; 32 | } 33 | } 34 | 35 | public static String get(String key) { 36 | if (getStringProperty != null) { 37 | try { 38 | Object value = getStringProperty.invoke(null, key); 39 | if (value == null) { 40 | return ""; 41 | } 42 | return trimToEmpty(value.toString()); 43 | } catch (Exception ignored) { 44 | } 45 | } 46 | return ""; 47 | } 48 | 49 | public static String get(String key, String def) { 50 | if (getStringProperty != null) { 51 | try { 52 | String value = (String) getStringProperty.invoke(null, key); 53 | return defaultString(trimToNull(value), def); 54 | } catch (Exception ignored) { 55 | } 56 | } 57 | return def; 58 | } 59 | 60 | private static String defaultString(String str, String defaultStr) { 61 | return str == null ? defaultStr : str; 62 | } 63 | 64 | private static String trimToNull(String str) { 65 | String ts = trim(str); 66 | return TextUtils.isEmpty(ts) ? null : ts; 67 | } 68 | 69 | private static String trimToEmpty(String str) { 70 | return str == null ? "" : str.trim(); 71 | } 72 | 73 | private static String trim(String str) { 74 | return str == null ? null : str.trim(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_activity_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_activity_background.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_back.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_expand.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_expand.PNG -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_fold_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_fold_arrow.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_ic_app_info_package_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_ic_app_info_package_name.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_ic_app_info_top_activity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_ic_app_info_top_activity.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_ic_fps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_ic_fps.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_icon.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_input_cancel.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_input_cancel.9.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_recorder_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_recorder_start.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_recorder_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_recorder_stop.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_switch_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_switch_off.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_switch_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_switch_on.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_unfold_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhuoKeTeam/QPM/1143f5a75d33c4fd847d32520016a9ce59633199/QPM_SDK/src/main/res/drawable-xxhdpi/jm_gt_unfold_arrow.png -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable/jm_gt_selector_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable/jm_gt_selector_switch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable/jm_gt_shape_activity_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable/jm_gt_shape_floatview.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable/jm_gt_shape_fps_green.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/drawable/jm_gt_shape_fps_red.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_activity_basic_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_activity_four_module.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_activity_main_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_activity_manifest_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_activity_network_api.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_activity_pref_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_activity_switch.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /QPM_SDK/src/main/res/layout/jm_gt_dialog_jump_with_param.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 20 | 21 | 29 | 30 | 39 | 40 | 44 | 45 | 51 | 52 | 56 | 57 | 61 | 62 | 71 | 72 | 76 | 77 | 78 | 79 |