diff --git a/res/drawable-hdpi/camera_lens.png b/res/drawable-hdpi/camera_lens.png new file mode 100644 index 0000000..a547a08 Binary files /dev/null and b/res/drawable-hdpi/camera_lens.png differ diff --git a/res/drawable-ldpi/camera_lens.png b/res/drawable-ldpi/camera_lens.png new file mode 100644 index 0000000..680707f Binary files /dev/null and b/res/drawable-ldpi/camera_lens.png differ diff --git a/res/drawable-mdpi/camera_lens.png b/res/drawable-mdpi/camera_lens.png new file mode 100644 index 0000000..0f8b49f Binary files /dev/null and b/res/drawable-mdpi/camera_lens.png differ diff --git a/src/ve/ucv/ciens/ccg/nxtcam/dialogs/ConnectRobotDialog.java b/src/ve/ucv/ciens/ccg/nxtcam/dialogs/ConnectRobotDialog.java new file mode 100644 index 0000000..ef0d08e --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtcam/dialogs/ConnectRobotDialog.java @@ -0,0 +1,56 @@ +package ve.ucv.ciens.ccg.nxtcam.dialogs; + +import ve.ucv.ciens.ccg.nxtcam.R; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; + +public class ConnectRobotDialog extends DialogFragment { + private final String TAG = "NXTCAM_ROBOT_DIALOG"; + private final String CLASS_NAME = ConnectRobotDialog.class.getSimpleName(); + + private ConnectRobotDialogListener listener; + + public interface ConnectRobotDialogListener{ + public void onConnectRobotDialogPositiveClick(DialogFragment dialog); + public void onConnectRobotDialogNegativeClick(DialogFragment dialog); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState){ + // Use the Builder class for convenient dialog construction + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + + builder.setMessage(R.string.wifi_on_msg).setPositiveButton(R.string.wifi_on_button, new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int id){ + + } + + }).setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int id){ + + } + + }); + + // Create the AlertDialog object and return it + return builder.create(); + } + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + + try{ + listener = (ConnectRobotDialogListener)activity; + }catch(ClassCastException cce){ + listener = null; + throw new ClassCastException(CLASS_NAME + ".onAttach() :: " + activity.toString() + "Must implement WifiOnDialogListener."); + } + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtcam/network/BTCommunicator.java b/src/ve/ucv/ciens/ccg/nxtcam/network/BTCommunicator.java new file mode 100644 index 0000000..f530187 --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtcam/network/BTCommunicator.java @@ -0,0 +1,234 @@ +package ve.ucv.ciens.ccg.nxtcam.network; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Set; +import java.util.UUID; + +import ve.ucv.ciens.ccg.nxtcam.MainActivity; +import ve.ucv.ciens.ccg.nxtcam.utils.Logger; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.util.Log; + +/** + * Basic Bluetooth communication manager class. + * + * @author Miguel Angel Astor Romero + * @version 1.0 + * @since 2012-10-15 + */ +public class BTCommunicator{ + private static final String TAG = "NXT_TEST_BTCOMM"; + private final String CLASS_NAME = MainActivity.class.getSimpleName(); + + private static final UUID SERIAL_PORT_SERVICE_CLASS_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + private static final String OUI_LEGO = "00:16:53"; + + private boolean connected; + private BluetoothAdapter bt_adapter = null; + private BluetoothSocket bt_socket = null; + private OutputStream nxt_out_stream = null; + private InputStream nxt_in_stream = null; + + private static class SingletonHolder{ + public static final BTCommunicator INSTANCE = new BTCommunicator(); + } + + /** + * Gets the singleton instance of this class. + * + * @return The singleton instance of this class. + */ + public static BTCommunicator getInstance(){ + return SingletonHolder.INSTANCE; + } + + /** + * Basic constructor. + */ + private BTCommunicator(){ + connected = false; + bt_adapter = BluetoothAdapter.getDefaultAdapter(); + bt_socket = null; + nxt_in_stream = null; + nxt_out_stream = null; + } + + /** + * Indicates if Bluetooth is available on the device. + * + * @return true if the default Bluetooth adapter exists, otherwise false. + */ + public boolean isBTSupported(){ + return bt_adapter != null; + } + + /** + * Indicates if there is an active connection. + * + * @return true if this device is connected to a NXT robot, otherwise false. + */ + public boolean isConnected(){ + return connected; + } + + /** + * Wrapper to the standard method for checking if Bluetooth is enabled. + * + * @see android.bluetooth.BluetoothAdapter + */ + public boolean isBTEnabled(){ + return bt_adapter.isEnabled(); + } + + /** + * Wrapper to the standard method for stopping this device's Bluetooth adapter. + * + * @see android.bluetooth.BluetoothAdapter + */ + public void disableBT(){ + bt_adapter.disable(); + } + + /** + * Gets all the devices paired to the default Bluetooth adapter. + * + * @return A set containing all devices paired to this device. + */ + public Set getPairedDevices(){ + return bt_adapter.getBondedDevices(); + } + + /** + * Sets up a connection with a NXT device. + * + * Verifies if the target device is a valid NXT robot by checking agains Lego's OUI. + * Also creates the socket and the streams associated with the connection + * + * @param mac_address The mac address of the target device. + * @return true if the connection was established succesfully, otherwise false. + * @throws IOException + */ + public boolean establishConnection(String mac_address) throws IOException{ + if (!bt_adapter.isEnabled()){ + return false; + } + if(connected){ + return false; + } + if(bt_adapter.isEnabled()){ + if(mac_address == "NONE"){ + return false; + }else{ + if(mac_address.substring(0, 8).compareTo(OUI_LEGO) != 0){ + Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Not a Lego MAC. Prefix : " + mac_address.substring(0, 8) + " :: OUI : " + OUI_LEGO); + return false; + }else{ + try{ + Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Getting device with mac address: " + mac_address); + BluetoothDevice nxtDevice = null; + nxtDevice = bt_adapter.getRemoteDevice(mac_address); + if (nxtDevice == null) { + Logger.log_e(TAG, CLASS_NAME + ".establishConnection() :: No device found."); + throw new IOException(); + } + + Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Opening socket."); + bt_socket = nxtDevice.createRfcommSocketToServiceRecord(SERIAL_PORT_SERVICE_CLASS_UUID); + Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Connecting."); + bt_socket.connect(); + + Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Opening IO streams."); + nxt_in_stream = bt_socket.getInputStream(); + nxt_out_stream = bt_socket.getOutputStream(); + + Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Connection established."); + connected = true; + + }catch(IOException e){ + Logger.log_e(TAG, CLASS_NAME + ".establishConnection() :: Connection failed."); + Logger.log_e(TAG, Log.getStackTraceString(e)); + connected = false; + throw e; + } + return connected; + } + } + } + return false; + } + + /** + * Closes the active connection if any. + * + * Additionally clears the socket and the streams associated to said connection. + * + * @return true if the connection was succesfully closed; false if no connection exists. + * @throws IOException + */ + public boolean stopConnection() throws IOException{ + try{ + if(bt_socket != null){ + Logger.log_d(TAG, CLASS_NAME + ".stopConnection() :: Closing connection."); + bt_socket.close(); + bt_socket = null; + nxt_in_stream = null; + nxt_out_stream = null; + connected = false; + Logger.log_d(TAG, CLASS_NAME + ".stopConnection() :: Connection closed."); + return true; + } + }catch( IOException e){ + Logger.log_e(TAG, CLASS_NAME + ".stopConnection()"); + Logger.log_e(TAG, Log.getStackTraceString(e)); + throw e; + } + return false; + } + + /** + * Sends a message to the NXT robot. + * + * @param message The data to be sent. + * @throws IOException + */ + public synchronized void writeMessage(byte[] message) throws IOException{ + if(connected){ + try{ + nxt_out_stream.write(message); + }catch(IOException e){ + Logger.log_e(TAG, CLASS_NAME + ".writeMessage()"); + Logger.log_e(TAG, Log.getStackTraceString(e)); + throw e; + } + } + } + + /** + * Reads a message sent by the NXT robot. + * + * @return The data received as a byte[] if a valid connection exists, otherwise null. + * @throws IOException + */ + public synchronized byte[] readMessage(int bytes) throws IOException{ + if(connected){ + try{ + byte[] message = new byte[bytes]; + for(int i = 0; i < message.length; ++i){ + message[i] = 0x00; + } + nxt_in_stream.read(message, 0, bytes); + return message; + }catch(IOException e){ + Logger.log_e(TAG, CLASS_NAME + ".readMessage()"); + Logger.log_e(TAG, Log.getStackTraceString(e)); + throw e; + } + }else{ + return null; + } + } +}