android Bluetooth Control PC End Code Sharing

  • 2021-09-20 21:32:53
  • OfStack

Introduction

On Android, instructions are sent to PC via Bluetooth, and java program receives instructions and executes corresponding actions. The instruction format is standardized, and the java program at PC is operated by robot library

Code

Control class remotePC. java


import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;

public class remotePC {
  //保存当前鼠标指针的坐标(px,py)
  private static int px;
  private static int py;
  //最大延迟时间:1秒
  public static final int MAX_DELAY = 1000;
  //最小间隔时间:1毫秒
  public static final int SAMPLE_TIME_DIV = 1;
  //魔法数字,用于设置默认的事件delay时间间隔
  private final double magicX = 1.0;
  //视觉延迟:默认100ms
  private final int VISIBAL_MOVEMENT = 100;
  //PC屏幕尺寸
  private int screenWidth;
  private int screenHeight;
  //手机屏幕尺寸
  private int mobileWidth;
  private int mobileHeight;
  //手机电脑尺寸转换的比例
  private double widScale;
  private double heiScale;
  //用于控制的robot类
  private Robot robot;

  //默认构造函数
  public remotePC() throws AWTException{
    this(1366, 768);
  }
  //构造函数,指定手机屏幕尺寸
  public remotePC(int mobileWidth, int mobileHeight) throws AWTException{
    robot = new Robot();
    robot.setAutoDelay((int)magicX);
    setScreenSize();
    this.mobileHeight = mobileHeight;
    this.mobileWidth = mobileWidth;
    setScale();
  }
  public void moveToCenter(){
    this.move(screenWidth/2, screenHeight/2, 1);
  }
  //[鼠标光标移动]
  //dt:间隔时间,时间长短对应速度
  //dx,dy:手机上移动的相对横纵位移,自动转换为pc上应该移动的尺寸
  public void move(int dx, int dy, int dt){
    double deltaX = (1.0*dx/widScale);
    double deltaY = (1.0*dy/heiScale);
    int dxpms = (int)deltaX/dt;
    int dypms = (int)deltaY/dt;
    for(int i=0; i<dt; i++){
      px += dxpms;
      py += dypms;
      if(px <= 0){
        px = 0;
      }else if(px >= screenWidth){
        px = screenWidth;
      }
      if(py <= 0){
        py = 0;
      }else if(py >= screenHeight){
        py = screenHeight;
      }
      robot.mouseMove((int)px, (int)py);
    }
  }
  //[按下鼠标左键]
  public void pressMouseL(){
    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
  }
  //[释放鼠标左键]
  public void releaseMouseL(){
    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
  }
  //[点击1下鼠标左键]
  public void clickMouseL(){
    this.pressMouseL();
    this.releaseMouseL();
  }
  //[按下鼠标右键]
  public void pressMouseR(){
    robot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
  }
  //[释放鼠标右键]
  public void releaseMouseR(){
    robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
  }
  //[点击鼠标右键]
  public void clickMouseR(){
    this.pressMouseR();
    this.releaseMouseR();
  }
  //[按下滚轮]
  public void pressWheel(){
    robot.mousePress(InputEvent.BUTTON2_DOWN_MASK);
  }
  //[释放滚轮]
  public void releaseWheel(){
    robot.mouseRelease(InputEvent.BUTTON2_DOWN_MASK);
  }
  //[滚轮往下移动]:step是移动步数,相对于滚轮的1格
  public void wheelDown(int step){
    for(int i=0; i<step; i++){
      robot.mouseWheel(1);
    }
  }
  //[滚轮往上移动]:step是移动步数,相对于滚轮的1格
  public void wheelUp(int step){
    for(int i=0; i<step; i++){
      robot.mouseWheel(-1);
    }
  }
  //[敲1格字符:A-Z]:c为字母的char类型字符,必须是大写的
  public void printChar(char c){
    if(c <= 'Z' && c >= 'A'){
      robot.keyPress((int)c);
      robot.keyRelease((int)c);
    }
  }
  //[敲1个空格]
  public void printSpace(){
    robot.keyPress(KeyEvent.VK_SPACE);
    robot.keyRelease(KeyEvent.VK_SPACE);
  }
  //[放大]相当于ctrl+滚轮上移
  public void zoomIn(int step){
    robot.keyPress(KeyEvent.VK_CONTROL);
    for(int i=0; i<step; i++)
      robot.mouseWheel(-1);
    robot.keyRelease(KeyEvent.VK_CONTROL);
  }
  //[缩小]相当于ctrl+滚轮下移
  public void zoomOut(int step){
    robot.keyPress(KeyEvent.VK_CONTROL);
    for(int i=0; i<step; i++)
      robot.mouseWheel(1);
    robot.keyRelease(KeyEvent.VK_CONTROL);
  }
  //[显示app切换栏]相当于alt+tab,并且alt不放开,1旦调用该函数后,需要手动调用closeSwitchApps()来释放alt按键
  public void showSwitchApps(){
    robot.keyPress(KeyEvent.VK_ALT);
    robot.keyPress(KeyEvent.VK_TAB);
    robot.keyRelease(KeyEvent.VK_TAB);
    //robot.keyRelease(KeyEvent.VK_ALT);
  }
  //[app向右切换]相当于在按了alt+tab的情况下再按1次tab
  public void tabRight(){
    robot.keyPress(KeyEvent.VK_TAB);
    robot.keyRelease(KeyEvent.VK_TAB);
  }
  //[app向左切换]相当于在按了alt+tab的情况下再按1次shift+tab
  public void tabLeft(){
    robot.keyPress(KeyEvent.VK_SHIFT);
    robot.keyPress(KeyEvent.VK_TAB);
    robot.keyRelease(KeyEvent.VK_TAB);
    robot.keyRelease(KeyEvent.VK_SHIFT);
  }
  //[关闭app切换栏]在使用showSwitchApps()后必须调用该函数来释放alt
  public void closeSwitchApps(){
    robot.keyRelease(KeyEvent.VK_ALT);
  }
  //[app回切/左切1次]:按下shift+alt+tab,并释放
  public void simpleLeftSwitchApp(){
    this.showSwitchApps();
    this.delay(VISIBAL_MOVEMENT);
    this.tabLeft();
    this.tabLeft();
    this.delay(VISIBAL_MOVEMENT);
    this.closeSwitchApps();
  }
  //[app切换/右切1次]:按下alt+tab,并释放
  public void simpleRightSwitchApp(){
    this.showSwitchApps();
    this.delay(VISIBAL_MOVEMENT);
    this.closeSwitchApps();
  }
  //[显示当前window下所有app]:相当于window+tab
  public void listAppsWindow(){
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_TAB);
    robot.keyRelease(KeyEvent.VK_TAB);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[显示桌面/隐藏app]:相当于window+M
  public void showDesktop(){
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_M);
    robot.keyRelease(KeyEvent.VK_M);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[当前窗口最大化]:相当于window+UP
  public void windowUp(){
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_UP);
    robot.keyRelease(KeyEvent.VK_UP);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[取消当前窗口最大化]:相当于window+DOWN
  public void windowDown(){
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_DOWN);
    robot.keyRelease(KeyEvent.VK_DOWN);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[窗口置于左侧/多窗口并排]:相当于window+LEFT
  public void windowLeft(){
    //TODO: window + Left
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_LEFT);
    robot.keyRelease(KeyEvent.VK_LEFT);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[窗口置于右侧/多窗口并排]:相当于window+RIGHT
  public void windowRight(){
    //TODO: window + Right
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_RIGHT);
    robot.keyRelease(KeyEvent.VK_RIGHT);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[切换桌面:左切]:window+control+left
  public void leftSwitchWindow(){
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_LEFT);
    robot.keyRelease(KeyEvent.VK_LEFT);
    robot.keyRelease(KeyEvent.VK_CONTROL);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[切换桌面:右切]:window+control+right
  public void rightSwitchWindow(){
    robot.keyPress(KeyEvent.VK_WINDOWS);
    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_RIGHT);
    robot.keyRelease(KeyEvent.VK_RIGHT);
    robot.keyRelease(KeyEvent.VK_CONTROL);
    robot.keyRelease(KeyEvent.VK_WINDOWS);
  }
  //[快速打开记事本]
  public void openNotepad(){
    try {
      Runtime.getRuntime().exec("notepad");
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  //[快速打开画图板]
  public void openPaint(){
    try {
      Runtime.getRuntime().exec("mspaint");
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  //[ppt笔]
  public void setDraw(){
    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_P);
    robot.keyRelease(KeyEvent.VK_CONTROL);
    robot.keyRelease(KeyEvent.VK_P);
  }
  //[ppt激光笔]
  public void setLaser(){
    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_L);
    robot.keyRelease(KeyEvent.VK_CONTROL);
    robot.keyRelease(KeyEvent.VK_L);
  }
  //[ppt荧光笔]
  public void setMark(){
    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_I);
    robot.keyRelease(KeyEvent.VK_CONTROL);
    robot.keyRelease(KeyEvent.VK_I);
  }
  //[ppt隐藏鼠标]
  public void hideMouse(){
    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_H);
    robot.keyRelease(KeyEvent.VK_CONTROL);
    robot.keyRelease(KeyEvent.VK_H);
  }
  //[ppt 上1张]
  public void prevSlide(){
    robot.keyPress(KeyEvent.VK_LEFT);
    robot.keyRelease(KeyEvent.VK_LEFT);
  }
  //[ppt 下1张]
  public void nextSlide(){
    robot.keyPress(KeyEvent.VK_RIGHT);
    robot.keyRelease(KeyEvent.VK_RIGHT);
  }
  //延迟函数,延迟ms个毫秒
  public void delay(int ms){
    robot.delay(ms);
  }
  //获得当前PC屏幕的尺寸
  public void setScreenSize(){
    Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();

    screenWidth = (int)screensize.getWidth();
    screenHeight = (int)screensize.getHeight();
  }  
  //打印当前PC屏幕的尺寸
  public String getScreenInfo(){
    return "screenSize:"+screenWidth+"*"+screenHeight;
  }
  //设置手机和PC屏幕尺寸的转换比
  private void setScale(){
    heiScale = -1.0 / 1.5;
    widScale = 1.0 / 3.0;
  }


}

