Advertisement
moonlightcheese

Untitled

Jun 23rd, 2011
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.34 KB | None | 0 0
  1. package com.moonlightcheese.btsrv;
  2.  
  3. import java.lang.*;
  4. import java.io.*;
  5. import java.util.*;
  6.  
  7. import android.app.*;
  8. import android.os.*;
  9. import android.bluetooth.*;
  10. import android.content.*;
  11. import android.util.Log;
  12.  
  13. //service that dies when completely unbound
  14. public class ScannerService extends Service
  15. {
  16. //instance of the Binder we define in this Service
  17. private final IBinder mBinder = new ScannerBinder();
  18.  
  19. //local variable needed for bluetooth connectivity
  20. BluetoothAdapter btAdapter; //the local Bluetooth adapter
  21. BluetoothDevice mScanner; //the scanner we are connecting to
  22. boolean isDiscoveringLocal = false; //a boolean value that we set/unset to tell if this service initiated discovery, this avoids listing devices if another application initiated the discovery
  23. List<BluetoothDevice> scannerList; //the list of bluetooth scanners found during discovery
  24. public static final UUID BLUETOOTH_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //the UUID. magic.
  25. ReconnectThread mRCT;
  26.  
  27. //message ids and constants
  28. public final static int MESSAGE_BT_READ = 21;
  29. public final static int MESSAGE_SOCKET_ERROR = 22;
  30. public final static int REQUEST_ENABLE_BT = 10;
  31. public final static String ACTION_SELECT_SCANNER = "com.conceptualsystems.scannerservice.selectscanner";
  32. public final static String ACTION_READ_SCANNER = "com.conceptualsystems.scannerservice.readscanner";
  33. public final static String ACTION_REQUEST_RECONNECT = "com.conceptualsystems.scannerservice.request_reconnect";
  34. public final static String ACTION_RECONNECT = "com.conceptualsystems.scannerservice.reconnect";
  35. public final static String LOG_TAG = "btsrv - ScannerService.java";
  36.  
  37. // Class that extends Binder
  38. ////////////////////////////
  39. public class ScannerBinder extends Binder {
  40. ScannerService getService () {
  41. //return this instance
  42. return ScannerService.this;
  43. }
  44. }
  45.  
  46. @Override
  47. public IBinder onBind(Intent intent) {
  48. return mBinder;
  49. }
  50.  
  51. @Override
  52. public void onCreate()
  53. {
  54. super.onCreate();
  55.  
  56. scannerList = new ArrayList<BluetoothDevice>();
  57. }
  58.  
  59. @Override
  60. public void onDestroy() {
  61. super.onDestroy();
  62. unregisterReceiver(mReceiver);
  63. }
  64.  
  65. private class ReconnectThread extends Thread {
  66. //Members
  67. BluetoothDevice mDevice;
  68. BluetoothConnectThread mBCT;
  69.  
  70. //Constructor
  71. public ReconnectThread(BluetoothDevice device) {
  72. this.mDevice=device;
  73. }
  74.  
  75. public void reconnect() {
  76. try {
  77. mBCT = new BluetoothConnectThread(mScanner, btHandler);
  78. mBCT.start();
  79. } catch(Exception e) {
  80. Log.i(LOG_TAG, e.getMessage());
  81. }
  82.  
  83. }
  84.  
  85. public void run() {
  86. //try to reconnect one time
  87. this.reconnect();
  88. //loop until an interrupt has been received
  89. while(true) {
  90. try {
  91. Thread.sleep(1000);
  92. } catch(InterruptedException e) {
  93. return;
  94. }
  95. }
  96. }
  97. }
  98.  
  99. // Create a BroadcastReceiver for ACTION_FOUND, ACTION_STATE_CHANGED, ACTION_DISCOVERY_FINISHED
  100. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  101. public void onReceive(Context context, Intent intent) {
  102. String action = intent.getAction();
  103. if (BluetoothDevice.ACTION_FOUND.equals(action) && isDiscoveringLocal) {
  104. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  105. boolean newEntry = true;
  106. Log.i(LOG_TAG, "found device: "+device.getName());
  107. for(BluetoothDevice storedDevice : scannerList) {
  108. if(device.getAddress().equals(storedDevice.getAddress())) {
  109. newEntry = false;
  110. }
  111. }
  112. if(newEntry) {
  113. scannerList.add(device);
  114. }
  115. }
  116. if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
  117. isDiscoveringLocal = false;
  118. Log.i(LOG_TAG, "discovery finished.");
  119. //TODO: broadcast an intent to interested applications so they can choose the device to use
  120. if(!scannerList.isEmpty()) {
  121. Intent i = new Intent(ACTION_SELECT_SCANNER);
  122. List<String> scannerLabels = new ArrayList<String>(scannerList.size());
  123. for(BluetoothDevice device : scannerList) {
  124. scannerLabels.add(device.getName()+"\n"+device.getBluetoothClass().toString());
  125. }
  126. i.putExtra("scannerArray", scannerLabels.toArray(new String[1]));
  127. sendBroadcast(i);
  128. Log.i(LOG_TAG, "sent broadcast with array elements: " + scannerList.toString());
  129. Log.i(LOG_TAG, "size of scannerList: " + scannerList.size());
  130. Log.i(LOG_TAG, "size of scannerLabels: " + scannerLabels.size());
  131. } else {
  132. Intent i = new Intent(ACTION_SELECT_SCANNER);
  133. sendBroadcast(i);
  134. Log.i(LOG_TAG, "sent broadcast with empty intent (no extras)");
  135. }
  136. }
  137. if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
  138. if(BluetoothAdapter.STATE_ON == btAdapter.getState()) {
  139. initialize(); //make a call to initialize when the adapter turns on to perform the discovery process
  140. }
  141. }
  142. ////////////////////////////
  143. //TODO: may need to rebond sometimes. initiate rebonding if device becomes unpaired here.
  144. if(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
  145. int bondState = -1;
  146. int oldBondState = -1;
  147. BluetoothDevice device = null;
  148. try {
  149. bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
  150. oldBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.BOND_NONE);
  151. device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  152. } catch (Exception e) {
  153. //
  154. }
  155. Log.i(LOG_TAG, "bond state changed.");
  156. Log.i(LOG_TAG, "device name: "+device.getName());
  157. Log.i(LOG_TAG, "device addr: "+device.getAddress());
  158. switch(bondState) {
  159. case BluetoothDevice.BOND_NONE:
  160. Log.i(LOG_TAG, "now unbonded");
  161. break;
  162. case BluetoothDevice.BOND_BONDED:
  163. Log.i(LOG_TAG, "now bonded");
  164. break;
  165. case BluetoothDevice.BOND_BONDING:
  166. Log.i(LOG_TAG, "now bonding");
  167. break;
  168. }
  169. switch(oldBondState) {
  170. case BluetoothDevice.BOND_NONE:
  171. Log.i(LOG_TAG, "was unbonded");
  172. break;
  173. case BluetoothDevice.BOND_BONDED:
  174. Log.i(LOG_TAG, "was bonded");
  175. break;
  176. case BluetoothDevice.BOND_BONDING:
  177. Log.i(LOG_TAG, "was bonding");
  178. break;
  179. }
  180. }
  181. if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
  182. Log.i(LOG_TAG, "connected.");
  183.  
  184. if(mRCT!=null && mRCT.getState() != Thread.State.NEW) {
  185. mRCT.destroy();
  186. }
  187. }
  188. if(BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
  189. Log.i(LOG_TAG, "disconnected.");
  190. //TODO: check the pref stored device in addition to the local, last used device in memory
  191. Intent reconnectIntent = new Intent();
  192. reconnectIntent.setAction(ScannerService.ACTION_REQUEST_RECONNECT);
  193. sendBroadcast(reconnectIntent);
  194. }
  195. if(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
  196. Log.i(LOG_TAG, "disconnect requested.");
  197. }
  198. if(ScannerService.ACTION_RECONNECT.equals(action)) {
  199. if(mScanner!=null) {
  200. mRCT = new ReconnectThread(mScanner);
  201. mRCT.start();
  202. }
  203. }
  204. }
  205. };
  206.  
  207. public void selectBluetoothDevice(int selection) {
  208. //
  209. if(scannerList.isEmpty()) {
  210. //TODO: NullPointerException needs to go here
  211. Log.i(LOG_TAG+":ssbt", "NullPointerException?");
  212. } else {
  213. if(selection > scannerList.size()-1 || selection < 0) {
  214. //TODO: IllegalArgumentException needs to go here
  215. Log.i(LOG_TAG+"ssbt", "IllegalArgumentException");
  216. } else {
  217. //argument should be good, use this selection to select the BluetoothDevice to connect to
  218. mScanner = scannerList.get(selection);
  219. scannerList.clear(); //clear the list after selection
  220. BluetoothConnectThread bct = new BluetoothConnectThread(mScanner, btHandler);
  221. bct.start();
  222. }
  223. }
  224. }
  225.  
  226. public boolean initialize() {
  227. btAdapter = BluetoothAdapter.getDefaultAdapter();
  228. if(btAdapter == null) {
  229. //no bluetooth adapter available. do not run bluetooth code.
  230. return false;
  231. } else {
  232. // Register the BroadcastReceiver
  233. IntentFilter filter = new IntentFilter();
  234. filter.addAction(BluetoothDevice.ACTION_FOUND);
  235. filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
  236. filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
  237. filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
  238. filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
  239. filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
  240. filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
  241. filter.addAction(ScannerService.ACTION_RECONNECT);
  242. //TODO: unregister receiver onDestroy()
  243. registerReceiver(mReceiver, filter);
  244. if(!btAdapter.isEnabled()) { //enable bluetooth if disabled.
  245. btAdapter.enable();
  246. return false;
  247. } else {
  248. isDiscoveringLocal = true;
  249. scannerList.clear();
  250. Log.i(LOG_TAG, "starting discovery process...");
  251. btAdapter.startDiscovery();
  252. }
  253. }
  254. return true;
  255. }
  256.  
  257. private class BluetoothServerThread extends Thread {
  258. private BluetoothServerSocket btServerSocket;
  259.  
  260. public BluetoothServerThread() {
  261. BluetoothServerSocket tmp = null;
  262. try {
  263. tmp = btAdapter.listenUsingRfcommWithServiceRecord("smsmobile", BLUETOOTH_UUID);
  264. } catch (IOException e) {}
  265. btServerSocket = tmp;
  266. }
  267.  
  268. public void run() {
  269. BluetoothSocket socket = null;
  270. while(true) {
  271. try {
  272. socket = btServerSocket.accept();
  273. } catch (IOException e) {
  274. break;
  275. }
  276. if(socket != null) {
  277. BluetoothSocketThread socketThread = new BluetoothSocketThread(socket, btHandler);
  278. socketThread.start();
  279. try {
  280. btServerSocket.close();
  281. } catch (IOException e) {
  282. Log.e(LOG_TAG+":bst", "could not close the server socket? i mean srsly, wtf?");
  283. }
  284. break;
  285. }
  286. }
  287. }
  288.  
  289. public void cancel() {
  290. try {
  291. btServerSocket.close();
  292. } catch (IOException e) {}
  293. }
  294. };
  295.  
  296. private class BluetoothConnectThread extends Thread {
  297. private BluetoothSocket mSocket;
  298. private BluetoothDevice mDevice;
  299. private Handler mHandler;
  300.  
  301. public BluetoothConnectThread(BluetoothDevice device, Handler handler) {
  302. BluetoothSocket tmp = null;
  303. mDevice = device;
  304. mHandler = handler;
  305.  
  306. try {
  307. tmp = device.createRfcommSocketToServiceRecord(BLUETOOTH_UUID);
  308. } catch (IOException e) {
  309. Log.e(LOG_TAG, "could not create rfcomm socket as client");
  310. }
  311.  
  312. mSocket = tmp;
  313. }
  314.  
  315. public synchronized void run() {
  316. btAdapter.cancelDiscovery();
  317. BluetoothSocketThread btsThread = null;
  318. try {
  319. mSocket.connect();
  320. btsThread = new BluetoothSocketThread(mSocket, btHandler);
  321. btsThread.start();
  322. } catch (Exception e) {
  323. if(mSocket == null) {
  324. Log.e(LOG_TAG, "device socket was never initiated, socket is null");
  325. }
  326. Log.e(LOG_TAG, "connection failed");
  327. Log.e(LOG_TAG, e.toString());
  328. Message m = Message.obtain(mHandler, MESSAGE_SOCKET_ERROR);
  329. mHandler.sendMessage(m);
  330. }
  331. }
  332.  
  333. public void cancel() {
  334. try {
  335. mSocket.close();
  336. } catch(IOException e) {
  337. Log.i(LOG_TAG, "client connection closed");
  338. }
  339. }
  340. };
  341.  
  342. private class BluetoothSocketThread extends Thread {
  343. private final BluetoothSocket mSocket;
  344. private final LineNumberReader mInStream;
  345. private final OutputStream mOutStream;
  346. private final Handler mHandler;
  347.  
  348. public BluetoothSocketThread(BluetoothSocket socket, Handler handler) {
  349. mSocket = socket;
  350. LineNumberReader tmpIn = null;
  351. OutputStream tmpOut = null;
  352. mHandler = handler;
  353.  
  354. try {
  355. tmpIn = new LineNumberReader(new InputStreamReader(socket.getInputStream()));
  356. tmpOut = socket.getOutputStream();
  357. } catch(IOException e) {
  358. Log.e(LOG_TAG, "could not capture input/output stream");
  359. //Message m = Message.obtain(mHandler, MESSAGE_SOCKET_ERROR);
  360. //mHandler.sendMessage(m);
  361. }
  362.  
  363. mInStream = tmpIn;
  364. mOutStream = tmpOut;
  365. }
  366.  
  367. public void run() {
  368. //Message m = Message.obtain(mHandler, MESSAGE_SOCKET_SEND, mSocket);
  369. //mHandler.sendMessage(m);
  370. Log.i(LOG_TAG, "socket successfully connected... starting listener loop");
  371. while(true) {
  372. try {
  373. Message m = Message.obtain(mHandler, MESSAGE_BT_READ, mInStream.readLine());
  374. mHandler.sendMessage(m);
  375. } catch(IOException e) {
  376. Log.e(LOG_TAG, "read or handling error");
  377. break;
  378. }
  379. }
  380. }
  381.  
  382. public void write(byte[] bytes) {
  383. try {
  384. mOutStream.write(bytes);
  385. } catch (IOException e) {
  386. Log.e(LOG_TAG+":bst", "write error");
  387. }
  388. }
  389.  
  390. public void cancel() {
  391. try {
  392. mSocket.close();
  393. } catch (IOException e) { }
  394. }
  395. };
  396.  
  397. private final Handler btHandler = new Handler() {
  398. @Override
  399. public void handleMessage(Message msg) {
  400. switch(msg.what) {
  401. case MESSAGE_BT_READ:
  402. //a read was requested
  403. ////broadcast an intent containing the string read from the scanner
  404. Intent i = new Intent(ACTION_READ_SCANNER);
  405. i.putExtra("scannerRead", (String)msg.obj);
  406. sendBroadcast(i);
  407. //Log.i(LOG_TAG+":bth", "read a message" + (String)msg.obj);
  408. break;
  409. case MESSAGE_SOCKET_ERROR:
  410. //error. if the reconnect thread is up and running, attempt a reconnect.
  411. Log.e(LOG_TAG, "a socket error occurred when trying to connect");
  412. if(mRCT!=null) {
  413. Log.i(LOG_TAG, "attempting reconnect...");
  414. mRCT.reconnect();
  415. }
  416. break;
  417. }
  418. }
  419. };
  420. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement