BluetoothSync.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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.util.Log;
  9. import android.app.Activity;
  10. import android.bluetooth.BluetoothAdapter;
  11. import android.bluetooth.BluetoothDevice;
  12. import android.bluetooth.BluetoothServerSocket;
  13. import android.bluetooth.BluetoothSocket;
  14. import android.content.BroadcastReceiver;
  15. import android.content.Context;
  16. import android.content.Intent;
  17. import android.content.IntentFilter;
  18. import android.os.Bundle;
  19. import android.os.Handler;
  20. import android.os.Message;
  21. import android.view.View;
  22. import android.widget.AdapterView;
  23. import android.widget.ArrayAdapter;
  24. import android.widget.LinearLayout;
  25. import android.widget.ListView;
  26. import android.widget.TextView;
  27. import android.widget.AdapterView.OnItemClickListener;
  28. import de.tudarmstadt.informatik.hostage.R;
  29. import de.tudarmstadt.informatik.hostage.persistence.HostageDBOpenHelper;
  30. public class BluetoothSync extends Activity{
  31. private static final int CONNECTION_ESTABLISHED = 0x0;
  32. private static final int CONNECTION_FAILED = 0x1;
  33. private static final int MESSAGE_SENT = 0x2;
  34. private static final int MESSAGE_RECIEVED = 0x3;
  35. private UUID serviceUUID;
  36. private BluetoothAdapter mBluetoothAdapter;
  37. private ArrayAdapter<String> arrayAdapter;
  38. private ServerThread serverThread;
  39. private ClientThread clientThread;
  40. CommunicationThread commThread;
  41. TextView mInfoText;
  42. ListView listView;
  43. LinearLayout layout;
  44. @Override
  45. public void onCreate(Bundle savedInstanceState){
  46. super.onCreate(savedInstanceState);
  47. setContentView(R.layout.activity_bluetooth);
  48. serviceUUID = UUID.fromString(getResources().getString(R.string.UUID));
  49. mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  50. arrayAdapter = new ArrayAdapter<String>(this, R.layout.list_view_bluetooth_devices);
  51. setLayoutElement();
  52. registerBroadcastReceiver();
  53. if (mBluetoothAdapter == null) {
  54. // Device does not support Bluetooth
  55. mInfoText.setText("Bluetooth is not available on this device.");
  56. }
  57. else if (!mBluetoothAdapter.isEnabled()) {
  58. mInfoText.setText("Enable Bluetooth before synchronizing.");
  59. Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
  60. startActivity(enableBtIntent);
  61. } else {
  62. startConnectionListener();
  63. chooseDevice();
  64. }
  65. }
  66. @Override
  67. public void onDestroy(){
  68. super.onDestroy();
  69. if(mRecieverRegistered){
  70. unregisterBroadcastReceiver();
  71. }
  72. if(commThread != null) {
  73. commThread.cancel();
  74. }
  75. if(clientThread != null){
  76. clientThread.cancel();
  77. }
  78. if(serverThread != null){
  79. serverThread.cancel();
  80. }
  81. }
  82. private void chooseDevice(){
  83. arrayAdapter.clear();
  84. if (!mBluetoothAdapter.startDiscovery())
  85. return;
  86. mInfoText.setText("Choose Device for synchronizing:\n");
  87. layout.addView(listView);
  88. setContentView(layout);
  89. }
  90. private void startConnectionListener() {
  91. Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
  92. discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
  93. startActivity(discoverableIntent);
  94. serverThread = new ServerThread();
  95. serverThread.start();
  96. }
  97. private void manageConnectedSocket(BluetoothSocket socket) {
  98. mBluetoothAdapter.cancelDiscovery();
  99. unregisterBroadcastReceiver();
  100. commThread = new CommunicationThread(socket);
  101. commThread.start();
  102. HostageDBOpenHelper dbh = new HostageDBOpenHelper(this);
  103. ArrayList<HashMap<String, Object>> localNetworkInformation = dbh.getNetworkInformation();
  104. commThread.write(localNetworkInformation);
  105. }
  106. private class ClientThread extends Thread {
  107. private final BluetoothSocket socket;
  108. public ClientThread(BluetoothDevice device) {
  109. BluetoothSocket tmp = null;
  110. try {
  111. tmp = device.createRfcommSocketToServiceRecord(serviceUUID);
  112. } catch (IOException e) {
  113. }
  114. socket = tmp;
  115. }
  116. /** Will cancel an in-progress connection, and close the socket */
  117. public void cancel() {
  118. try {
  119. socket.close();
  120. } catch (IOException e) {
  121. }
  122. }
  123. @Override
  124. public void run() {
  125. try {
  126. socket.connect();
  127. } catch (IOException connectException) {
  128. mHandler.obtainMessage(CONNECTION_FAILED).sendToTarget();
  129. // Unable to connect; close the socket and get out
  130. try {
  131. socket.close();
  132. } catch (IOException closeException) {
  133. }
  134. return;
  135. }
  136. mHandler.obtainMessage(CONNECTION_ESTABLISHED, socket).sendToTarget();
  137. manageConnectedSocket(socket);
  138. }
  139. }
  140. private class ServerThread extends Thread {
  141. private final BluetoothServerSocket serverSocket;
  142. public ServerThread() {
  143. BluetoothServerSocket tmp = null;
  144. try {
  145. tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(getResources().getString(R.string.app_name), serviceUUID);
  146. } catch (IOException e) {
  147. }
  148. serverSocket = tmp;
  149. }
  150. /** Will cancel the listening socket, and cause the thread to finish */
  151. public void cancel() {
  152. try {
  153. serverSocket.close();
  154. } catch (IOException e) {
  155. }
  156. }
  157. @Override
  158. public void run() {
  159. BluetoothSocket socket = null;
  160. while (true) {
  161. try {
  162. socket = serverSocket.accept();
  163. } catch (IOException e) {
  164. e.printStackTrace();
  165. mHandler.obtainMessage(CONNECTION_FAILED).sendToTarget();
  166. break;
  167. }
  168. if (socket != null) {
  169. // Do work to manage the connection (in a separate thread)
  170. manageConnectedSocket(socket);
  171. mHandler.obtainMessage(CONNECTION_ESTABLISHED, socket).sendToTarget();
  172. try {
  173. serverSocket.close();
  174. } catch (IOException e) {
  175. e.printStackTrace();
  176. }
  177. break;
  178. }
  179. }
  180. }
  181. }
  182. private class CommunicationThread extends Thread {
  183. private final BluetoothSocket mmSocket;
  184. private final ObjectInputStream objectInput;
  185. private final ObjectOutputStream objectOuput;
  186. public CommunicationThread(BluetoothSocket socket) {
  187. mmSocket = socket;
  188. ObjectInputStream tmpIn = null;
  189. ObjectOutputStream tmpOut = null;
  190. // Get the input and output streams, using temp objects because
  191. // member streams are final
  192. try {
  193. tmpOut = new ObjectOutputStream(socket.getOutputStream());
  194. tmpIn = new ObjectInputStream(socket.getInputStream());
  195. } catch (IOException e) {
  196. e.printStackTrace();
  197. }
  198. objectInput = tmpIn;
  199. objectOuput = tmpOut;
  200. }
  201. /* Call this from the main activity to shutdown the connection */
  202. public void cancel() {
  203. try {
  204. mmSocket.close();
  205. } catch (IOException e) {
  206. }
  207. }
  208. @Override
  209. public void run() {
  210. // Keep listening to the InputStream until an exception occurs
  211. while (true) {
  212. try {
  213. // TODO Ersetze dbh mit Logger
  214. HostageDBOpenHelper dbh = new HostageDBOpenHelper(getContext());
  215. // Read from the InputStream
  216. ArrayList<HashMap<String, Object>> remoteNetworkInformation = (ArrayList<HashMap<String, Object>>) objectInput.readObject();
  217. // update database
  218. dbh.updateNetworkInformation(remoteNetworkInformation);
  219. mHandler.obtainMessage(MESSAGE_RECIEVED).sendToTarget();
  220. } catch (ClassNotFoundException e) {
  221. e.printStackTrace();
  222. } catch (IOException e) {
  223. e.printStackTrace();
  224. break;
  225. }
  226. }
  227. }
  228. /* Call this from the main activity to send data to the remote device */
  229. public void write(ArrayList<HashMap<String, Object>> networkInformation) {
  230. try {
  231. objectOuput.writeObject(networkInformation);
  232. mHandler.obtainMessage(MESSAGE_SENT).sendToTarget();
  233. } catch (IOException e) {
  234. e.printStackTrace();
  235. }
  236. }
  237. }
  238. // Create a BroadcastReceiver for ACTION_FOUND
  239. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  240. @Override
  241. public void onReceive(Context context, Intent intent) {
  242. String action = intent.getAction();
  243. // When discovery finds a device
  244. if (BluetoothDevice.ACTION_FOUND.equals(action)) {
  245. // Get the BluetoothDevice object from the Intent
  246. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  247. // Add the name and address to an array adapter to show in a ListView
  248. arrayAdapter.add(device.getName() + "\n" + device.getAddress());
  249. arrayAdapter.notifyDataSetChanged();
  250. }else if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){
  251. int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
  252. Log.i("BluetoothSync", state + "");
  253. if(state == BluetoothAdapter.STATE_ON){
  254. startConnectionListener();
  255. chooseDevice();
  256. }else if(state == BluetoothAdapter.STATE_OFF || state == BluetoothAdapter.STATE_TURNING_OFF){
  257. mInfoText.setText("Enable Bluetooth before synchronizing.");
  258. layout.removeView(listView);
  259. }
  260. }
  261. }
  262. };
  263. private boolean mRecieverRegistered = false;
  264. // Register the BroadcastReceiver
  265. private void registerBroadcastReceiver() {
  266. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
  267. filter.addAction(BluetoothAdapter. ACTION_STATE_CHANGED);
  268. registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
  269. mRecieverRegistered = true;
  270. }
  271. private void unregisterBroadcastReceiver(){
  272. unregisterReceiver(mReceiver);
  273. mRecieverRegistered = false;
  274. }
  275. private Context getContext(){
  276. return this;
  277. }
  278. private void setLayoutElement(){
  279. mInfoText = (TextView) findViewById(R.id.bluetoothInfoText);
  280. layout = (LinearLayout) findViewById(R.id.bluetoothLayout);
  281. listView = new ListView(this);
  282. listView.setAdapter(arrayAdapter);
  283. listView.setOnItemClickListener(new OnItemClickListener() {
  284. @Override
  285. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  286. String deviceInfo = arrayAdapter.getItem(position);
  287. String mac = deviceInfo.substring(deviceInfo.indexOf("\n") + 1);
  288. clientThread = new ClientThread(mBluetoothAdapter.getRemoteDevice(mac));
  289. clientThread.start();
  290. }
  291. });
  292. }
  293. private boolean message_sent = false;
  294. private boolean message_recieved = false;
  295. private Handler mHandler = new Handler() {
  296. @Override
  297. public void handleMessage(Message msg) {
  298. switch(msg.what){
  299. case CONNECTION_ESTABLISHED:
  300. layout.removeView(listView);
  301. BluetoothSocket socket = (BluetoothSocket) msg.obj;
  302. String deviceName = socket.getRemoteDevice().getName();
  303. mInfoText.setText("Synchronizing with " + deviceName + "...");
  304. break;
  305. case CONNECTION_FAILED:
  306. mInfoText.setText("Synchronization failed!");
  307. break;
  308. case MESSAGE_SENT:
  309. message_sent = true;
  310. if(message_recieved)
  311. mInfoText.setText("Synchronization successfull!");
  312. break;
  313. case MESSAGE_RECIEVED:
  314. message_recieved = true;
  315. if(message_sent)
  316. mInfoText.setText("Synchronization successfull!");
  317. break;
  318. }
  319. }
  320. };
  321. }