Pages

Subscribe:

Ads 468x60px

Labels

2013年6月3日 星期一

Android Bluetooth API 使用心得筆記

1.Bluetooth基本概念
可以參考BlueCove這個實作JSR82的Project,裡面的這張圖對Bluetooth解說很清楚,可供參考。

Bluetooth Stack的部份在不同系統、程式語言上都是相同的,會有差異的只有頂層的Abstract API。

若想對Bluetooth整體軟硬体有仔細的了解可以參考「Bluetooth Application Programming with the Java APIs Essentials Edition」這本書。

2.Android Bluetooth開發基本需求
Android SDK 2.0以上(含2.0)版本。
支援Android 2.0的手機一隻(Android Emulater無法模擬Bluetooth,所以一定要有實體手機)。

3.實作參考文件
http://developer.android.com/guide/topics/wireless/bluetooth.html
http://www.anddev.org/serial_over_bluetooth_simple_test_client-t11106.html

一般來說,我們只會實作Bluetooth Client的程式去跟其它的Bluetooth硬體溝通取資料。連線方式大多是利用Serial Port Service方式去跟遠端的裝置溝通,所以相對應的UUID不能設錯,一定要設成下述範例這組UUID,不然會發生找不到Service的問題(附帶一提,這是假設一般遠端裝置有提供Serial Port Service,所以你才可以用這組UUID來進行通訊,如果遠端裝置比較特別就要去查硬體規格去看它提供的Service是哪些,找出對應的UUID)。

1
private static final UUID SERIAL_PORT_SERVICE_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");


4.Android Bluetooth API目前的限制
目前只支援RFCOMM的方式進行通訊

5.實作參考範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// 取自http://www.anddev.org/serial_over_bluetooth_simple_test_client-t11106.html裡的範例
package  com.example.thinbtclient;
 
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
 
public class ThinBTClient extends Activity {
     
     private static final String TAG = "THINBTCLIENT";
     private static final boolean D = true;
     private BluetoothAdapter mBluetoothAdapter = null;
     private BluetoothSocket btSocket = null;
     private OutputStream outStream = null;
     // Well known SPP UUID (will *probably* map to
     // RFCOMM channel 1 (default) if not in use);
     // see comments in onResume().
     private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
 
     // ==> hardcode your server's MAC address here <==
     private static String address = "XX:XX:XX:XX:XX:XX";
 
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
 
          if (D)
               Log.e(TAG, "+++ ON CREATE +++");
 
          mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
          if (mBluetoothAdapter == null) {
               Toast.makeText(this,
                    "Bluetooth is not available.",
                    Toast.LENGTH_LONG).show();
               finish();
               return;
          }
 
          if (!mBluetoothAdapter.isEnabled()) {
               Toast.makeText(this,
                    "Please enable your BT and re-run this program.",
                    Toast.LENGTH_LONG).show();
               finish();
               return;
          }
 
          if (D)
               Log.e(TAG, "+++ DONE IN ON CREATE, GOT LOCAL BT ADAPTER +++");
     }
 
     @Override
     public void onStart() {
          super.onStart();
          if (D)
               Log.e(TAG, "++ ON START ++");
     }
 
     @Override
     public void onResume() {
          super.onResume();
 
          if (D) {
               Log.e(TAG, "+ ON RESUME +");
               Log.e(TAG, "+ ABOUT TO ATTEMPT CLIENT CONNECT +");
          }
 
          // When this returns, it will 'know' about the server,
          // via it's MAC address.
          BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
 
          // We need two things before we can successfully connect
          // (authentication issues aside): a MAC address, which we
          // already have, and an RFCOMM channel.
          // Because RFCOMM channels (aka ports) are limited in
          // number, Android doesn't allow you to use them directly;
          // instead you request a RFCOMM mapping based on a service
          // ID. In our case, we will use the well-known SPP Service
          // ID. This ID is in UUID (GUID to you Microsofties)
          // format. Given the UUID, Android will handle the
          // mapping for you. Generally, this will return RFCOMM 1,
          // but not always; it depends what other BlueTooth services
          // are in use on your Android device.
          try {
               btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
          } catch (IOException e) {
               Log.e(TAG, "ON RESUME: Socket creation failed.", e);
          }
 
          // Discovery may be going on, e.g., if you're running a
          // 'scan for devices' search from your handset's Bluetooth
          // settings, so we call cancelDiscovery(). It doesn't hurt
          // to call it, but it might hurt not to... discovery is a
          // heavyweight process; you don't want it in progress when
          // a connection attempt is made.
          mBluetoothAdapter.cancelDiscovery();
 
          // Blocking connect, for a simple client nothing else can
          // happen until a successful connection is made, so we
          // don't care if it blocks.
          try {
               btSocket.connect();
               Log.e(TAG, "ON RESUME: BT connection established, data transfer link open.");
          } catch (IOException e) {
               try {
                    btSocket.close();
               } catch (IOException e2) {
                    Log.e(TAG,"ON RESUME: Unable to close socket during connection failure", e2);
               }
          }
 
          // Create a data stream so we can talk to server.
          if (D)
               Log.e(TAG, "+ ABOUT TO SAY SOMETHING TO SERVER +");
 
          try {
               outStream = btSocket.getOutputStream();
          } catch (IOException e) {
               Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
          }
 
          String message = "Hello message from client to server.";
          byte[] msgBuffer = message.getBytes();
          try {
               outStream.write(msgBuffer);
          } catch (IOException e) {
               Log.e(TAG, "ON RESUME: Exception during write.", e);
          }
     }
 
     @Override
     public void onPause() {
          super.onPause();
 
          if (D)
               Log.e(TAG, "- ON PAUSE -");
 
          if (outStream != null) {
               try {
                    outStream.flush();
               } catch (IOException e) {
                    Log.e(TAG, "ON PAUSE: Couldn't flush output stream.", e);
               }
          }
 
          try  {
               btSocket.close();
          } catch (IOException e2) {
               Log.e(TAG, "ON PAUSE: Unable to close socket.", e2);
          }
     }
 
     @Override
     public void onStop() {
          super.onStop();
          if (D)
               Log.e(TAG, "-- ON STOP --");
     }
 
     @Override
     public void onDestroy() {
          super.onDestroy();
          if (D)
               Log.e(TAG, "--- ON DESTROY ---");
     }
}
 
AndroidManifest.xml裡的Permission設定加下述二行
"android.permission.BLUETOOTH_ADMIN"
/> "android.permission.BLUETOOTH" />

Android SDK 2.1裡的Bluetooh Sample (在 x:/android sdk安裝目錄/platforms/android-2.1/samples/BluetoothChat 裡面,或是到 http://developer.android.com/resources/samples/BluetoothChat/index.html 看範例,二者是一樣的東西)

http://code.google.com/p/apps-for-android/ 裡面有個 BTClickLinkCompete Sample,可經由SVN去下載回來看 


資料來源

沒有留言:

張貼留言