package de.tudarmstadt.informatik.hostage.sync; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.UUID; import android.app.AlertDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.widget.ArrayAdapter; import de.tudarmstadt.informatik.hostage.R; import de.tudarmstadt.informatik.hostage.logging.DatabaseHandler; public class BluetoothSync{ private final UUID serviceUUID; private final int SERVER = 0; private final int CLIENT = 1; private BluetoothAdapter mBluetoothAdapter; private Context context; private ArrayAdapter arrayAdapter; private ServerThread serverThread; private AlertDialog ad; public BluetoothSync(Context context){ this.context = context; serviceUUID = UUID.fromString(context.getResources().getString(R.string.UUID)); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } public boolean syncData(){ if(!bluetoothAvaible()) return false; syncDataPassive(); return syncDataActive(); } private boolean syncDataActive() { registerBroadcastReceiver(); arrayAdapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1); //Start scanning for devices if(!mBluetoothAdapter.startDiscovery()) return false; deviceDialog(); return true; } private void syncDataPassive(){ Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); context.startActivity(discoverableIntent); serverThread = new ServerThread(); serverThread.start(); } private void manageConnectedSocket(BluetoothSocket socket, int identifier){ if(identifier == SERVER){ ad.dismiss(); } mBluetoothAdapter.cancelDiscovery(); context.unregisterReceiver(mReceiver); CommunicationThread commThread = new CommunicationThread(socket, identifier); commThread.start(); } private boolean bluetoothAvaible(){ if (mBluetoothAdapter == null) { // Device does not support Bluetooth return false; } if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); context.startActivity(enableBtIntent); //TODO CHECK // if(!mBluetoothAdapter.isEnabled()) // return false; } return true; } // Create a BroadcastReceiver for ACTION_FOUND private final BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // Add the name and address to an array adapter to show in a ListView arrayAdapter.add(device.getName() + "\n" + device.getAddress()); arrayAdapter.notifyDataSetChanged(); } } }; // Register the BroadcastReceiver private void registerBroadcastReceiver(){ IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); context.registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy } private void deviceDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.delete_dialog_title); builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int position) { String deviceInfo = arrayAdapter.getItem(position); String mac = deviceInfo.substring(deviceInfo.indexOf("\n") + 1); ClientThread clientThread = new ClientThread(mBluetoothAdapter.getRemoteDevice(mac)); clientThread.start(); } }); // builder.create(); ad = builder.show(); } private class ServerThread extends Thread { private final BluetoothServerSocket serverSocket; public ServerThread() { BluetoothServerSocket tmp = null; try { tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(context.getResources().getString(R.string.app_name), serviceUUID); } catch (IOException e) { } serverSocket = tmp; } public void run() { BluetoothSocket socket = null; while(true){ try { socket = serverSocket.accept(); } catch (IOException e) { e.printStackTrace(); break; } if (socket != null) { // Do work to manage the connection (in a separate thread) manageConnectedSocket(socket, SERVER); try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } break; } } } /** Will cancel the listening socket, and cause the thread to finish */ public void cancel() { try { serverSocket.close(); } catch (IOException e) { } } } private class ClientThread extends Thread { private final BluetoothSocket socket; public ClientThread(BluetoothDevice device) { BluetoothSocket tmp = null; try { tmp = device.createRfcommSocketToServiceRecord(serviceUUID); } catch (IOException e) { } socket = tmp; } public void run() { try { socket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and get out try { socket.close(); } catch (IOException closeException) { } return; } manageConnectedSocket(socket, CLIENT); } /** Will cancel an in-progress connection, and close the socket */ public void cancel() { try { socket.close(); } catch (IOException e) { } } } private class CommunicationThread extends Thread { private final BluetoothSocket mmSocket; private final ObjectInputStream objectInput; private final ObjectOutputStream objectOuput; private final int identifier; public CommunicationThread(BluetoothSocket socket, int identifier) { mmSocket = socket; ObjectInputStream tmpIn = null; ObjectOutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try { tmpOut = new ObjectOutputStream(socket.getOutputStream()); tmpIn = new ObjectInputStream(socket.getInputStream()); } catch (IOException e) { e.printStackTrace();} objectInput = tmpIn; objectOuput = tmpOut; this.identifier = identifier; } public void run() { // Keep listening to the InputStream until an exception occurs // while (true) { try { DatabaseHandler dbh = new DatabaseHandler(context); ArrayList> localNetworkInformation = dbh.getNetworkInformation(); if(identifier == SERVER){ // Read from the InputStream ArrayList> remoteNetworkInformation = (ArrayList>) objectInput.readObject();; dbh.updateNetworkInformation(remoteNetworkInformation); objectOuput.writeObject(localNetworkInformation); }else{ objectOuput.writeObject(localNetworkInformation); // Read from the InputStream ArrayList> remoteNetworkInformation = (ArrayList>) objectInput.readObject(); dbh.updateNetworkInformation(remoteNetworkInformation); mmSocket.close(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // } } /* Call this from the main activity to send data to the remote device */ public void write(ArrayList> networkInformation) { try { objectOuput.writeObject(networkInformation); } catch (IOException e) { e.printStackTrace(); } } /* Call this from the main activity to shutdown the connection */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } } }