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.UglyDbHelper; public class BluetoothSync { 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; } /** Will cancel an in-progress connection, and close the socket */ public void cancel() { try { socket.close(); } catch (IOException e) { } } @Override 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); } } 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; } /* Call this from the main activity to shutdown the connection */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } @Override public void run() { // Keep listening to the InputStream until an exception occurs // while (true) { try { // TODO Ersetze dbh mit Logger UglyDbHelper dbh = new UglyDbHelper(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(); } } } 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; } /** Will cancel the listening socket, and cause the thread to finish */ public void cancel() { try { serverSocket.close(); } catch (IOException e) { } } @Override 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; } } } } 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; // Create a BroadcastReceiver for ACTION_FOUND private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override 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(); } } }; 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 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); return false; } return true; } private void deviceDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(context); // TODO in resources auslagern builder.setTitle("Choose Device"); builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() { @Override 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 void manageConnectedSocket(BluetoothSocket socket, int identifier) { if (identifier == SERVER) { ad.dismiss(); } mBluetoothAdapter.cancelDiscovery(); context.unregisterReceiver(mReceiver); CommunicationThread commThread = new CommunicationThread(socket, identifier); commThread.start(); } // 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 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(); } }