Android之藍牙 一個簡單實用的Android藍牙程序實例

作者:   張奇

       我將在這篇文章中介紹了的Android藍牙程序。這個程序就是將實現把手機變做電腦PPT播放的遙控器:用音量加和音量減鍵來控制PPT頁面的切換。

遙控器服務器端

首先,我們需要編寫一個遙控器的服務器端(支持藍牙的電腦)來接收手機端發出的信號。爲了實現這個服務器端,我用到了一個叫做Bluecove(專門用來爲藍牙服務的!)的Java庫。

以下是我的RemoteBluetoothServer類:

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

在主方法中創建了一個線程,用於連接客戶端,並處理信號。


[java] view plain copy
  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.         LocalDevice local = null;  
  16.   
  17.         StreamConnectionNotifier notifier;  
  18.         StreamConnection connection = null;  
  19.   
  20.         // setup the server to listen for connection  
  21.         try {  
  22.             local = LocalDevice.getLocalDevice();  
  23.             local.setDiscoverable(DiscoveryAgent.GIAC);  
  24.   
  25.             UUID uuid = new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"  
  26.             String url = "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.                 System.out.println("waiting for connection...");  
  36.                         connection = notifier.acceptAndOpen();  
  37.   
  38.                 Thread processThread = 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] view plain copy
  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.             System.out.println("waiting for input");  
  22.   
  23.             while (true) {  
  24.                 int command = inputStream.read();  
  25.   
  26.                 if (command == EXIT_CMD)  
  27.                 {  
  28.                     System.out.println("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.             Robot robot = new Robot();  
  45.             switch (command) {  
  46.                 case KEY_RIGHT:  
  47.                     robot.keyPress(KeyEvent.VK_RIGHT);  
  48.                     System.out.println("Right");  
  49.                     break;  
  50.                 case KEY_LEFT:  
  51.                     robot.keyPress(KeyEvent.VK_LEFT);  
  52.                     System.out.println("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] view plain copy
  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.         Intent enableIntent = 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.         mCommandService = new BluetoothCommandService(this, mHandler);  
  20. }  
  21. </span>  


onStart()用於檢查手機上的藍牙是否已經打開,如果沒有打開則創建一個Intent來打開藍牙。setupCommand()用於在按下音量加或音量減鍵時向服務器發送命令。其中用到了onKeyDown事件:


[java] view plain copy
  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] view plain copy
  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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章