The PC side interacts with Android app via Bluetooth: BluetoothServer.java


/**
 * Created by luyudi on 2016/11/9.
 * Modified by Lannooo on 2016/12/4.
 */
// server
import java.awt.*;
import java.io.InputStream;
import java.io.IOException;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

public class BlueToothServer implements Runnable {
  private remotePC Controller;
  //  Below UUID Must be related to the mobile phone client UUID Phase 1 To 
  private static UUID ECHO_SERVER_UUID= new UUID("aeb9f938a1a34947ace29ebd0c67adf1", false);
  //  Stream connection notification   Used to create a flow connection 
  private StreamConnectionNotifier myPCConnNotifier = null;
  //  Stream connection 
  private StreamConnection streamConn = null;
  //  Accept data byte stream 
  //  Receive x y  Coordinates 
  private byte[] acceptedByteArray = new byte[1024];
  //  Read (input) stream 
  private InputStream inputStream = null;

  //  Main thread 
  public static void main(String[] args) {
    new BlueToothServer();
  }

  public BlueToothServer() {
    try {
      String url = "btspp://localhost:" + ECHO_SERVER_UUID.toString();
      //  Get stream connection notification 
      myPCConnNotifier = (StreamConnectionNotifier) Connector.open(url);
      Controller = new remotePC();
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    //  Open the connection channel and read the streamline thread 
    new Thread(this).start();
  }
  public static int getInt(byte[] bytes){
    return (0xff & bytes[3])       |
        (0xff00 & (bytes[2] << 8))  |
        (0xff0000 & (bytes[1] << 16)) |
        (0xff000000 & (bytes[0] << 24));
  }
  public static float getFloat(byte[] b){
    return Float.intBitsToFloat(getInt(b));
  }
  @Override
  public void run() {
    try {
      boolean isMouseLPressed = false;
      boolean isWheelPressed = false;
      boolean end = false;

      while (true) {
        //  Continuously keeps listening to the connection request of the client 
        //  Get a stream connection 
        streamConn = myPCConnNotifier.acceptAndOpen();
        //  Acquisition flow channel 
        inputStream = streamConn.openInputStream();
        //  Loop to read the byte stream and judge code Type and x , y Coordinates 
        while (inputStream.read(acceptedByteArray) != -1) {
          String acceptString = new String(acceptedByteArray);
          int index;
          if((index = acceptString.indexOf("RemoteTouch")) != -1) {
            byte[] codeBytes = new byte[4];
            byte[] dxBytes = new byte[6];
            byte[] dyBytes = new byte[6];
            System.arraycopy(acceptedByteArray, index + 11, codeBytes, 0, 4);
            System.arraycopy(acceptedByteArray, index + 15, dyBytes, 0, 6);
            System.arraycopy(acceptedByteArray, index + 21, dxBytes, 0, 6);
            int dy = Integer.parseInt(new String(dyBytes));
            int dx = Integer.parseInt(new String(dxBytes));
            int code = getInt(codeBytes);
            if (end) {
              inputStream.close();
              if (streamConn != null) {
                streamConn.close();
                System.out.println("Disconnected...");
              }
              break;
            }
            switch (code) {
              case 1:// Press the left mouse button 
                isMouseLPressed = true;
                Controller.pressMouseL();
                System.out.println("Pressing mouse L");
                break;
              case 2:// Release the left mouse button 
                if (isMouseLPressed) {
                  Controller.releaseMouseL();
                  System.out.println("Released mouse L");
                  isMouseLPressed=false;
                }
                break;
              case 3:// Click the left mouse button 
                Controller.clickMouseL();
                System.out.println("Clicked mouse L");
                break;
              case 4:// Click the right mouse button 
                Controller.clickMouseR();
                System.out.println("Clicked mouse R");
                break;
              case 5:// Press down the roller 
//           isWheelPressed = true;
//           Controller.pressWheel();
//           System.out.println("Pressing wheel");
                break;
              case 6:// Release roller 
//           if(isWheelPressed){
//             Controller.releaseWheel();
//             System.out.println("Released wheel");
//           }
                break;
              case 7:// Roller rolling 
                int step = Math.abs(dy) / 40;
                System.out.println("wheel");
                if (dy > 0) {
                  Controller.wheelDown(step);
                  System.out.printf("Wheel Down:%d steps. dy=%d\n", step, dy);
                } else {
                  Controller.wheelUp(step);
                  System.out.printf("Wheel Up:%d steps. dy=%d\n", step, dy);
                }
                break;
              case 8:// Zoom in, zoom out 
                double s = Math.sqrt((double) (dx * dx + dy * dy));
                if (dx < 0) {
                  Controller.zoomOut((int) s / 20);
                  System.out.printf("Zoom out %d steps. dx=%d,dy=%d\n", (int) s / 20, dx, dy);
                } else {
                  Controller.zoomIn((int) s / 20);
                  System.out.printf("Zoom in %d steps. dx=%d,dy=%d\n", (int) s / 20, dx, dy);
                }
                break;
              case 9:// Display switchable apps
                Controller.listAppsWindow();
                System.out.println("show Switch apps");
                break;
              case 10:// Display desktop 
                Controller.showDesktop();
                System.out.println("show desktop");
                break;
              case 11://app  Right incision 
                Controller.simpleRightSwitchApp();
                System.out.println("switch app: right");
                break;
              case 12://app  Left cut 
                Controller.simpleLeftSwitchApp();
                System.out.println("switch app: left");
                break;
              case 13://window  Right incision 
                Controller.rightSwitchWindow();
                System.out.println("switch window right");
                break;
              case 14://window  Left cut 
                Controller.leftSwitchWindow();
                System.out.println("switch window left");
                break;
              case 15:// Double-click the left mouse button 
                Controller.clickMouseL();
                Controller.delay(1);
                Controller.clickMouseL();
                System.out.println("clicked double mouse L");
                break;
              case 16:// Mouse movement 
                Controller.move(dx, dy, 1);
                //System.out.printf("Move mouse:dx=%d,dy=%d\n", dx, dy);
                break;
              case 17:// Left split screen 
                Controller.windowLeft();
                System.out.println("Window divide: left");
                break;
              case 18:// Right split screen 
                Controller.windowRight();
                System.out.println("Window divide: right");
                break;
              case 19: // Upper 1 Zhang ppt
                Controller.prevSlide();
                System.out.println("previous slide");
                break;
              case 20:
                Controller.nextSlide();
                System.out.println("Next Slide");
                break;
              case 32: // PPT Set to hide the mouse 
                Controller.hideMouse();
                System.out.println("Hide");
                break;
              case 33: // ppt Laser pointer 
                Controller.setLaser();
                System.out.println("Laser");
                break;
              case 34: // ppt Pen 
                Controller.setDraw();
                System.out.println("Draw");
                break;
              case 35: // ppt  Highlighter 
                Controller.setMark();
                System.out.println("Mark");
                break;
              case 100:// Quit 
                end = true;
                System.out.println("Quit.");
                break;

              default:// Not recognized 
                System.out.println("Unknown code");
                break;
            }
          }
          // clear data
          acceptedByteArray = new byte[1024];
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Related articles: