作者:   张奇

       我将在这篇文章中介绍了的Android蓝牙程序。这个程序就是将实现把手机变做电脑PPT播放的遥控器:用音量加和音量减键来控制PPT页面的切换。

遥控器服务器端

首先,我们需要编写一个遥控器的服务器端(支持蓝牙的电脑)来接收手机端发出的信号。为了实现这个服务器端,我用到了一个叫做Bluecove(专门用来为蓝牙服务的!)的Java库。

以下是我的RemoteBluetoothServer类:

[java]  
    
1. <span style="font-size:16px;">public class RemoteBluetoothServer{  
2.   
3. public static void main(String[] args) {  
4. new Thread(new WaitThread());  
5.         waitThread.start();  
6.     }  
7. }  
8. </span>



在主方法中创建了一个线程,用于连接客户端,并处理信号。

[java]  
    
1. <span style="font-size:16px;">public class WaitThread implements Runnable{  
2.   
3. /** Constructor */  
4. public WaitThread() {  
5.     }  
6.   
7. @Override  
8. public void run() {  
9.         waitForConnection();  
10.     }  
11.   
12. /** Waiting for connection from devices */  
13. private void waitForConnection() {  
14. // retrieve the local Bluetooth device object  
15. null;  
16.   
17.         StreamConnectionNotifier notifier;  
18. null;  
19.   
20. // setup the server to listen for connection  
21. try {  
22.             local = LocalDevice.getLocalDevice();  
23.             local.setDiscoverable(DiscoveryAgent.GIAC);  
24.   
25. new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"  
26. "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";  
27.             notifier = (StreamConnectionNotifier)Connector.open(url);  
28. catch (Exception e) {  
29.             e.printStackTrace();  
30. return;  
31.         }  
32. // waiting for connection  
33. while(true) {  
34. try {  
35. "waiting for connection...");  
36.                         connection = notifier.acceptAndOpen();  
37.   
38. new Thread(new ProcessConnectionThread(connection));  
39.                 processThread.start();  
40. catch (Exception e) {  
41.                 e.printStackTrace();  
42. return;  
43.             }  
44.         }  
45.     }  
46. }  
47. </span>



在waitForConnection()中,首先将服务器设为可发现的,并为这个程序创建了UUID(用于同客户端通信);然后就等待来自客户端的连接请求。当它收到一个初始的连接请求时,将创建一个ProcessConnectionThread来处理来自客户端的命令。以下是ProcessConnectionThread的代码:

[java]  
1. <span style="font-size:16px;">public class ProcessConnectionThread implements Runnable{  
2.   
3. private StreamConnection mConnection;  
4.   
5. // Constant that indicate command from devices  
6. private static final int EXIT_CMD = -1;  
7. private static final int KEY_RIGHT = 1;  
8. private static final int KEY_LEFT = 2;  
9.   
10. public ProcessConnectionThread(StreamConnection connection)  
11.     {  
12.         mConnection = connection;  
13.     }  
14.   
15. @Override  
16. public void run() {  
17. try {  
18. // prepare to receive data  
19.             InputStream inputStream = mConnection.openInputStream();  
20.   
21. "waiting for input");  
22.   
23. while (true) {  
24. int command = inputStream.read();  
25.   
26. if (command == EXIT_CMD)  
27.                 {  
28. "finish process");  
29. break;  
30.                 }  
31.                 processCommand(command);  
32.             }  
33. catch (Exception e) {  
34.             e.printStackTrace();  
35.         }  
36.     }  
37.   
38. /**
39.      * Process the command from client
40.      * @param command the command code
41.      */  
42. private void processCommand(int command) {  
43. try {  
44. new Robot();  
45. switch (command) {  
46. case KEY_RIGHT:  
47.                     robot.keyPress(KeyEvent.VK_RIGHT);  
48. "Right");  
49. break;  
50. case KEY_LEFT:  
51.                     robot.keyPress(KeyEvent.VK_LEFT);  
52. "Left");  
53. break;  
54.             }  
55. catch (Exception e) {  
56.             e.printStackTrace();  
57.         }  
58.     }  
59. }  
60. </span>


ProcessConnectionThread类主要用于接收并处理客户端发送的命令。需要处理的命令只有两个:KEY_RIGHT和KEY_LEFT。我用java.awt.Robot来生成电脑端的键盘事件。

 

以上就是服务器端所需要做的工作。

 

遥控器客户端

这里的客户端指的其实就是Android手机。在开发手机端代码的过程中,我参考了 Android Dev Guide中Bluetooth Chat这个程序的代码,这个程序在SDK的示例代码中可以找到。

 

要将客户端连接服务器端,那么必须让手机可以扫描到电脑,DeviceListActivity 类的工作就是扫描并连接服务器。BluetoothCommandService类负责将命令传至服务器端。这两个类与Bluetooth Chat中的内容相似,只是删除了Bluetooth Chat中的BluetoothCommandService中的AcceptThread ,因为客户端不需要接受连接请求。ConnectThread用于初始化与服务器的连接,ConnectedThread 用于发送命令。

RemoteBluetooth 是客户端的主activity,其中主要代码如下:


[java]  
    
 
1. <span style="font-size:16px;">protected void onStart() {  
2. super.onStart();  
3.   
4. // If BT is not on, request that it be enabled.  
5. // setupCommand() will then be called during onActivityResult  
6. if (!mBluetoothAdapter.isEnabled()) {  
7. new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
8.         startActivityForResult(enableIntent, REQUEST_ENABLE_BT);  
9.     }  
10. // otherwise set up the command service  
11. else {  
12. if (mCommandService==null)  
13.             setupCommand();  
14.     }  
15. }  
16.   
17. private void setupCommand() {  
18. // Initialize the BluetoothChatService to perform bluetooth connections  
19. new BluetoothCommandService(this, mHandler);  
20. }  
21. </span>

onStart()用于检查手机上的蓝牙是否已经打开,如果没有打开则创建一个Intent来打开蓝牙。setupCommand()用于在按下音量加或音量减键时向服务器发送命令。其中用到了onKeyDown事件:

[java]  
    
   
 
   
  
1. <span style="font-size:16px;">public boolean onKeyDown(int keyCode, KeyEvent event) {  
2. if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {  
3.         mCommandService.write(BluetoothCommandService.VOL_UP);  
4. return true;  
5.     }  
6. else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){  
7.         mCommandService.write(BluetoothCommandService.VOL_DOWN);  
8. return true;  
9.     }  
10.   
11. return super.onKeyDown(keyCode, event);  
12. }  
13. </span>

此外,还需要在AndroidManifest.xml加入打开蓝牙的权限的代码。


[html]  
    
1. <span style="font-size:16px;"> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />  
2. <uses-permission android:name="android.permission.BLUETOOTH" />  
3. </span>

以上就是客户端的代码。

 

将两个程序分别在电脑和手机上安装后,即可实现用手机当作一个PPT遥控器了!

 

参考文献:

http://developer.android.com/guide/topics/wireless/bluetooth.html

http://developer.android.com/resources/samples/BluetoothChat/index.html