android藍(lán)牙控制PC端代碼分享
引言
在安卓端通過藍(lán)牙發(fā)送指令到PC端,java程序接收指令,并執(zhí)行相應(yīng)的動(dòng)作。其中指令格式有所規(guī)范,PC端的java程序通過robot庫(kù)進(jìn)行操作
代碼
控制類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 {
//保存當(dāng)前鼠標(biāo)指針的坐標(biāo)(px,py)
private static int px;
private static int py;
//最大延遲時(shí)間:1秒
public static final int MAX_DELAY = 1000;
//最小間隔時(shí)間:1毫秒
public static final int SAMPLE_TIME_DIV = 1;
//魔法數(shù)字,用于設(shè)置默認(rèn)的事件delay時(shí)間間隔
private final double magicX = 1.0;
//視覺延遲:默認(rèn)100ms
private final int VISIBAL_MOVEMENT = 100;
//PC屏幕尺寸
private int screenWidth;
private int screenHeight;
//手機(jī)屏幕尺寸
private int mobileWidth;
private int mobileHeight;
//手機(jī)電腦尺寸轉(zhuǎn)換的比例
private double widScale;
private double heiScale;
//用于控制的robot類
private Robot robot;
//默認(rèn)構(gòu)造函數(shù)
public remotePC() throws AWTException{
this(1366, 768);
}
//構(gòu)造函數(shù),指定手機(jī)屏幕尺寸
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);
}
//[鼠標(biāo)光標(biāo)移動(dòng)]
//dt:間隔時(shí)間,時(shí)間長(zhǎng)短對(duì)應(yīng)速度
//dx,dy:手機(jī)上移動(dòng)的相對(duì)橫縱位移,自動(dòng)轉(zhuǎn)換為pc上應(yīng)該移動(dòng)的尺寸
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);
}
}
//[按下鼠標(biāo)左鍵]
public void pressMouseL(){
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
}
//[釋放鼠標(biāo)左鍵]
public void releaseMouseL(){
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
//[點(diǎn)擊一下鼠標(biāo)左鍵]
public void clickMouseL(){
this.pressMouseL();
this.releaseMouseL();
}
//[按下鼠標(biāo)右鍵]
public void pressMouseR(){
robot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
}
//[釋放鼠標(biāo)右鍵]
public void releaseMouseR(){
robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
}
//[點(diǎn)擊鼠標(biāo)右鍵]
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);
}
//[滾輪往下移動(dòng)]:step是移動(dòng)步數(shù),相對(duì)于滾輪的一格
public void wheelDown(int step){
for(int i=0; i<step; i++){
robot.mouseWheel(1);
}
}
//[滾輪往上移動(dòng)]:step是移動(dòng)步數(shù),相對(duì)于滾輪的一格
public void wheelUp(int step){
for(int i=0; i<step; i++){
robot.mouseWheel(-1);
}
}
//[敲一格字符:A-Z]:c為字母的char類型字符,必須是大寫的
public void printChar(char c){
if(c <= 'Z' && c >= 'A'){
robot.keyPress((int)c);
robot.keyRelease((int)c);
}
}
//[敲一個(gè)空格]
public void printSpace(){
robot.keyPress(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_SPACE);
}
//[放大]相當(dāng)于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);
}
//[縮小]相當(dāng)于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切換欄]相當(dāng)于alt+tab,并且alt不放開,一旦調(diào)用該函數(shù)后,需要手動(dòng)調(diào)用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向右切換]相當(dāng)于在按了alt+tab的情況下再按一次tab
public void tabRight(){
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
}
//[app向左切換]相當(dāng)于在按了alt+tab的情況下再按一次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);
}
//[關(guān)閉app切換欄]在使用showSwitchApps()后必須調(diào)用該函數(shù)來釋放alt
public void closeSwitchApps(){
robot.keyRelease(KeyEvent.VK_ALT);
}
//[app回切/左切一次]:按下shift+alt+tab,并釋放
public void simpleLeftSwitchApp(){
this.showSwitchApps();
this.delay(VISIBAL_MOVEMENT);
this.tabLeft();
this.tabLeft();
this.delay(VISIBAL_MOVEMENT);
this.closeSwitchApps();
}
//[app切換/右切一次]:按下alt+tab,并釋放
public void simpleRightSwitchApp(){
this.showSwitchApps();
this.delay(VISIBAL_MOVEMENT);
this.closeSwitchApps();
}
//[顯示當(dāng)前window下所有app]:相當(dāng)于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]:相當(dāng)于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);
}
//[當(dāng)前窗口最大化]:相當(dāng)于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);
}
//[取消當(dāng)前窗口最大化]:相當(dāng)于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);
}
//[窗口置于左側(cè)/多窗口并排]:相當(dāng)于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);
}
//[窗口置于右側(cè)/多窗口并排]:相當(dāng)于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隱藏鼠標(biāo)]
public void hideMouse(){
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_H);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_H);
}
//[ppt 上一張]
public void prevSlide(){
robot.keyPress(KeyEvent.VK_LEFT);
robot.keyRelease(KeyEvent.VK_LEFT);
}
//[ppt 下一張]
public void nextSlide(){
robot.keyPress(KeyEvent.VK_RIGHT);
robot.keyRelease(KeyEvent.VK_RIGHT);
}
//延遲函數(shù),延遲ms個(gè)毫秒
public void delay(int ms){
robot.delay(ms);
}
//獲得當(dāng)前PC屏幕的尺寸
public void setScreenSize(){
Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
screenWidth = (int)screensize.getWidth();
screenHeight = (int)screensize.getHeight();
}
//打印當(dāng)前PC屏幕的尺寸
public String getScreenInfo(){
return "screenSize:"+screenWidth+"*"+screenHeight;
}
//設(shè)置手機(jī)和PC屏幕尺寸的轉(zhuǎn)換比
private void setScale(){
heiScale = -1.0 / 1.5;
widScale = 1.0 / 3.0;
}
}
PC端通過藍(lán)牙和安卓app交互: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;
// 下面的UUID必須和手機(jī)客戶端的UUID相一致
private static UUID ECHO_SERVER_UUID= new UUID("aeb9f938a1a34947ace29ebd0c67adf1", false);
// 流連接通知 用于創(chuàng)建流連接
private StreamConnectionNotifier myPCConnNotifier = null;
// 流連接
private StreamConnection streamConn = null;
// 接受數(shù)據(jù)字節(jié)流
// 接收x y 坐標(biāo)
private byte[] acceptedByteArray = new byte[1024];
// 讀?。ㄝ斎耄┝?
private InputStream inputStream = null;
// 主線程
public static void main(String[] args) {
new BlueToothServer();
}
public BlueToothServer() {
try {
String url = "btspp://localhost:" + ECHO_SERVER_UUID.toString();
// 得到流連接通知
myPCConnNotifier = (StreamConnectionNotifier) Connector.open(url);
Controller = new remotePC();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 打開連接通道并讀取流線程
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) {
// 持續(xù)保持著監(jiān)聽客戶端的連接請(qǐng)求
// 獲取流連接
streamConn = myPCConnNotifier.acceptAndOpen();
// 獲取流通道
inputStream = streamConn.openInputStream();
// 循環(huán)讀取字節(jié)流,判斷code類型和x,y坐標(biāo)
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://按下鼠標(biāo)左鍵
isMouseLPressed = true;
Controller.pressMouseL();
System.out.println("Pressing mouse L");
break;
case 2://釋放鼠標(biāo)左鍵
if (isMouseLPressed) {
Controller.releaseMouseL();
System.out.println("Released mouse L");
isMouseLPressed=false;
}
break;
case 3://點(diǎn)擊鼠標(biāo)左鍵
Controller.clickMouseL();
System.out.println("Clicked mouse L");
break;
case 4://點(diǎn)擊鼠標(biāo)右鍵
Controller.clickMouseR();
System.out.println("Clicked mouse R");
break;
case 5://按下滾輪
// isWheelPressed = true;
// Controller.pressWheel();
// System.out.println("Pressing wheel");
break;
case 6://釋放滾輪
// if(isWheelPressed){
// Controller.releaseWheel();
// System.out.println("Released wheel");
// }
break;
case 7://滾輪滾動(dòng)
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://放大、縮小
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://顯示可切換apps
Controller.listAppsWindow();
System.out.println("show Switch apps");
break;
case 10://顯示桌面
Controller.showDesktop();
System.out.println("show desktop");
break;
case 11://app 右切
Controller.simpleRightSwitchApp();
System.out.println("switch app: right");
break;
case 12://app 左切
Controller.simpleLeftSwitchApp();
System.out.println("switch app: left");
break;
case 13://window 右切
Controller.rightSwitchWindow();
System.out.println("switch window right");
break;
case 14://window 左切
Controller.leftSwitchWindow();
System.out.println("switch window left");
break;
case 15://鼠標(biāo)左鍵雙擊
Controller.clickMouseL();
Controller.delay(1);
Controller.clickMouseL();
System.out.println("clicked double mouse L");
break;
case 16://鼠標(biāo)移動(dòng)
Controller.move(dx, dy, 1);
//System.out.printf("Move mouse:dx=%d,dy=%d\n", dx, dy);
break;
case 17://左分屏
Controller.windowLeft();
System.out.println("Window divide: left");
break;
case 18://右分屏
Controller.windowRight();
System.out.println("Window divide: right");
break;
case 19: //上一張ppt
Controller.prevSlide();
System.out.println("previous slide");
break;
case 20:
Controller.nextSlide();
System.out.println("Next Slide");
break;
case 32: // PPT設(shè)置為隱藏鼠標(biāo)
Controller.hideMouse();
System.out.println("Hide");
break;
case 33: // ppt激光筆
Controller.setLaser();
System.out.println("Laser");
break;
case 34: // ppt筆
Controller.setDraw();
System.out.println("Draw");
break;
case 35: // ppt 熒光筆
Controller.setMark();
System.out.println("Mark");
break;
case 100://退出
end = true;
System.out.println("Quit.");
break;
default://未識(shí)別
System.out.println("Unknown code");
break;
}
}
// clear data
acceptedByteArray = new byte[1024];
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Studio如何查看源碼并調(diào)試的方法步驟
這篇文章主要介紹了Android Studio如何查看源碼并調(diào)試的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
Android實(shí)現(xiàn)通話自動(dòng)錄音
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)通話自動(dòng)錄音,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
Android編程之計(jì)時(shí)器Chronometer簡(jiǎn)單示例
這篇文章主要介紹了Android計(jì)時(shí)器Chronometer簡(jiǎn)單用法,結(jié)合實(shí)例形式分析了Android計(jì)時(shí)器Chronometer的定義、事件響應(yīng)及界面布局相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Android開發(fā)注解排列組合出啟動(dòng)任務(wù)ksp
這篇文章主要為大家介紹了Android開發(fā)注解排列組合出啟動(dòng)任務(wù)ksp示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Android實(shí)現(xiàn)簡(jiǎn)單動(dòng)態(tài)搜索功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡(jiǎn)單動(dòng)態(tài)搜索功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
android 實(shí)現(xiàn)側(cè)邊彈窗特效代碼
側(cè)邊彈窗是在左邊,需要定位好位置,實(shí)現(xiàn)原理其實(shí)就是進(jìn)出動(dòng)效,用位移加透明度效果來控制,下面通過代碼給大家介紹android 實(shí)現(xiàn)側(cè)邊彈窗,需要的朋友參考下吧2021-06-06
Android開發(fā)中總結(jié)的Adapter工具類【附完整源碼下載】
這篇文章主要介紹了Android開發(fā)中總結(jié)的Adapter工具類,簡(jiǎn)單說明了Adapter的功能,并結(jié)合實(shí)例形式分析了Adapter工具類的相關(guān)使用方法,并附帶完整源碼供讀者下載參考,需要的朋友可以參考下2017-11-11
詳解Flutter?響應(yīng)式狀態(tài)管理框架GetX
這篇文章主要為大家介紹了Flutter?響應(yīng)式狀態(tài)管理框架GetX詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Android Back鍵點(diǎn)擊兩次退出應(yīng)用詳解及實(shí)現(xiàn)方法總結(jié)
這篇文章主要介紹了Android Back鍵點(diǎn)擊兩次退出應(yīng)用詳解及實(shí)現(xiàn)方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2016-10-10
詳解基于Android App 安全登錄認(rèn)證解決方案
這篇文章主要介紹了基于Android App 安全登錄認(rèn)證解決方案,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09

