└── ViewDebugHelper ├── .gitignore ├── README.md ├── apks └── ViewDebugHelper-2015-10-13.apk ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zanlabs │ │ └── viewdebughelper │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zanlabs │ │ └── viewdebughelper │ │ ├── ActivityHelper.java │ │ ├── FloatWindowView.java │ │ ├── HomeActivity.java │ │ ├── MyWindowManager.java │ │ ├── ViewDebugHelperApplication.java │ │ ├── service │ │ ├── FloatWindowService.java │ │ └── ViewDebugHelperService.java │ │ └── util │ │ ├── AccessibilityServiceHelper.java │ │ └── ClipManagerUtil.java │ └── res │ ├── layout │ ├── activity_home.xml │ ├── float_window_small.xml │ └── view_float_window.xml │ ├── menu │ └── menu_home.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ ├── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── view_debug_helper.xml ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /ViewDebugHelper/.gitignore: -------------------------------------------------------------------------------- 1 | !apks/ 2 | 3 | 4 | .gradle 5 | /local.properties 6 | /.idea/workspace.xml 7 | /.idea/libraries 8 | .DS_Store 9 | /build 10 | /captures 11 | .idea 12 | *.iml 13 | 14 | # Built application files 15 | *.apk 16 | *.ap_ 17 | 18 | # Files for the Dalvik VM 19 | *.dex 20 | 21 | # Java class files 22 | *.class 23 | 24 | # Generated files 25 | bin/ 26 | gen/ 27 | 28 | # Gradle files 29 | .gradle/ 30 | build/ 31 | /*/build/ 32 | /gradle.properties 33 | 34 | # Local configuration file (sdk path, etc) 35 | local.properties 36 | 37 | # Proguard folder generated by Eclipse 38 | proguard/ 39 | 40 | # Log Files 41 | *.log -------------------------------------------------------------------------------- /ViewDebugHelper/README.md: -------------------------------------------------------------------------------- 1 | **PROJECT MOVED** 2 | NEW [ViewDebugHelper](https://github.com/waylife/ViewDebugHelper) 3 | 4 | 5 | #ViewDebugHelper 6 | A tool help you to get the current top running activity. 7 | Support Lollipop(Android 5.0)+. 8 | 9 | #Download link 10 | go to apks folder 11 | 12 | -------------------------------------------------------------------------------- /ViewDebugHelper/apks/ViewDebugHelper-2015-10-13.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylife/DemoCollections/13b59ccfebec48c4fe697508b2fc2926bd58e249/ViewDebugHelper/apks/ViewDebugHelper-2015-10-13.apk -------------------------------------------------------------------------------- /ViewDebugHelper/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.0" 6 | 7 | defaultConfig { 8 | applicationId "com.zanlabs.viewdebughelper" 9 | minSdkVersion 8 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:23.+' 25 | } 26 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Java\SDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/androidTest/java/com/zanlabs/viewdebughelper/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/ActivityHelper.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.pm.ActivityInfo; 7 | import android.content.pm.PackageManager; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Created by rxread on 2015/1/21. 13 | */ 14 | public class ActivityHelper { 15 | 16 | /** 17 | * 慎重使用此函数
18 | * GET_TASK was deprecated in API level 21. No longer enforced 19 | */ 20 | public static boolean isApplicationBroughtToBackground(final Context context) { 21 | try { 22 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 23 | List tasks = am.getRunningTasks(1); 24 | if (!tasks.isEmpty()) { 25 | ComponentName topActivity = tasks.get(0).topActivity; 26 | if (!topActivity.getPackageName().equals(context.getPackageName())) { 27 | return true; 28 | } 29 | } 30 | }catch (Exception ex){ 31 | ex.printStackTrace(); 32 | } 33 | return false; 34 | } 35 | 36 | /** 37 | * 是否在前台运行 38 | * 慎重使用此函数
39 | * GET_TASK was deprecated in API level 21. No longer enforced 40 | * @return 41 | */ 42 | public static boolean isAppOnForeground(Context context) { 43 | return !isApplicationBroughtToBackground(context); 44 | } 45 | 46 | /** 47 | * 慎重使用此函数
48 | * GET_TASK was deprecated in API level 21. No longer enforced 49 | */ 50 | public static String currentAppPackageNameOnForeground(final Context context) { 51 | try { 52 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 53 | List tasks = am.getRunningTasks(1); 54 | if (!tasks.isEmpty()) { 55 | ComponentName topActivity = tasks.get(0).topActivity; 56 | return topActivity.getPackageName(); 57 | } 58 | }catch (Exception ex){ 59 | ex.printStackTrace(); 60 | } 61 | return ""; 62 | } 63 | 64 | 65 | /** 66 | * 慎重使用此函数
67 | * GET_TASK was deprecated in API level 21. No longer enforced 68 | */ 69 | public static String getTopActivity(final Context context) { 70 | try { 71 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 72 | List tasks = am.getRunningTasks(1); 73 | if (!tasks.isEmpty()) { 74 | ComponentName topActivity = tasks.get(0).topActivity; 75 | return topActivity.getClassName(); 76 | } 77 | }catch (Exception ex){ 78 | ex.printStackTrace(); 79 | } 80 | return ""; 81 | } 82 | 83 | public static ActivityInfo tryGetActivity(Context context,ComponentName componentName) { 84 | try { 85 | return context.getPackageManager().getActivityInfo(componentName, 0); 86 | } catch (PackageManager.NameNotFoundException e) { 87 | return null; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/FloatWindowView.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import android.content.Context; 6 | import android.view.LayoutInflater; 7 | import android.view.MotionEvent; 8 | import android.view.View; 9 | import android.view.WindowManager; 10 | import android.widget.LinearLayout; 11 | import android.widget.TextView; 12 | 13 | public class FloatWindowView extends LinearLayout { 14 | 15 | /** 16 | * 记录小悬浮窗的宽度 17 | */ 18 | public static int viewWidth; 19 | 20 | /** 21 | * 记录小悬浮窗的高度 22 | */ 23 | public static int viewHeight; 24 | 25 | /** 26 | * 记录系统状态栏的高度 27 | */ 28 | private static int statusBarHeight; 29 | 30 | /** 31 | * 用于更新小悬浮窗的位置 32 | */ 33 | private WindowManager windowManager; 34 | 35 | /** 36 | * 小悬浮窗的参数 37 | */ 38 | private WindowManager.LayoutParams mParams; 39 | 40 | /** 41 | * 记录当前手指位置在屏幕上的横坐标值 42 | */ 43 | private float xInScreen; 44 | 45 | /** 46 | * 记录当前手指位置在屏幕上的纵坐标值 47 | */ 48 | private float yInScreen; 49 | 50 | /** 51 | * 记录手指按下时在屏幕上的横坐标的值 52 | */ 53 | private float xDownInScreen; 54 | 55 | /** 56 | * 记录手指按下时在屏幕上的纵坐标的值 57 | */ 58 | private float yDownInScreen; 59 | 60 | /** 61 | * 记录手指按下时在小悬浮窗的View上的横坐标的值 62 | */ 63 | private float xInView; 64 | 65 | /** 66 | * 记录手指按下时在小悬浮窗的View上的纵坐标的值 67 | */ 68 | private float yInView; 69 | 70 | public FloatWindowView(Context context) { 71 | super(context); 72 | windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 73 | LayoutInflater.from(context).inflate(R.layout.float_window_small, this); 74 | View view = findViewById(R.id.small_window_layout); 75 | viewWidth = view.getLayoutParams().width; 76 | viewHeight = view.getLayoutParams().height; 77 | } 78 | 79 | @Override 80 | public boolean onTouchEvent(MotionEvent event) { 81 | switch (event.getAction()) { 82 | case MotionEvent.ACTION_DOWN: 83 | // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度 84 | xInView = event.getX(); 85 | yInView = event.getY(); 86 | xDownInScreen = event.getRawX(); 87 | yDownInScreen = event.getRawY() - getStatusBarHeight(); 88 | xInScreen = event.getRawX(); 89 | yInScreen = event.getRawY() - getStatusBarHeight(); 90 | break; 91 | case MotionEvent.ACTION_MOVE: 92 | xInScreen = event.getRawX(); 93 | yInScreen = event.getRawY() - getStatusBarHeight(); 94 | // 手指移动的时候更新小悬浮窗的位置 95 | updateViewPosition(); 96 | break; 97 | case MotionEvent.ACTION_UP: 98 | // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 99 | if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) { 100 | MyWindowManager.updateCurrentTopActvity(getContext()); 101 | } 102 | break; 103 | default: 104 | break; 105 | } 106 | return true; 107 | } 108 | 109 | /** 110 | * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。 111 | * 112 | * @param params 113 | * 小悬浮窗的参数 114 | */ 115 | public void setParams(WindowManager.LayoutParams params) { 116 | mParams = params; 117 | } 118 | 119 | /** 120 | * 更新小悬浮窗在屏幕中的位置。 121 | */ 122 | private void updateViewPosition() { 123 | mParams.x = (int) (xInScreen - xInView); 124 | mParams.y = (int) (yInScreen - yInView); 125 | windowManager.updateViewLayout(this, mParams); 126 | } 127 | 128 | 129 | /** 130 | * 用于获取状态栏的高度。 131 | * 132 | * @return 返回状态栏高度的像素值。 133 | */ 134 | private int getStatusBarHeight() { 135 | if (statusBarHeight == 0) { 136 | try { 137 | Class c = Class.forName("com.android.internal.R$dimen"); 138 | Object o = c.newInstance(); 139 | Field field = c.getField("status_bar_height"); 140 | int x = (Integer) field.get(o); 141 | statusBarHeight = getResources().getDimensionPixelSize(x); 142 | } catch (Exception e) { 143 | e.printStackTrace(); 144 | } 145 | } 146 | return statusBarHeight; 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/HomeActivity.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper; 2 | 3 | import android.os.Build; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.Toast; 11 | 12 | import com.zanlabs.viewdebughelper.service.FloatWindowService; 13 | import com.zanlabs.viewdebughelper.util.AccessibilityServiceHelper; 14 | 15 | public class HomeActivity extends AppCompatActivity { 16 | 17 | Button mActionBtn; 18 | Button mActiveServiceBtn; 19 | boolean mIsServiceRunning; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_home); 25 | mActionBtn= (Button) findViewById(R.id.home_action_btn); 26 | mActiveServiceBtn= (Button) findViewById(R.id.home_activte_service_btn); 27 | mActionBtn.setOnClickListener(new View.OnClickListener() { 28 | @Override 29 | public void onClick(View v) { 30 | setServiceState(); 31 | if(mIsServiceRunning){ 32 | FloatWindowService.stop(HomeActivity.this); 33 | }else{ 34 | FloatWindowService.start(HomeActivity.this); 35 | } 36 | Toast.makeText(HomeActivity.this,mIsServiceRunning?"服务已停止":"服务已启动",Toast.LENGTH_SHORT).show(); 37 | } 38 | }); 39 | 40 | mActiveServiceBtn.setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | AccessibilityServiceHelper.goServiceSettings(HomeActivity.this); 44 | } 45 | }); 46 | checkApiGreaterThanLollipop(); 47 | } 48 | 49 | private void setServiceState(){ 50 | mIsServiceRunning=FloatWindowService.isRunning(); 51 | if(mActionBtn!=null){ 52 | mActionBtn.setText(mIsServiceRunning?"停止服务":"启动服务"); 53 | } 54 | } 55 | 56 | @Override 57 | protected void onResume() { 58 | super.onResume(); 59 | setServiceState(); 60 | } 61 | 62 | public void checkApiGreaterThanLollipop(){ 63 | if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){ 64 | mActiveServiceBtn.setVisibility(View.VISIBLE); 65 | Toast.makeText(this,"Android 5.0(LOLLIPOP)之后需要开启ViewDebugHelper服务才能获取当前activity信息",Toast.LENGTH_SHORT).show(); 66 | }else{ 67 | mActiveServiceBtn.setVisibility(View.GONE); 68 | } 69 | } 70 | 71 | @Override 72 | public boolean onCreateOptionsMenu(Menu menu) { 73 | // Inflate the menu; this adds items to the action bar if it is present. 74 | getMenuInflater().inflate(R.menu.menu_home, menu); 75 | return true; 76 | } 77 | 78 | @Override 79 | public boolean onOptionsItemSelected(MenuItem item) { 80 | // Handle action bar item clicks here. The action bar will 81 | // automatically handle clicks on the Home/Up button, so long 82 | // as you specify a parent activity in AndroidManifest.xml. 83 | int id = item.getItemId(); 84 | 85 | //noinspection SimplifiableIfStatement 86 | if (id == R.id.action_settings) { 87 | return true; 88 | } 89 | 90 | return super.onOptionsItemSelected(item); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/MyWindowManager.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.graphics.PixelFormat; 6 | import android.net.Uri; 7 | import android.os.Build; 8 | import android.provider.Settings; 9 | import android.view.Gravity; 10 | import android.view.WindowManager; 11 | import android.view.WindowManager.LayoutParams; 12 | import android.widget.TextView; 13 | import android.widget.Toast; 14 | 15 | import com.zanlabs.viewdebughelper.service.ViewDebugHelperService; 16 | import com.zanlabs.viewdebughelper.util.AccessibilityServiceHelper; 17 | 18 | public class MyWindowManager { 19 | 20 | private static FloatWindowView mFloatWindow; 21 | 22 | 23 | /** 24 | * 小悬浮窗View的参数 25 | */ 26 | private static LayoutParams mFloatWindowParams; 27 | 28 | 29 | /** 30 | * 用于控制在屏幕上添加或移除悬浮窗 31 | */ 32 | private static WindowManager mWindowManager; 33 | 34 | /** 35 | * 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。 36 | * 37 | * @param context 必须为应用程序的Context. 38 | */ 39 | public static void createFloatWindow(Context context) { 40 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 41 | if (!Settings.canDrawOverlays(context)) { 42 | Toast.makeText(context, "Permit drawing over other apps permission!", Toast.LENGTH_LONG).show(); 43 | Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, 44 | Uri.parse("package:" + context.getPackageName())); 45 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 46 | context.startActivity(intent); 47 | return; 48 | } 49 | } 50 | 51 | WindowManager windowManager = getWindowManager(context); 52 | int screenWidth = windowManager.getDefaultDisplay().getWidth(); 53 | int screenHeight = windowManager.getDefaultDisplay().getHeight(); 54 | if (mFloatWindow == null) { 55 | mFloatWindow = new FloatWindowView(context); 56 | if (mFloatWindowParams == null) { 57 | mFloatWindowParams = new LayoutParams(); 58 | mFloatWindowParams.type = LayoutParams.TYPE_PHONE; 59 | mFloatWindowParams.format = PixelFormat.RGBA_8888; 60 | mFloatWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL 61 | | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_KEEP_SCREEN_ON | LayoutParams.FLAG_FULLSCREEN; 62 | mFloatWindowParams.gravity = Gravity.LEFT | Gravity.TOP; 63 | mFloatWindowParams.width = FloatWindowView.viewWidth; 64 | mFloatWindowParams.height = FloatWindowView.viewHeight; 65 | mFloatWindowParams.x = screenWidth; 66 | mFloatWindowParams.y = screenHeight / 2; 67 | } 68 | mFloatWindow.setParams(mFloatWindowParams); 69 | windowManager.addView(mFloatWindow, mFloatWindowParams); 70 | } 71 | } 72 | 73 | /** 74 | * 将小悬浮窗从屏幕上移除。 75 | * 76 | * @param context 必须为应用程序的Context. 77 | */ 78 | public static void removeFloatWindow(Context context) { 79 | if (mFloatWindow != null) { 80 | WindowManager windowManager = getWindowManager(context); 81 | windowManager.removeView(mFloatWindow); 82 | mFloatWindow = null; 83 | } 84 | } 85 | 86 | 87 | public static void updateCurrentTopActvity(Context context) { 88 | if (mFloatWindow != null) { 89 | TextView percentView = (TextView) mFloatWindow.findViewById(R.id.float_textview); 90 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 91 | if (AccessibilityServiceHelper.isAccessibilitySettingsOn(context, ViewDebugHelperApplication.getInstance().getCurrentPackName() + "/" + ViewDebugHelperService.class.getName())) { 92 | percentView.setText(ViewDebugHelperApplication.getInstance().getLastTopActivityName()); 93 | } else { 94 | percentView.setText("服务未开,数据不一定准确\n" + ActivityHelper.getTopActivity(context)); 95 | } 96 | } else { 97 | percentView.setText(ActivityHelper.getTopActivity(context)); 98 | } 99 | } 100 | } 101 | 102 | /** 103 | * 是否有悬浮窗(包括小悬浮窗和大悬浮窗)显示在屏幕上。 104 | * 105 | * @return 有悬浮窗显示在桌面上返回true,没有的话返回false。 106 | */ 107 | public static boolean isWindowShowing() { 108 | return mFloatWindow != null; 109 | } 110 | 111 | /** 112 | * 如果WindowManager还未创建,则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。 113 | * 114 | * @param context 必须为应用程序的Context. 115 | * @return WindowManager的实例,用于控制在屏幕上添加或移除悬浮窗。 116 | */ 117 | private static WindowManager getWindowManager(Context context) { 118 | if (mWindowManager == null) { 119 | mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 120 | } 121 | return mWindowManager; 122 | } 123 | 124 | 125 | } 126 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/ViewDebugHelperApplication.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper; 2 | 3 | import android.app.Application; 4 | 5 | public class ViewDebugHelperApplication extends Application { 6 | 7 | private static ViewDebugHelperApplication mInstance = null; 8 | 9 | private String mLastTopActivityName = ""; 10 | 11 | private String mCurrentPackName=""; 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | mInstance=this; 17 | mCurrentPackName=getPackageName(); 18 | } 19 | 20 | @Override 21 | public void onTerminate() { 22 | super.onTerminate(); 23 | } 24 | 25 | public static ViewDebugHelperApplication getInstance() { 26 | return mInstance; 27 | } 28 | 29 | 30 | public String getLastTopActivityName() { 31 | return mLastTopActivityName; 32 | } 33 | 34 | public void setLastTopActivityName(String lastTopActivityName) { 35 | this.mLastTopActivityName = lastTopActivityName; 36 | } 37 | 38 | public String getCurrentPackName() { 39 | return mCurrentPackName; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/service/FloatWindowService.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper.service; 2 | 3 | import android.app.Service; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Handler; 7 | import android.os.IBinder; 8 | 9 | import com.zanlabs.viewdebughelper.MyWindowManager; 10 | 11 | import java.util.Timer; 12 | import java.util.TimerTask; 13 | 14 | public class FloatWindowService extends Service { 15 | 16 | public static void start(Context context){ 17 | Intent intent=new Intent(context,FloatWindowService.class); 18 | context.startService(intent); 19 | } 20 | 21 | public static void stop(Context context){ 22 | Intent intent=new Intent(context,FloatWindowService.class); 23 | context.stopService(intent); 24 | } 25 | 26 | private static boolean isRunning=false; 27 | 28 | public static boolean isRunning(){ 29 | return isRunning; 30 | } 31 | /** 32 | * 用于在线程中创建或移除悬浮窗。 33 | */ 34 | private Handler handler = new Handler(); 35 | 36 | /** 37 | * 定时器,定时进行检测当前应该创建还是移除悬浮窗。 38 | */ 39 | private Timer timer; 40 | 41 | public FloatWindowService() { 42 | } 43 | 44 | @Override 45 | public void onCreate() { 46 | super.onCreate(); 47 | isRunning=true; 48 | // 开启定时器,每隔0.5秒刷新一次 49 | if (timer == null) { 50 | timer = new Timer(); 51 | timer.scheduleAtFixedRate(new RefreshTask(), 0, 500); 52 | } 53 | } 54 | 55 | 56 | 57 | @Override 58 | public void onDestroy() { 59 | super.onDestroy(); 60 | MyWindowManager.removeFloatWindow(getApplicationContext()); 61 | isRunning=false; 62 | } 63 | 64 | @Override 65 | public IBinder onBind(Intent intent) { 66 | throw new UnsupportedOperationException("Not support"); 67 | } 68 | 69 | class RefreshTask extends TimerTask { 70 | 71 | @Override 72 | public void run() { 73 | if(!isRunning) 74 | return; 75 | // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。 76 | if (!MyWindowManager.isWindowShowing()) { 77 | handler.post(new Runnable() { 78 | @Override 79 | public void run() { 80 | if(!isRunning) 81 | return; 82 | MyWindowManager.createFloatWindow(getApplicationContext()); 83 | } 84 | }); 85 | }else{ 86 | handler.post(new Runnable() { 87 | @Override 88 | public void run() { 89 | MyWindowManager.updateCurrentTopActvity(getApplicationContext()); 90 | } 91 | }); 92 | } 93 | } 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/service/ViewDebugHelperService.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper.service; 2 | 3 | import android.accessibilityservice.AccessibilityService; 4 | import android.accessibilityservice.AccessibilityServiceInfo; 5 | import android.annotation.TargetApi; 6 | import android.content.ComponentName; 7 | import android.content.pm.ActivityInfo; 8 | import android.os.Build; 9 | import android.util.Log; 10 | import android.view.accessibility.AccessibilityEvent; 11 | 12 | import com.zanlabs.viewdebughelper.ActivityHelper; 13 | import com.zanlabs.viewdebughelper.ViewDebugHelperApplication; 14 | 15 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 16 | public class ViewDebugHelperService extends AccessibilityService { 17 | 18 | public static void log(String message) { 19 | Log.i("ViewDebugHelperService", message); 20 | } 21 | 22 | /** 23 | * {@inheritDoc} 24 | */ 25 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 26 | @Override 27 | public void onServiceConnected() { 28 | super.onServiceConnected(); 29 | AccessibilityServiceInfo accessibilityServiceInfo = getServiceInfo(); 30 | if (accessibilityServiceInfo == null) 31 | accessibilityServiceInfo = new AccessibilityServiceInfo(); 32 | accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; 33 | accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; 34 | accessibilityServiceInfo.notificationTimeout = 10; 35 | if (Build.VERSION.SDK_INT >= 16) { 36 | accessibilityServiceInfo.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 37 | } 38 | setServiceInfo(accessibilityServiceInfo); 39 | } 40 | 41 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 42 | @Override 43 | public void onAccessibilityEvent(AccessibilityEvent event) { 44 | if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { 45 | ComponentName componentName = new ComponentName(event.getPackageName().toString(), event.getClassName().toString()); 46 | ActivityInfo activityInfo = ActivityHelper.tryGetActivity(this, componentName); 47 | boolean isActivity = activityInfo != null; 48 | if (isActivity) { 49 | log("CurrentActivity" + componentName.flattenToString()); 50 | ViewDebugHelperApplication.getInstance().setLastTopActivityName(componentName.flattenToString()); 51 | } 52 | } 53 | } 54 | 55 | 56 | @Override 57 | public void onInterrupt() { 58 | log("onInterrupt"); 59 | } 60 | 61 | 62 | @Override 63 | public void onDestroy() { 64 | super.onDestroy(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/util/AccessibilityServiceHelper.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper.util; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.provider.Settings; 6 | import android.provider.Settings.SettingNotFoundException; 7 | import android.text.TextUtils; 8 | 9 | public class AccessibilityServiceHelper { 10 | 11 | public static void goServiceSettings(Context context) { 12 | context.startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)); 13 | } 14 | 15 | // To check if service is enabled 16 | // String servicename = context.getPackageName() + "/" + xxx.class.getName(); 17 | public static boolean isAccessibilitySettingsOn(Context context,String serviceName) { 18 | int accessibilityEnabled = 0; 19 | boolean accessibilityFound = false; 20 | try { 21 | accessibilityEnabled = Settings.Secure.getInt(context.getApplicationContext().getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED); 22 | } catch (SettingNotFoundException e) { 23 | } 24 | TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':'); 25 | if (accessibilityEnabled == 1) { 26 | String settingValue = Settings.Secure.getString(context.getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 27 | if (settingValue != null) { 28 | TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 29 | splitter.setString(settingValue); 30 | while (splitter.hasNext()) { 31 | String accessabilityService = splitter.next(); 32 | if (accessabilityService.equalsIgnoreCase(serviceName)) { 33 | return true; 34 | } 35 | } 36 | } 37 | } else { 38 | // Log.v(TAG, "***ACCESSIBILIY IS DISABLED***"); 39 | } 40 | 41 | return accessibilityFound; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/java/com/zanlabs/viewdebughelper/util/ClipManagerUtil.java: -------------------------------------------------------------------------------- 1 | package com.zanlabs.viewdebughelper.util; 2 | 3 | import android.content.Context; 4 | import android.text.ClipboardManager; 5 | 6 | /** 7 | * 剪切板类
8 | * 9 | * @author rxread 10 | */ 11 | public class ClipManagerUtil { 12 | /** 13 | * copy plain text to clip board
14 | * 复制文本到剪切板
15 | */ 16 | public static void copyToClipBoard(Context context, CharSequence text) { 17 | ClipboardManager clipboardManager = (ClipboardManager) context 18 | .getSystemService(Context.CLIPBOARD_SERVICE); 19 | clipboardManager.setText(text); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ViewDebugHelper/app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 |