最近想写一个小程序,把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端,然后就可以通信了。
好,打完收工。