├── AndroidManifest.xml ├── README.md ├── java └── com │ └── example │ └── android │ └── autoclick │ ├── AutoService.java │ ├── FloatingManager.java │ ├── FloatingView.java │ └── MainActivity.java └── res ├── drawable-v24 └── ic_launcher_foreground.xml ├── drawable └── ic_launcher_background.xml ├── layout ├── activity_main.xml └── floating_view.xml ├── mipmap-anydpi-v26 ├── ic_launcher.xml └── ic_launcher_round.xml ├── mipmap-hdpi ├── ic_launcher.png └── ic_launcher_round.png ├── mipmap-mdpi ├── ic_launcher.png └── ic_launcher_round.png ├── mipmap-xhdpi ├── ic_launcher.png └── ic_launcher_round.png ├── mipmap-xxhdpi ├── ic_launcher.png └── ic_launcher_round.png ├── mipmap-xxxhdpi ├── ic_launcher.png └── ic_launcher_round.png ├── values ├── colors.xml ├── strings.xml └── styles.xml └── xml └── global_action_bar_service.xml /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoClicker 2 | An auto clicker app made using android studio accessibility service 3 | Upon the pressing of "start" button on the draggable floating window, 4 | the app will "tap" the screen on the user's behalf at the current location of the floating window 5 | -------------------------------------------------------------------------------- /java/com/example/android/autoclick/AutoService.java: -------------------------------------------------------------------------------- 1 | package com.example.android.autoclick; 2 | 3 | import android.accessibilityservice.AccessibilityService; 4 | import android.accessibilityservice.GestureDescription; 5 | import android.content.Intent; 6 | import android.graphics.Path; 7 | import android.os.Handler; 8 | import android.os.HandlerThread; 9 | import android.util.Log; 10 | import android.view.accessibility.AccessibilityEvent; 11 | import android.widget.Toast; 12 | 13 | import androidx.annotation.RequiresApi; 14 | 15 | public class AutoService extends AccessibilityService { 16 | private Handler mHandler; 17 | private int mX; 18 | private int mY; 19 | 20 | 21 | @Override 22 | public void onCreate() { 23 | super.onCreate(); 24 | HandlerThread handlerThread = new HandlerThread("auto-handler"); 25 | handlerThread.start(); 26 | mHandler = new Handler(handlerThread.getLooper()); 27 | } 28 | 29 | @Override 30 | protected void onServiceConnected() { 31 | 32 | } 33 | 34 | @Override 35 | public int onStartCommand(Intent intent, int flags, int startId) { 36 | Log.d("Service","SERVICE STARTED"); 37 | if(intent!=null){ 38 | String action = intent.getStringExtra("action"); 39 | if (action.equals("play")) { 40 | mX = intent.getIntExtra("x", 0); 41 | //Log.d("x_value",Integer.toString(mX)); 42 | mY = intent.getIntExtra("y", 0); 43 | if (mRunnable == null) { 44 | mRunnable = new IntervalRunnable(); 45 | } 46 | //playTap(mX,mY); 47 | //mHandler.postDelayed(mRunnable, 1000); 48 | mHandler.post(mRunnable); 49 | Toast.makeText(getBaseContext(), "Started", Toast.LENGTH_SHORT).show(); 50 | } 51 | else if(action.equals("stop")){ 52 | mHandler.removeCallbacksAndMessages(null); 53 | } 54 | } 55 | return super.onStartCommand(intent, flags, startId); 56 | } 57 | 58 | //@RequiresApi(api = Build.VERSION_CODES.N) 59 | private void playTap(int x, int y) { 60 | //Log.d("TAPPED","STARTED TAPpING"); 61 | Path swipePath = new Path(); 62 | swipePath.moveTo(x, y); 63 | swipePath.lineTo(x, y); 64 | GestureDescription.Builder gestureBuilder = new GestureDescription.Builder(); 65 | gestureBuilder.addStroke(new GestureDescription.StrokeDescription(swipePath, 0, 10)); 66 | //dispatchGesture(gestureBuilder.build(), null, null); 67 | //Log.d("hello","hello?"); 68 | dispatchGesture(gestureBuilder.build(), new GestureResultCallback() { 69 | @Override 70 | public void onCompleted(GestureDescription gestureDescription) { 71 | Log.d("Gesture Completed","Gesture Completed"); 72 | super.onCompleted(gestureDescription); 73 | //mHandler.postDelayed(mRunnable, 1); 74 | mHandler.post(mRunnable); 75 | } 76 | 77 | @Override 78 | public void onCancelled(GestureDescription gestureDescription) { 79 | //Log.d("Gesture Cancelled","Gesture Cancelled"); 80 | super.onCancelled(gestureDescription); 81 | } 82 | }, null); 83 | //Log.d("hi","hi?"); 84 | } 85 | 86 | @Override 87 | public void onAccessibilityEvent(AccessibilityEvent event) { 88 | 89 | } 90 | 91 | 92 | @Override 93 | public void onInterrupt() { 94 | } 95 | 96 | 97 | private IntervalRunnable mRunnable; 98 | 99 | private class IntervalRunnable implements Runnable { 100 | @Override 101 | public void run() { 102 | //Log.d("clicked","click"); 103 | playTap(mX, mY); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /java/com/example/android/autoclick/FloatingManager.java: -------------------------------------------------------------------------------- 1 | package com.example.android.autoclick; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.WindowManager; 6 | 7 | 8 | public class FloatingManager { 9 | private WindowManager mWindowManager; 10 | private static FloatingManager mInstance; 11 | private Context mContext; 12 | 13 | public static FloatingManager getInstance(Context context) { 14 | if (mInstance == null) { 15 | mInstance = new FloatingManager(context); 16 | } 17 | return mInstance; 18 | } 19 | 20 | private FloatingManager(Context context) { 21 | mContext = context; 22 | mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);//获得WindowManager对象 23 | } 24 | 25 | /** 26 | * adds floating view 27 | * 28 | * @param view 29 | * @param params 30 | * @return 31 | */ 32 | protected boolean addView(View view, WindowManager.LayoutParams params) { 33 | try { 34 | mWindowManager.addView(view, params); 35 | return true; 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | return false; 40 | } 41 | 42 | /** 43 | * removes floating view 44 | * 45 | * @param view 46 | * @return 47 | */ 48 | protected boolean removeView(View view) { 49 | try { 50 | mWindowManager.removeView(view); 51 | return true; 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | } 55 | return false; 56 | } 57 | 58 | /** 59 | * 60 | * 61 | * @param view 62 | * @param params 63 | * @return 64 | */ 65 | protected boolean updateView(View view, WindowManager.LayoutParams params) { 66 | try { 67 | mWindowManager.updateViewLayout(view, params); 68 | return true; 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | return false; 73 | } 74 | } -------------------------------------------------------------------------------- /java/com/example/android/autoclick/FloatingView.java: -------------------------------------------------------------------------------- 1 | package com.example.android.autoclick; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.graphics.PixelFormat; 6 | import android.os.Build; 7 | import android.os.IBinder; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | import android.view.WindowManager; 13 | import android.widget.Button; 14 | 15 | import com.example.android.autoclick.R; 16 | 17 | 18 | public class FloatingView extends Service implements View.OnClickListener { 19 | private WindowManager mWindowManager; 20 | private View myFloatingView; 21 | 22 | @Override 23 | public IBinder onBind(Intent intent) { 24 | return null; 25 | } 26 | 27 | 28 | @Override 29 | public void onCreate() { 30 | super.onCreate(); 31 | 32 | 33 | //getting the widget layout from xml using layout inflater 34 | myFloatingView = LayoutInflater.from(this).inflate(R.layout.floating_view, null); 35 | 36 | 37 | int layout_parms; 38 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 39 | 40 | { 41 | layout_parms = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 42 | 43 | } 44 | 45 | else { 46 | 47 | layout_parms = WindowManager.LayoutParams.TYPE_PHONE; 48 | 49 | } 50 | 51 | //setting the layout parameters 52 | final WindowManager.LayoutParams params = new WindowManager.LayoutParams( 53 | WindowManager.LayoutParams.WRAP_CONTENT, 54 | WindowManager.LayoutParams.WRAP_CONTENT, 55 | layout_parms, 56 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 57 | PixelFormat.TRANSLUCENT); 58 | 59 | 60 | //getting windows services and adding the floating view to it 61 | mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); 62 | mWindowManager.addView(myFloatingView, params); 63 | 64 | 65 | 66 | //adding an touchlistener to make drag movement of the floating widget 67 | myFloatingView.findViewById(R.id.thisIsAnID).setOnTouchListener(new View.OnTouchListener() { 68 | private int initialX; 69 | private int initialY; 70 | private float initialTouchX; 71 | private float initialTouchY; 72 | @Override 73 | public boolean onTouch(View v, MotionEvent event) { 74 | Log.d("TOUCH","THIS IS TOUCHED"); 75 | switch (event.getAction()) { 76 | case MotionEvent.ACTION_DOWN: 77 | initialX = params.x; 78 | initialY = params.y; 79 | initialTouchX = event.getRawX(); 80 | initialTouchY = event.getRawY(); 81 | return true; 82 | 83 | case MotionEvent.ACTION_UP: 84 | 85 | return true; 86 | 87 | case MotionEvent.ACTION_MOVE: 88 | //this code is helping the widget to move around the screen with fingers 89 | params.x = initialX + (int) (event.getRawX() - initialTouchX); 90 | params.y = initialY + (int) (event.getRawY() - initialTouchY); 91 | mWindowManager.updateViewLayout(myFloatingView, params); 92 | return true; 93 | } 94 | return false; 95 | } 96 | }); 97 | 98 | Button startButton = (Button) myFloatingView.findViewById(R.id.start); 99 | startButton.setOnClickListener(this); 100 | Button stopButton = (Button) myFloatingView.findViewById(R.id.stop); 101 | stopButton.setOnClickListener(this); 102 | 103 | } 104 | 105 | @Override 106 | public void onDestroy() { 107 | super.onDestroy(); 108 | if (myFloatingView != null) mWindowManager.removeView(myFloatingView); 109 | } 110 | 111 | 112 | @Override 113 | public void onClick(View v) { 114 | //Log.d("onClick","THIS IS CLICKED"); 115 | Intent intent = new Intent(getApplicationContext(), AutoService.class); 116 | switch (v.getId()) { 117 | case R.id.start: 118 | //Log.d("START","THIS IS STARTED"); 119 | int[] location = new int[2]; 120 | myFloatingView.getLocationOnScreen(location); 121 | intent.putExtra("action", "play"); 122 | intent.putExtra("x", location[0] - 1); 123 | intent.putExtra("y", location[1] - 1); 124 | break; 125 | case R.id.stop: 126 | intent.putExtra("action", "stop"); 127 | mWindowManager.removeView(myFloatingView); 128 | Intent appMain = new Intent(getApplicationContext(), MainActivity.class); 129 | 130 | //getApplication().startActivity(appMain); 131 | //requires the FLAG_ACTIVITY_NEW_TASK flag 132 | } 133 | getApplication().startService(intent); 134 | } 135 | 136 | } -------------------------------------------------------------------------------- /java/com/example/android/autoclick/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.android.autoclick; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | import android.provider.Settings; 10 | import android.view.View; 11 | import android.widget.Toast; 12 | 13 | import com.example.android.autoclick.R; 14 | 15 | public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 16 | //FrameLayout mLayout; 17 | private static final int SYSTEM_ALERT_WINDOW_PERMISSION = 2084; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_main); 23 | 24 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) { 25 | askPermission(); 26 | } 27 | findViewById(R.id.startFloat).setOnClickListener(this); 28 | } 29 | 30 | 31 | 32 | private void askPermission() { 33 | Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, 34 | Uri.parse("package:" + getPackageName())); 35 | startActivityForResult(intent, SYSTEM_ALERT_WINDOW_PERMISSION); 36 | } 37 | 38 | 39 | @Override 40 | public void onClick(View v) { 41 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 42 | startService(new Intent(MainActivity.this, FloatingView.class)); 43 | finish(); 44 | } else if (Settings.canDrawOverlays(this)) { 45 | startService(new Intent(MainActivity.this, FloatingView.class)); 46 | finish(); 47 | } else { 48 | askPermission(); 49 | Toast.makeText(this, "You need System Alert Window Permission to do this", Toast.LENGTH_SHORT).show(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 |