2012年10月26日 星期五

Java Bluetooth 程式開發入門

Java Bluetooth 程式開發入門

This document is provided as is. Use it at your own risks. You are, however, welcomed to use it for educational, non-commercial purpose.
Written by: 國立中興大學資管系呂瑞麟

請勿轉貼
看其他教材

目錄

  1. 藍芽簡介
  2. 開發環境簡介
  3. 程式開發
    1. LocalDevice 的查詢
    2. RemoteDevice 的查詢
    3. 利用 RFCOMM 來交換訊息
    4. 利用 L2CAP 來交換訊息
    5. 利用 OBEX 來傳送檔案

藍芽簡介

Under Construction

開發環境簡介

這一節的說明主要是針對 Linux 的環境,或者更嚴格的說是我還沒有發現 Blue Cove 以前的測試環境。現在 Windows XP SP2 之後已經支援藍芽的驅動程式, 再加上 Blue Cove 以及藍芽設備,你就可以開始開發了。不過,我還是把 以下的說明留下來當參考用。
  1. 兩部安裝了 Linux 的電腦,請確定這個版本的 Linux 內建支援 BlueZ。 我們用的是 Fedora Core 1,你也可以參考 窮人的 Java Bluetooth 開發環境之建置 來建置你的開發環境。
  2. 依照 BlueZ 硬體相容清單 去 採購你的藍芽裝置. 我用的是別人幫我買的 X-Micro 的 Bluetooth USB Dongle. 雖然這個設備並未出現在相容清單內,但是目前 為止使用上都還蠻順利的。你可以在環境架好了以後,再去購買,如果發現不相容 可以馬上退貨。
  3. Linux 環境安裝有 J2SDK 1.4.x (or later) 以及 Rococo Software's Impronto Developer Kit for Linux.
  4. 安裝至少 bluez-libs 和 bluez-utils 套件。
  5. 請在兩部電腦上都利用以下指令來確定你的環境是正確的(# 為註解)
    hciconfig -a                    #來確定你的藍芽裝置是正常運作的
    hcitool scan                    #來確定遠端的藍芽裝置是正常運作的
                                    #假設遠端的藍芽裝置是 00:02:72:01:83:E0
    hcitool info 00:02:72:01:83:E0  #來確定兩部藍芽裝置可以互相連線的
    
  6. 注意: 我發現如果 hcitool info 00:02:72:01:83:E0 出現 Input/Output Error,這可能是你的藍芽裝置的設定需求是要求 auth and encrypt,而 hcitool 是以 noauth and noencrypt 的方式來進行 (跟我們以下的範例程式相同),你可以用以下的指令來取消設定
    hciconfig hci0 noauth
    hciconfig hci0 noencrypt
    
    如果要永久的更改,你必須把 /etc/bluetooth/hcid.conf
    # Authentication and Encryption
    auth enable;
    encrypt enable;
    
    改成
    # Authentication and Encryption
    auth disable;
    encrypt disable;
    
    必且執行 /etc/init.d/bluetooth restart.

程式開發

  1. LocalDevice 的查詢
    1. LocalInfo.java
      import java.io.*;
      import javax.bluetooth.*;
      
      public class LocalInfo
      {
        public static void main(String args[]) throws BluetoothStateException {
          LocalDevice localdev = null;
      
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          System.out.println("a local bluetooth device is found:");
          System.out.println("   Name: " + localdev.getFriendlyName());
          System.out.println("Address: " + localdev.getBluetoothAddress());
      
          System.out.println("\nIts device classes are:");
          DeviceClass devcla = localdev.getDeviceClass();
          System.out.println(devcla.toString());
          System.out.println("Service Class: " + devcla.getServiceClasses());
          System.out.println("Major Device Class: " + devcla.getMajorDeviceClass());
          System.out.println("Minor Device Class: " + devcla.getMinorDeviceClass());
        }
      }
        
  2. RemoteDevice 的查詢
    1. RemoteInfo.java
      import java.io.*;
      import javax.bluetooth.*;
      
      public class RemoteInfo
      {
        public static void main(String args[]) throws BluetoothStateException
        {
          LocalDevice localdev = null;
          MyListener listener = new MyListener();
      
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          DiscoveryAgent agent = localdev.getDiscoveryAgent();
          try {
            agent.startInquiry(DiscoveryAgent.GIAC, listener);
          } catch (BluetoothStateException e) {
            System.out.println("Device unable to inquiry");
            System.exit(2);
          }
        }
      }
      
    2. MyListener.java
      //
      // a Lisntener class that implements DiscoveryListener
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class MyListener implements DiscoveryListener
      {
        private RemoteDevice remote = null;
      
        // 當藍芽裝置發現遠端有藍芽裝置,就會自動呼叫(依照順序)
        // deviceDiscovered() and then inquiryCompleted()
        public void deviceDiscovered(RemoteDevice rt, DeviceClass cod) {
          remote = rt;
          System.out.println("A Remote Device Found:");
          System.out.println("Address: " + rt.getBluetoothAddress());
          try {
            System.out.println("   Name: " + rt.getFriendlyName(true));
          } catch (IOException e) {}
        }
      
        public void inquiryCompleted(int distype) {
          if(distype == INQUIRY_TERMINATED)
            System.out.println("Application Terminated");
          else if(distype == INQUIRY_COMPLETED)
            System.out.println("Inquiry Completed");
          else
            System.out.println("ERROR: Inquiry aborted");
        }
      
        public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
        }
      
        public void serviceSearchCompleted(int transID, int respCode) {
        }
      }
      
    3. 我們也可以將 RemoteInfo 和 MyListener 結合成一個 class,底下的 RemoteOne.java 說明這個做法。
      //
      // Query remote device's information.
      // Combine client and DiscoveryListener into one class
      // compare this program with RemoteInfo and MyListener
      // Advantage: main() can use queried remote device directly
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class RemoteOne implements DiscoveryListener
      {
        public static void main(String args[]) throws BluetoothStateException
        {
          LocalDevice localdev = null;
          RemoteOne listener = new RemoteOne();
      
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          DiscoveryAgent agent = localdev.getDiscoveryAgent();
          try {
            agent.startInquiry(DiscoveryAgent.GIAC, listener);
          } catch (BluetoothStateException e) {
            System.out.println("Device unable to inquiry");
            System.exit(2);
          }
        }
      
        // implement required methods.
        private RemoteDevice remote = null;
      
        public void deviceDiscovered(RemoteDevice rt, DeviceClass cod) {
          remote = rt;
          System.out.println("A Remote Device Found:");
          System.out.println("Address: " + rt.getBluetoothAddress());
          try {
            System.out.println("   Name: " + rt.getFriendlyName(true));
          } catch (IOException e) {}
        }
      
        public void inquiryCompleted(int distype) {
          if(distype == INQUIRY_TERMINATED)
            System.out.println("Application Terminated");
          else if(distype == INQUIRY_COMPLETED)
            System.out.println("Inquiry Completed");
          else
            System.out.println("ERROR: Inquiry aborted");
        }
      
        public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
        }
      
        public void serviceSearchCompleted(int transID, int respCode) {
        }
      }
        
  3. 利用 RFCOMM 來交換訊息:RFListener.java 和 RFDateClient.java 在同一部 電腦執行,而 RFDateServ.java 再另一部電腦執行。一般來說,程式的執行過程 需要先將 server 端的 service 實作出來,然後將該 service 跟 server 登記並 發布,因此你必須先執行 RFDateServ。等到 service 發布後,你就 執行 RFDateClient 讓 client 經由 searchServices() 發現 service 並與 service 取得連接。
    1. RFListener.java
      //
      // a Lisntener class that implements DiscoveryListener
      // From a source code published in Benhui.net claimes that
      // Impronto prefers to have a Lisntener class.
      // conn: RFCOMM
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class RFListener implements DiscoveryListener
      {
        private static RemoteDevice remote;
        private static ServiceRecord first;
      
        public RemoteDevice getDevFound() {
          return remote;
        }
      
        public void deviceDiscovered(RemoteDevice rt, DeviceClass cod) {
          remote = rt;
          System.out.println("A Remote Device Found:");
          System.out.println("Address: " + rt.getBluetoothAddress());
          try {
            System.out.println("   Name: " + rt.getFriendlyName(true));
          } catch (IOException e) {}
        }
      
        public void inquiryCompleted(int distype) {
          if(distype == INQUIRY_TERMINATED)
            System.out.println("Application Terminated");
          else if(distype == INQUIRY_COMPLETED)
            System.out.println("Inquiry Completed");
          else
            System.out.println("ERROR: Inquiry aborted");
        }
      
        // 當裝置從遠端的藍芽裝置發現該裝置上有服務的時候,會先呼叫
        // servicesDiscovered() 然後 serviceSearchCompleted()
        public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
          first = servRecord[0];
      
          // 從 service record 來取得 url
          String url = first.getConnectionURL(first.NOAUTHENTICATE_NOENCRYPT, false);
          try {
            // 與 server 建立連線
            StreamConnection conn = (StreamConnection) Connector.open(url);
      
            String message = "What time is it now?";
            InputStream is = conn.openInputStream();
            OutputStream os = conn.openOutputStream();
            byte[] rbuf = new byte[100];
            os.write(message.getBytes());
            is.read(rbuf);
            System.out.println(new String(rbuf));
            is.close();
            os.close();
            conn.close();
          } catch (Exception e) {
            System.out.println("ERROR: connection error");
          }
        }
      
        public void serviceSearchCompleted(int transID, int respCode) {
          // 依照 respCode 來了解 serviceSearch 的結果
          if(respCode == SERVICE_SEARCH_COMPLETED)
            System.out.println("Services successfully located");
          else if(respCode == SERVICE_SEARCH_TERMINATED)
            System.out.println("Service inquiry was cancelled");
          else if(respCode == SERVICE_SEARCH_DEVICE_NOT_REACHABLE)
            System.out.println("Service connection cannot be established");
          else if(respCode == SERVICE_SEARCH_NO_RECORDS)
            System.out.println("No service found");
          else
            System.out.println("ERROR: service inquiry failed");
        }
      }
        
    2. RFDateClient.java
      //
      // a Client to request Date/Time from server
      // connection: RFCOMM
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class RFDateClient
      {
        public static void main(String args[]) throws BluetoothStateException
        {
          LocalDevice localdev = null;
          RFListener listener = new RFListener();
      
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          DiscoveryAgent agent = localdev.getDiscoveryAgent();
          try {
            // startInquiry() is non-blocking.
            agent.startInquiry(DiscoveryAgent.GIAC, listener);
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: device inquiry failed");
            System.exit(2);
          }
      
          // pause for a while
          while (listener.getDevFound() == null)
            try {
              Thread.sleep(5000);
            } catch (Exception e) {}
          RemoteDevice rd = listener.getDevFound();
      
          // UUID 還得多研究一下
          UUID[] uuidSet = new UUID[1];
          uuidSet[0] = new UUID("102030405060708090A0B0C0D0E0F011", false);
      
          int trans;
          try {
            // 對遠端藍芽裝置 rd 查詢服務
            trans = agent.searchServices(null, uuidSet, rd, listener);
          } catch (BluetoothStateException e) {
            System.out.println("device unable to begin service inquiry");
          }
        }
      }
        
    3. RFDateServ.java
      //
      // a Date/Time server
      // conn: RFCOMM
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      import java.util.*;
      
      public class RFDateServ
      {
        public static void main(String args[])
        {
          LocalDevice localdev = null;
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          // show an example usage of getProperty.
          //System.out.println("MTU: " + localdev.getProperty(
          //                   "bluetooth.l2cap.receiveMTU.max"));
      
          UUID uuid = new UUID("102030405060708090A0B0C0D0E0F011", false);
          String url = "btspp://localhost:" + uuid.toString();
      
          try {
            // 1. create service record
            StreamConnectionNotifier n = (StreamConnectionNotifier) Connector.open(url);
      
            // 2. obtain the service record
            // set ServiceRecrod ServiceAvailability (0x0008) attribute to
            // indicate our service is available
            // 0xFF indicate fully available status
            // This operation is optional
            ServiceRecord record = localdev.getRecord(n);
            record.setAttributeValue( 0x0008, new DataElement( DataElement.U_INT_1,0xF
      F ) );
      
            System.out.println("Waiting to be connected...");
      
            // 3.ready to accept connection: will block until a client connects
            StreamConnection conn = n.acceptAndOpen();
      
            // send and receive data
            String message = new Date().toString();
            InputStream is = conn.openInputStream();
            OutputStream os = conn.openOutputStream();
            os.write(message.getBytes());
            byte[] rbuf = new byte[100];
            is.read(rbuf);
            System.out.println("Received: " + new String(rbuf));
            is.close();
            os.close();
            conn.close();
          } catch (Exception e) {
            System.out.println("ERROR: connection failed.");
          }
        }
      }
        
    4. 相同的,我們也提供一個將 client 與 listener 包起來的範例,其他的 就讓讀者自己去試試看。
      //
      // a Client to request Date/Time from server
      // connection: RFCOMM
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class RFClientOne implements DiscoveryListener
      {
        public static void main(String args[]) throws BluetoothStateException
        {
          LocalDevice localdev = null;
          RFClientOne listener = new RFClientOne();
      
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          DiscoveryAgent agent = localdev.getDiscoveryAgent();
          try {
            // startInquiry() is non-blocking.
            agent.startInquiry(DiscoveryAgent.GIAC, listener);
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: device inquiry failed");
            System.exit(2);
          }
      
          // pause for a while
          // NOTE: if there is no remote device, this may go into infinite loop
          // this program also shows that to start services from a client it's
          // better to have a GUI interface.
          while (remote == null)
            try {
              Thread.sleep(5000);
            } catch (Exception e) {}
      
          UUID[] uuidSet = new UUID[1];
          uuidSet[0] = new UUID("102030405060708090A0B0C0D0E0F011", false);
      
          int trans;
          try {
            trans = agent.searchServices(null, uuidSet, remote, listener);
          } catch (BluetoothStateException e) {
            System.out.println("device unable to begin service inquiry");
          }
        }
      
        // implement required listener methods.
        private static RemoteDevice remote = null;
        private static ServiceRecord first = null;
      
        public void deviceDiscovered(RemoteDevice rt, DeviceClass cod) {
          remote = rt;
          System.out.println("A Remote Device Found:");
          System.out.println("Address: " + rt.getBluetoothAddress());
          try {
            System.out.println("   Name: " + rt.getFriendlyName(true));
          } catch (IOException e) {}
        }
      
        public void inquiryCompleted(int distype) {
          if(distype == INQUIRY_TERMINATED)
            System.out.println("Application Terminated");
          else if(distype == INQUIRY_COMPLETED)
            System.out.println("Inquiry Completed");
          else
            System.out.println("ERROR: Inquiry aborted");
        }
      
        public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
          first = servRecord[0];
      
          String url = first.getConnectionURL(first.NOAUTHENTICATE_NOENCRYPT, false);
          try {
            StreamConnection conn = (StreamConnection) Connector.open(url);
            String message = "What time is it now?";
            InputStream is = conn.openInputStream();
            OutputStream os = conn.openOutputStream();
            byte[] rbuf = new byte[100];
            os.write(message.getBytes());
            is.read(rbuf);
            System.out.println(new String(rbuf));
            is.close();
            os.close();
            conn.close();
          } catch (Exception e) {
            System.out.println("ERROR: connection error");
          }
        }
      
        public void serviceSearchCompleted(int transID, int respCode) {
          if(respCode == SERVICE_SEARCH_COMPLETED)
            System.out.println("Services successfully located");
          else if(respCode == SERVICE_SEARCH_TERMINATED)
            System.out.println("Service inquiry was cancelled");
          else if(respCode == SERVICE_SEARCH_DEVICE_NOT_REACHABLE)
            System.out.println("Service connection cannot be established");
          else if(respCode == SERVICE_SEARCH_NO_RECORDS)
            System.out.println("No service found");
          else
            System.out.println("ERROR: service inquiry failed");
        }
      }
        
  4. 利用 L2CAP 來交換訊息
    1. L2Listener.java
      //
      // a Lisntener class that implements DiscoveryListener
      // From a source code published in Benhui.net claimes that
      // Impronto prefers to have a Lisntener class.
      // conn: L2CAP
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class L2Listener implements DiscoveryListener
      {
        private static RemoteDevice remote;
        private static ServiceRecord first;
      
        public RemoteDevice getDevFound() {
          return remote;
        }
      
        public void deviceDiscovered(RemoteDevice rt, DeviceClass cod) {
          remote = rt;
          System.out.println("A Remote Device Found:");
          System.out.println("Address: " + rt.getBluetoothAddress());
          try {
            System.out.println("   Name: " + rt.getFriendlyName(true));
          } catch (IOException e) {}
        }
      
        public void inquiryCompleted(int distype) {
          if(distype == INQUIRY_TERMINATED)
            System.out.println("Application Terminated");
          else if(distype == INQUIRY_COMPLETED)
            System.out.println("Inquiry Completed");
          else
            System.out.println("ERROR: Inquiry aborted");
        }
      
        public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
          first = servRecord[0];
      
          // 需增加 url += ";ReceiveMTU=512;TransmitMTU=512";
          String url = first.getConnectionURL(first.NOAUTHENTICATE_NOENCRYPT, false);
          url += ";ReceiveMTU=512;TransmitMTU=512";
          try {
            L2CAPConnection conn = (L2CAPConnection) Connector.open(url);
            String message = "Hello Server";
            int is = conn.getReceiveMTU();
            int os = conn.getTransmitMTU();
            byte[] rbuf = new byte[is];
            conn.send(message.getBytes());
            conn.receive(rbuf);
            System.out.println("Received: " + new String(rbuf));
            conn.close();
          } catch (Exception e) {
            System.out.println("ERROR: connection error");
          }
        }
      
        public void serviceSearchCompleted(int transID, int respCode) {
          if(respCode == SERVICE_SEARCH_COMPLETED)
            System.out.println("Services successfully located");
          else if(respCode == SERVICE_SEARCH_TERMINATED)
            System.out.println("Service inquiry was cancelled");
          else if(respCode == SERVICE_SEARCH_DEVICE_NOT_REACHABLE)
            System.out.println("Service connection cannot be established");
          else if(respCode == SERVICE_SEARCH_NO_RECORDS)
            System.out.println("No service found");
          else
            System.out.println("ERROR: service inquiry failed");
        }
      }
        
    2. DateClient.java
      //
      // a Client to request Date/Time from server
      // connection: L2CAP
      // usage: you can use l2ping to check if the connection is up and running.
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class DateClient
      {
        public static void main(String args[]) throws BluetoothStateException
        {
          LocalDevice localdev = null;
          L2Listener listener = new L2Listener();
      
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          DiscoveryAgent agent = localdev.getDiscoveryAgent();
          try {
            // startInquiry() is non-blocking.
            agent.startInquiry(DiscoveryAgent.GIAC, listener);
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: device inquiry failed");
            System.exit(2);
          }
      
          // pause for a while
          while (listener.getDevFound() == null)
            try {
              Thread.sleep(5000);
            } catch (Exception e) {}
          RemoteDevice rd = listener.getDevFound();
      
          UUID[] uuidSet = new UUID[1];
          uuidSet[0] = new UUID("102030405060708090A0B0C0D0E0F011", false);
      
          int trans;
          try {
            trans = agent.searchServices(null, uuidSet, rd, listener);
          } catch (BluetoothStateException e) {
            System.out.println("device unable to begin service inquiry");
          }
        }
      }
        
    3. DateServ.java
      import java.io.*;
      import javax.bluetooth.*;
      import javax.microedition.io.*;
      
      public class DateServ
      {
        public static void main(String args[])
        {
          // Since no service record is needed, LocalDevice is not needed.
      
          // for L2CAP, protocol name btl2cap is used.
          UUID uuid = new UUID("102030405060708090A0B0C0D0E0F011", false);
          String url = "btl2cap://localhost:" + uuid.toString() +";ReceiveMTU=512;Tran
      smitMTU=512";
      
          try {
            // 1. create service record
            L2CAPConnectionNotifier n = (L2CAPConnectionNotifier) Connector.open(url);
      
            System.out.println("Waiting to be connected...");
      
            // 3.ready to accept connection: will block until a client connects
            L2CAPConnection conn = n.acceptAndOpen();
      
            // send and receive data
            String message = "Hello World";
            int is = conn.getReceiveMTU();
            int os = conn.getTransmitMTU();
            conn.send(message.getBytes());
            byte[] rbuf = new byte[is];
            conn.receive(rbuf);
            System.out.println("Received: " + new String(rbuf));
            conn.close();
          } catch (Exception e) {
            System.out.println("ERROR: connection failed.");
          }
        }
      }
        
  5. 利用 OBEX 來傳送檔案 The Object Exchange (OBEX) protocol 允許客戶端程式利用 pull (onGet()) 或者 push (onPut())的方式來下載或者上傳檔案,在以下的範例中, 我們展示如何從 server 端下載一個 XML 的檔案到客戶端。
    1. OBEXServ.java
      //
      // a simple file server
      // conn: OBEX
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.obex.*;
      import javax.microedition.io.*;
      
      public class OBEXServ extends ServerRequestHandler
      {
        // override onGet() in ServerRequestHandler
        public int onGet(Operation op) {
          try {
            HeaderSet headers = op.getReceivedHeaders();
      
            // receive the name of the file requested by clients
            String fname = (String) headers.getHeader(HeaderSet.NAME);
            DataOutputStream os = op.openDataOutputStream();
      
            DataInputStream is = new DataInputStream(
                                 new FileInputStream(fname));
      /*
            // the following two lines are from RocoSoft User Guide
            // 還搞不清楚為什麼手冊要這樣子寫?
            InputConnection fconn = (InputConnection) Connector.open(fname);
            DataInputStream is = fconn.openDataInputStream();
      */
      
            // confirm file name with clients
            HeaderSet rephead = createHeaderSet();
            rephead.setHeader(HeaderSet.NAME, fname);
            op.sendHeaders(rephead);
      
            // send the file to the client
            int data;
            while((data = is.read()) != -1) {
              os.write((byte) data);
            }
      
            is.close();
            os.close();
            op.close();
          } catch (IOException e) {
            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
          }
      
          return ResponseCodes.OBEX_HTTP_OK;
        }
      
        public static void main(String args[]) {
          // create a request handler
          OBEXServ handler = new OBEXServ();
      
          UUID uuid = new UUID("102030405060708090A0B0C0D0E0F011", false);
          String url = "btgoep://localhost:" + uuid.toString();
      
          try {
            // 1. create service record
            SessionNotifier n = (SessionNotifier) Connector.open(url);
      
            System.out.println("Waiting to be connected...");
      
            // 3.ready to accept connection: will block until a client connects
            n.acceptAndOpen(handler);
            // send and receive data is now covered by onGet() or onPut()
      
          } catch (Exception e) {
            System.out.println("ERROR: connection failed.");
          }
        }
      }
        
    2. OBEXClient.java
      //
      // a Client to request file from server
      // connection: OBEX
      //
      
      import java.io.*;
      import javax.bluetooth.*;
      import javax.obex.*;
      import javax.microedition.io.*;
      
      public class OBEXClient implements DiscoveryListener
      {
        public static void main(String args[]) throws BluetoothStateException
        {
          LocalDevice localdev = null;
          OBEXClient listener = new OBEXClient();
      
          try {
            localdev = LocalDevice.getLocalDevice();
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: cannot access local device");
            System.exit(1);
          }
      
          DiscoveryAgent agent = localdev.getDiscoveryAgent();
          try {
            agent.startInquiry(DiscoveryAgent.GIAC, listener);
          } catch (BluetoothStateException e) {
            System.out.println("ERROR: device inquiry failed");
            System.exit(2);
          }
      
          // pause for a while
          // NOTE: if there is no remote device, this may go into infinite loop
          // this program also shows that to start services from a client it's
          // better to have a GUI interface.
          while (remote == null)
            try {
              Thread.sleep(5000);
            } catch (Exception e) {}
      
          UUID[] uuidSet = new UUID[1];
          uuidSet[0] = new UUID("102030405060708090A0B0C0D0E0F011", false);
      
          int trans;
          try {
            trans = agent.searchServices(null, uuidSet, remote, listener);
          } catch (BluetoothStateException e) {
            System.out.println("device unable to begin service inquiry");
          }
        }
      
        // implement required listener methods.
        private static RemoteDevice remote = null;
        private static ServiceRecord first = null;
      
        public void deviceDiscovered(RemoteDevice rt, DeviceClass cod) {
          remote = rt;
          System.out.println("A Remote Device Found:");
          System.out.println("Address: " + rt.getBluetoothAddress());
          try {
            System.out.println("   Name: " + rt.getFriendlyName(true));
          } catch (IOException e) {}
        }
      
        public void inquiryCompleted(int distype) {
          if(distype == INQUIRY_TERMINATED)
            System.out.println("Application Terminated");
          else if(distype == INQUIRY_COMPLETED)
            System.out.println("Inquiry Completed");
          else
            System.out.println("ERROR: Inquiry aborted");
        }
      
        public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
          first = servRecord[0];
      
          String url = first.getConnectionURL(first.NOAUTHENTICATE_NOENCRYPT, false);
          try {
            ClientSession conn = (ClientSession) Connector.open(url);
      
            // check to see if OBEX connection is successful
            HeaderSet reshead = conn.connect(null);
            int status = reshead.getResponseCode();
            if(status != ResponseCodes.OBEX_HTTP_OK) {
              System.out.println("OBEX connection error!!");
              System.exit(1);
            }
      
            System.out.println("Getting object from server");
      
            // get object from server
            HeaderSet headset = conn.createHeaderSet();
            headset.setHeader(HeaderSet.NAME, "test.xml");
            Operation op = conn.get(headset);
            InputStream is = op.openInputStream();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
      
            System.out.println("Reading data from server");
      
            // read data from server
            int data;
            while((data = is.read()) != -1)
              os.write((byte) data);
            System.out.println("Size: " + os.size());
            System.out.println(os.toString());
      
            // Although this is not necessary required, but if this is not inserted,
            // I got IO error. And this type of IO error requires some hardware
            // reset.
            Thread.sleep(5000);
      
            is.close();
            os.close();
            conn.close();
          } catch (Exception e) {
            System.out.println("ERROR: connection error");
          }
        }
      
        public void serviceSearchCompleted(int transID, int respCode) {
          if(respCode == SERVICE_SEARCH_COMPLETED)
            System.out.println("Services successfully located");
          else if(respCode == SERVICE_SEARCH_TERMINATED)
            System.out.println("Service inquiry was cancelled");
          else if(respCode == SERVICE_SEARCH_DEVICE_NOT_REACHABLE)
            System.out.println("Service connection cannot be established");
          else if(respCode == SERVICE_SEARCH_NO_RECORDS)
            System.out.println("No service found");
          else
            System.out.println("ERROR: service inquiry failed");
        }
      }
        




Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu

沒有留言:

張貼留言