Android当无线鼠标,通过蓝牙与pc通信,pc端用java写 分类: Android 2015-07-30 09:24 18人阅读 评论(0) 收藏

最近想写一个小程序,把android通过蓝牙当做无线鼠标操作笔记本,pc端用java语言实现,于是查了查资料,android的蓝牙开发网上的例子也不少,自动的sdk里也有一个例子BluetoothChat,把android蓝牙经常用的方法基本上都用了,而且http://blog.csdn.net/pku_android/article/details/7430849这个例子也很不错,参照这些例子,android端的程序也就很简单了。首先这个原理很简单,通过蓝牙进行连接,获得手指在屏幕上水平方向移动距离的x和竖直方向y,并发送到pc端,然后控制pc端鼠标移动,至于数据格式,采用了<String,String>这样的形式,这样在pc端解析的时候也很简单,截取字符串就行了,在界面中增加两个按钮分别作为左键和右键,触发事件时发送自定义的字符串就行,在pc端接收后模拟鼠标左键或右键按下事件即可。
      下面android端开始,首先要声明一个[url=]BlueAdapter对象并获得这个对象[/url][mw_shl_code=java,true]blueadapter=BluetoothAdapter.getDefaultAdapter();[/mw_shl_code][url=],[/url][url=]这个对象相当于本地蓝牙,[/url]要通过本地蓝牙远程连接pc端的蓝牙还需要pc端蓝牙的MAC地址,要获得MAC地址首先要在设置页面里让android与pc端蓝牙匹配,然后可以通过getpairedDevices()方法获得,[mw_shl_code=java,true]private void getpairedDevices(){
        Set<BluetoothDevice> pairedDevice=blueadapter.getBondedDevices();
        if(mArrays!=null){
                mArrays.clear();
        }
        if(pairedDevice.size()>0){
                for(BluetoothDevice device:pairedDevice){
                        names.add(device.getName());//设备名字
                        addresses.add(device.getAddress());//设备地址
                }
        }
} [/mw_shl_code]
names和addresses是声明的两个ArrayList<String>对象,用来动态添加字符串,我的方法是添加一个ListView对象,把names放在封装在ListView对象中,得到点击ListView的位置,然后通过addresses得到所连接的MAC地址,然后调用[url=]getRemoteDevice[/url]([url=]String[/url] address)方法得到BluetoothDevice对象[mw_shl_code=java,true]BluetoothDevice device = blueadapter.getRemoteDevice(addresses.get(position));[/mw_shl_code]然后就是通过device得到ConnectThread对象,ConnectThread类用来来实现连接,创建BluetoothSocket对象发送数据,由于只需要发送数据不用接收pc端发来的数据,所以sdk例子中的接收数据部分就可以省略了,在ConnectThread中加一个write方法就行了,ConnectThread的代码如下:[mw_shl_code=java,true]private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
        UUID MY_UUID=UUID.fromString("04c6093b-0000-1000-8000-00805f9b34fb");
        private OutputStream mmOutStream;//输出流
    public ConnectThread(BluetoothDevice device) {       
        BluetoothSocket tmp = null;
              
        try {            
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);//获得socket对象
        } catch (IOException e) { }
        mmSocket = tmp;
    }

    public void run() {
       
        try {            
            mmSocket.connect();//连接
                        mmOutStream = mmSocket.getOutputStream();
        } catch (IOException connectException) {
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;
        }
    }

   //取消 
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
        //向输出流中写数据
         public void write(byte[] bytes) {
        try {
            mmOutStream.write(bytes);
        } catch (IOException e) {
                e.printStackTrace();
        }
      
    }
}[/mw_shl_code]
下面就是活动手指移动距离了,在界面中随便添加一个控件,TextView或ImageView,只要有setOnTouchListener方法就行,因为要捕捉手指移动事件,[mw_shl_code=java,true]
private float initx;//初始x,y
private float inity;
private float disx;//移动x,y
private float disy;
                //mousedraw设置监听,发送鼠标移动信息
mousedraw.setOnTouchListener(new OnTouchListener(){

                        public boolean onTouch(View arg0, MotionEvent event) {
                                switch(event.getAction()){
                                case MotionEvent.ACTION_DOWN:
                                        initx=event.getX();
                                        inity=event.getY();                                        
                                        break;
                                case MotionEvent.ACTION_MOVE:
                                        disx=event.getX()-initx;//x方向的移动距离
                                        disy=event.getY()-inity;//y方向的移动距离
                                        
                                        initx=event.getX();
                                        inity=event.getY();
                                        if(disx!=0||disy!=0){
                                                msg="<"+disx+","+disy+">";//根据自定义的格式得到字符串
                                                connectblue.write(msg.getBytes());//发送数据
                                        }
                                        break;
                                }
                                return true;
                        }
                        
                });[/mw_shl_code]
