BluetoothSync.java 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. package de.tudarmstadt.informatik.hostage.sync;
  2. import java.io.IOException;
  3. import java.io.ObjectInputStream;
  4. import java.io.ObjectOutputStream;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.UUID;
  8. import android.app.AlertDialog;
  9. import android.bluetooth.BluetoothAdapter;
  10. import android.bluetooth.BluetoothDevice;
  11. import android.bluetooth.BluetoothServerSocket;
  12. import android.bluetooth.BluetoothSocket;
  13. import android.content.BroadcastReceiver;
  14. import android.content.Context;
  15. import android.content.DialogInterface;
  16. import android.content.Intent;
  17. import android.content.IntentFilter;
  18. import android.widget.ArrayAdapter;
  19. import de.tudarmstadt.informatik.hostage.R;
  20. import de.tudarmstadt.informatik.hostage.persistence.HostageDBOpenHelper;
  21. public class BluetoothSync {
  22. private class ClientThread extends Thread {
  23. private final BluetoothSocket socket;
  24. public ClientThread(BluetoothDevice device) {
  25. BluetoothSocket tmp = null;
  26. try {
  27. tmp = device.createRfcommSocketToServiceRecord(serviceUUID);
  28. } catch (IOException e) {
  29. }
  30. socket = tmp;
  31. }
  32. /** Will cancel an in-progress connection, and close the socket */
  33. public void cancel() {
  34. try {
  35. socket.close();
  36. } catch (IOException e) {
  37. }
  38. }
  39. @Override
  40. public void run() {
  41. try {
  42. socket.connect();
  43. } catch (IOException connectException) {
  44. // Unable to connect; close the socket and get out
  45. try {
  46. socket.close();
  47. } catch (IOException closeException) {
  48. }
  49. return;
  50. }
  51. manageConnectedSocket(socket, CLIENT);
  52. }
  53. }
  54. private class CommunicationThread extends Thread {
  55. private final BluetoothSocket mmSocket;
  56. private final ObjectInputStream objectInput;
  57. private final ObjectOutputStream objectOuput;
  58. private final int identifier;
  59. public CommunicationThread(BluetoothSocket socket, int identifier) {
  60. mmSocket = socket;
  61. ObjectInputStream tmpIn = null;
  62. ObjectOutputStream tmpOut = null;
  63. // Get the input and output streams, using temp objects because
  64. // member streams are final
  65. try {
  66. tmpOut = new ObjectOutputStream(socket.getOutputStream());
  67. tmpIn = new ObjectInputStream(socket.getInputStream());
  68. } catch (IOException e) {
  69. e.printStackTrace();
  70. }
  71. objectInput = tmpIn;
  72. objectOuput = tmpOut;
  73. this.identifier = identifier;
  74. }
  75. /* Call this from the main activity to shutdown the connection */
  76. public void cancel() {
  77. try {
  78. mmSocket.close();
  79. } catch (IOException e) {
  80. }
  81. }
  82. @Override
  83. public void run() {
  84. // Keep listening to the InputStream until an exception occurs
  85. // while (true) {
  86. try {
  87. // TODO Ersetze dbh mit Logger
  88. HostageDBOpenHelper dbh = new HostageDBOpenHelper(context);
  89. ArrayList<HashMap<String, Object>> localNetworkInformation = dbh.getNetworkInformation();
  90. if (identifier == SERVER) {
  91. // Read from the InputStream
  92. ArrayList<HashMap<String, Object>> remoteNetworkInformation = (ArrayList<HashMap<String, Object>>) objectInput.readObject();
  93. ;
  94. dbh.updateNetworkInformation(remoteNetworkInformation);
  95. objectOuput.writeObject(localNetworkInformation);
  96. } else {
  97. objectOuput.writeObject(localNetworkInformation);
  98. // Read from the InputStream
  99. ArrayList<HashMap<String, Object>> remoteNetworkInformation = (ArrayList<HashMap<String, Object>>) objectInput.readObject();
  100. dbh.updateNetworkInformation(remoteNetworkInformation);
  101. mmSocket.close();
  102. }
  103. } catch (ClassNotFoundException e) {
  104. e.printStackTrace();
  105. } catch (IOException e) {
  106. e.printStackTrace();
  107. }
  108. // }
  109. }
  110. /* Call this from the main activity to send data to the remote device */
  111. public void write(ArrayList<HashMap<String, Object>> networkInformation) {
  112. try {
  113. objectOuput.writeObject(networkInformation);
  114. } catch (IOException e) {
  115. e.printStackTrace();
  116. }
  117. }
  118. }
  119. private class ServerThread extends Thread {
  120. private final BluetoothServerSocket serverSocket;
  121. public ServerThread() {
  122. BluetoothServerSocket tmp = null;
  123. try {
  124. tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(context.getResources().getString(R.string.app_name), serviceUUID);
  125. } catch (IOException e) {
  126. }
  127. serverSocket = tmp;
  128. }
  129. /** Will cancel the listening socket, and cause the thread to finish */
  130. public void cancel() {
  131. try {
  132. serverSocket.close();
  133. } catch (IOException e) {
  134. }
  135. }
  136. @Override
  137. public void run() {
  138. BluetoothSocket socket = null;
  139. while (true) {
  140. try {
  141. socket = serverSocket.accept();
  142. } catch (IOException e) {
  143. e.printStackTrace();
  144. break;
  145. }
  146. if (socket != null) {
  147. // Do work to manage the connection (in a separate thread)
  148. manageConnectedSocket(socket, SERVER);
  149. try {
  150. serverSocket.close();
  151. } catch (IOException e) {
  152. e.printStackTrace();
  153. }
  154. break;
  155. }
  156. }
  157. }
  158. }
  159. private final UUID serviceUUID;
  160. private final int SERVER = 0;
  161. private final int CLIENT = 1;
  162. private BluetoothAdapter mBluetoothAdapter;
  163. private Context context;
  164. private ArrayAdapter<String> arrayAdapter;
  165. private ServerThread serverThread;
  166. private AlertDialog ad;
  167. // Create a BroadcastReceiver for ACTION_FOUND
  168. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  169. @Override
  170. public void onReceive(Context context, Intent intent) {
  171. String action = intent.getAction();
  172. // When discovery finds a device
  173. if (BluetoothDevice.ACTION_FOUND.equals(action)) {
  174. // Get the BluetoothDevice object from the Intent
  175. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  176. // Add the name and address to an array adapter to show in a
  177. // ListView
  178. arrayAdapter.add(device.getName() + "\n" + device.getAddress());
  179. arrayAdapter.notifyDataSetChanged();
  180. }
  181. }
  182. };
  183. public BluetoothSync(Context context) {
  184. this.context = context;
  185. serviceUUID = UUID.fromString(context.getResources().getString(R.string.UUID));
  186. mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  187. }
  188. public boolean syncData() {
  189. if (!bluetoothAvaible())
  190. return false;
  191. syncDataPassive();
  192. return syncDataActive();
  193. }
  194. private boolean bluetoothAvaible() {
  195. if (mBluetoothAdapter == null) {
  196. // Device does not support Bluetooth
  197. return false;
  198. }
  199. if (!mBluetoothAdapter.isEnabled()) {
  200. Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
  201. context.startActivity(enableBtIntent);
  202. return false;
  203. }
  204. return true;
  205. }
  206. private void deviceDialog() {
  207. AlertDialog.Builder builder = new AlertDialog.Builder(context);
  208. // TODO in resources auslagern
  209. builder.setTitle("Choose Device");
  210. builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
  211. @Override
  212. public void onClick(DialogInterface dialog, int position) {
  213. String deviceInfo = arrayAdapter.getItem(position);
  214. String mac = deviceInfo.substring(deviceInfo.indexOf("\n") + 1);
  215. ClientThread clientThread = new ClientThread(mBluetoothAdapter.getRemoteDevice(mac));
  216. clientThread.start();
  217. }
  218. });
  219. // builder.create();
  220. ad = builder.show();
  221. }
  222. private void manageConnectedSocket(BluetoothSocket socket, int identifier) {
  223. if (identifier == SERVER) {
  224. ad.dismiss();
  225. }
  226. mBluetoothAdapter.cancelDiscovery();
  227. context.unregisterReceiver(mReceiver);
  228. CommunicationThread commThread = new CommunicationThread(socket, identifier);
  229. commThread.start();
  230. }
  231. // Register the BroadcastReceiver
  232. private void registerBroadcastReceiver() {
  233. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
  234. context.registerReceiver(mReceiver, filter); // Don't forget to
  235. // unregister during
  236. // onDestroy
  237. }
  238. private boolean syncDataActive() {
  239. registerBroadcastReceiver();
  240. arrayAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1);
  241. // Start scanning for devices
  242. if (!mBluetoothAdapter.startDiscovery())
  243. return false;
  244. deviceDialog();
  245. return true;
  246. }
  247. private void syncDataPassive() {
  248. Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
  249. discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
  250. context.startActivity(discoverableIntent);
  251. serverThread = new ServerThread();
  252. serverThread.start();
  253. }
  254. }