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();
}
}
}