其中主要的也就是[mw_shl_code=java,true]msg="<"+disx+","+disy+">";
connectblue.write(msg.getBytes());[/mw_shl_code]这两句了,connectblue是获得的ConnectThread对象,write就是发送数据了。至于左键,右键就不写了,原理一样,只不过发送字符串变成了特定的字符串了,个人建议不要有大于,小于符号因为pc端可以通过是否含有大于,小于号来判断是鼠标移动还是按下。这样android端就差不多了。

下面是pc端,pc端用java写,要让鼠标移动,并且可以产生按下事件,于是就用到了Robot。java中的Robot专门用于控制键盘和鼠标。而java调用蓝牙则需要一个叫做bluecove的第三方库,可以在网上下,要取得数据就要取得连接,首先写一个连接类来建立连接[mw_shl_code=java,true]public class WaitThread implements Runnable{
        public WaitThread(){
                
        }
        @Override
        public void run() {
                // TODO Auto-generated method stub
                waitForConnection();
        }
        //Waiting for connection from devices
        private void waitForConnection(){
                //retrieve the local Bluetooth device object
                LocalDevice local=null;
                StreamConnectionNotifier notifier;
                StreamConnection connection=null;
                
                //setup the server to listen for connection
                try{
                        local=LocalDevice.getLocalDevice();
                        local.setDiscoverable(DiscoveryAgent.GIAC);
                        UUID uuid=new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"
                        
                        String url="btspp://localhost:"+uuid.toString()+";name=RemoteBluetooth";
                        notifier=(StreamConnectionNotifier)Connector.open(url);
                }catch(Exception e){
                        e.printStackTrace();
                        return;
                }
                //waiting for connection
                while(true){
                        try{
                                System.out.println("waiting for connection...");
                                connection=notifier.acceptAndOpen();
                                
                                Thread processThread=new Thread(new ProcessConnectionThread(connection));
                                processThread.start();//启动ProcessConnectionThread实例
                        }catch(Exception e){
                                e.printStackTrace();
                                return;
                        }
                }
        }

}[/mw_shl_code]ProcessConnectionThread作用是接收数据并进行分析[mw_shl_code=java,true]public class ProcessConnectionThread implements Runnable{
        private StreamConnection mConnection;//连接对象
        
        //左键,右键
        private String MOU_LEFT="MOU_LEFT";
        private String MOU_RIGH="MOU_RIGH";
        private float nowx;
        private float nowy;
        private String movex_str;
        private String movey_str;
        private float movex=0.0f;
        private float movey=0.0f;
        InputStream inputStream=null;
        public ProcessConnectionThread(StreamConnection connection){
                mConnection=connection;
        }
        @Override
        public void run() {
                // TODO Auto-generated method stub
                try{
                        inputStream=mConnection.openInputStream();
                        byte[] buffer=new byte[1024];
                        int len=-1;
                        System.out.println("waiting for input");
                        String cmd;
                        while(true){                                
                                if((len=inputStream.read(buffer))!=-1){                                        
                                        cmd=new String(buffer,0,len,Charset.forName("UTF-8"));//获得字符串
                                        processCommand(cmd);
                                }
                        }
                }catch(Exception e){
                        e.printStackTrace();
                }
        }
        private void processCommand(String command){
                try{
        
                        Robot robot=new Robot();
                        if(command.contains("<")){
                                movex_str=command.substring(command.indexOf("<")+1, command.indexOf(","));//截取字符串,获得x方向的移动距离
                                movey_str=command.substring(command.indexOf(",")+1,command.indexOf(">"));//y方向
                                movex=Float.parseFloat(movex_str);
                                movey=Float.parseFloat(movey_str);
                                Point point = MouseInfo.getPointerInfo().getLocation();//获得当前鼠标位置
                                nowx=point.x;
                                nowy=point.y;
                                robot.mouseMove((int)(nowx+movex),(int)(nowy+movey));//鼠标移动到当前位置
                        }else if(command.equals(MOU_LEFT)){
//左键按下
                                robot.mousePress(InputEvent.BUTTON1_MASK);
                                robot.mouseRelease(InputEvent.BUTTON1_MASK);
                        }else if(command.equals(MOU_RIGH)){
//右键按下
                                robot.mousePress(InputEvent.BUTTON3_MASK);
                                robot.mouseRelease(InputEvent.BUTTON3_MASK);
                        }else{
                                System.out.println(command);
                        }
                        
                }catch(Exception e){
                        e.printStackTrace();
                }
        }
}[/mw_shl_code]
最后在一个main函数里声明一个WaitThread对象并启动就行了。pc端启动后,可以启动android端,然后就可以通信了。
      好,打完收工。

原文地址:https://www.cnblogs.com/xieping/p/4714157.html