Merge branch 'milestone1'
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="10"
|
||||
android:minSdkVersion="11"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
BIN
res/drawable-ldpi/camera_lens.png
Normal file
BIN
res/drawable-ldpi/camera_lens.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
res/drawable-mdpi/camera_lens.png
Normal file
BIN
res/drawable-mdpi/camera_lens.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
@@ -2,38 +2,32 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:baselineAligned="false"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:baselineAligned="false"
|
||||
tools:context=".MainActivity" >
|
||||
|
||||
<Button
|
||||
android:id="@+id/connectButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@+id/startButton"
|
||||
android:layout_alignRight="@+id/startButton"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center"
|
||||
android:onClick="connectWithRobot"
|
||||
android:text="@string/robot_pair_button" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/startButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_below="@+id/connectButton"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center"
|
||||
android:onClick="startConnections"
|
||||
android:text="@string/start_button" />
|
||||
|
||||
<!-- <EditText
|
||||
android:id="@+id/ipAddressField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/startButton"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:ems="10"
|
||||
android:inputType="text" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBaseline="@+id/ipAddressField"
|
||||
android:layout_alignBottom="@+id/ipAddressField"
|
||||
android:layout_toLeftOf="@+id/ipAddressField"
|
||||
android:text="@string/ipAddressLabel" />
|
||||
-->
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
@@ -7,10 +7,27 @@
|
||||
<string name="camera_success">Cámara abierta exitosamente</string>
|
||||
<string name="camera_failure">La cámara no pudo abrirse</string>
|
||||
<string name="get_server_button">Conectar con NxtAR</string>
|
||||
<string name="start_button">Conectar con dispositivo controlador</string>
|
||||
<string name="start_button">Comenzar streaming de video</string>
|
||||
<string name="title_activity_cam">CamActivity</string>
|
||||
<string name="ipAddressLabel">Dirección IP de NxtAR</string>
|
||||
<string name="badIpToast">La dirección IP no es válida</string>
|
||||
<string name="emptyIpToast">Rellene el campo de dirección IP</string>
|
||||
<string name="wifi_on_title">Esta app requiere WiFi</string>
|
||||
<string name="wifi_on_msg">¿Encender el WiFi?</string>
|
||||
<string name="cancel_button">Cancelar</string>
|
||||
<string name="wifi_on_button">Encender</string>
|
||||
<string name="wifi_on_success">El radio del WiFi está encendido</string>
|
||||
<string name="wifi_on_fail">Esta app no puede funcionar sin wifi, cerrando.</string>
|
||||
<string name= "bt_no_support">Este dispositivo no soporta Bluetooth</string>
|
||||
<string name="bt_on_fail">Esta app no puede funcionar sin Bluetooth, cerrando</string>
|
||||
<string name="lens_icon">Ícono de lente</string>
|
||||
<string name="robot_pair_button">Conectar con el robot</string>
|
||||
<string name="robot_choice">Escoja un robot</string>
|
||||
<string name="conn_established">Conexión exitosa con el robot</string>
|
||||
<string name="conn_failed">No se pudo conectar con el robot</string>
|
||||
<string name="bt_wait">Por favor espere por la conexión</string>
|
||||
<string name="serv_wait">Por favor espere, buscando dispositivo de control</string>
|
||||
<string name="serv_connected">Conectado con el dispositivo de control</string>
|
||||
<string name="serv_fail">Falló la conexión con el dispositivo de control</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -8,9 +8,26 @@
|
||||
<string name="camera_failure">Camera could not be opened</string>
|
||||
<string name="title_activity_cam">CamActivity</string>
|
||||
<string name="get_server_button">Connect with NxtAR</string>
|
||||
<string name="start_button">Connect with controller device</string>
|
||||
<string name="start_button">Start video streaming</string>
|
||||
<string name="ipAddressLabel">NxtAR IP Address</string>
|
||||
<string name="badIpToast">Invalid IP address</string>
|
||||
<string name="emptyIpToast">Fill out the IP address field</string>
|
||||
<string name="wifi_on_title">This app requires WiFi</string>
|
||||
<string name="wifi_on_msg">Turn on the WiFi?</string>
|
||||
<string name="cancel_button">Cancel</string>
|
||||
<string name="wifi_on_button">Turn on</string>
|
||||
<string name="wifi_on_success">The WiFi radio is on now</string>
|
||||
<string name="wifi_on_fail">This app cannot work without WiFi, closing</string>
|
||||
<string name="bt_no_support">This device does not support Bluetooth</string>
|
||||
<string name="bt_on_fail">This app cannot work without Bluetooth, closing</string>
|
||||
<string name="lens_icon">Image lens icon</string>
|
||||
<string name="robot_pair_button">Connect with robot</string>
|
||||
<string name="robot_choice">Pick a robot</string>
|
||||
<string name="conn_established">Successfully connected with the robot</string>
|
||||
<string name="conn_failed">Could not connect with the robot</string>
|
||||
<string name="bt_wait">Please wait for the connection</string>
|
||||
<string name="serv_wait">Please wait, looking for control device</string>
|
||||
<string name="serv_connected">Connected with the control device</string>
|
||||
<string name="serv_fail">Could no connect with the control device</string>
|
||||
|
||||
</resources>
|
||||
</resources>
|
@@ -3,14 +3,12 @@ package ve.ucv.ciens.ccg.nxtcam;
|
||||
import ve.ucv.ciens.ccg.nxtcam.camera.CameraPreview;
|
||||
import ve.ucv.ciens.ccg.nxtcam.network.ImageTransferThread;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.hardware.Camera;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.WindowManager;
|
||||
@@ -94,7 +92,7 @@ public class CamActivity extends Activity{
|
||||
if(hwCamera != null){
|
||||
cPreview.setCamera(hwCamera);
|
||||
}else{
|
||||
Log.wtf(TAG, CLASS_NAME + ".startCameraPreview() :: CAMERA IS NULL!");
|
||||
Logger.log_wtf(TAG, CLASS_NAME + ".startCameraPreview() :: CAMERA IS NULL!");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -115,23 +113,23 @@ public class CamActivity extends Activity{
|
||||
try{
|
||||
cam = Camera.open(0);
|
||||
}catch(Exception e){
|
||||
if(ProjectConstants.DEBUG) Log.e(TAG, CLASS_NAME + ".doInBackground() :: Failed to open the camera.");
|
||||
Logger.log_e(TAG, CLASS_NAME + ".doInBackground() :: Failed to open the camera.");
|
||||
}
|
||||
return cam;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Camera result) {
|
||||
super.onPostExecute(result);
|
||||
|
||||
hwCamera = result;
|
||||
if(result != null){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPostExecute() :: Camera successfully opened");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".onPostExecute() :: Camera successfully opened");
|
||||
}else{
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPostExecute() :: Camera open failed on background task.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".onPostExecute() :: Camera open failed on background task.");
|
||||
Toast.makeText(getApplicationContext(), R.string.camera_failure, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
startCameraPreview();
|
||||
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -4,11 +4,19 @@ import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.Socket;
|
||||
|
||||
import ve.ucv.ciens.ccg.nxtcam.dialogs.ConnectRobotDialog;
|
||||
import ve.ucv.ciens.ccg.nxtcam.dialogs.ConnectRobotDialog.ConnectRobotDialogListener;
|
||||
import ve.ucv.ciens.ccg.nxtcam.dialogs.WifiOnDialog;
|
||||
import ve.ucv.ciens.ccg.nxtcam.dialogs.WifiOnDialog.WifiOnDialogListener;
|
||||
import ve.ucv.ciens.ccg.nxtcam.network.BTCommunicator;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants;
|
||||
import android.app.Activity;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.ProgressDialog;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiManager;
|
||||
@@ -18,7 +26,6 @@ import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
@@ -32,22 +39,25 @@ import android.widget.Toast;
|
||||
* datagram carrying the string "NxtAR server here!" is received.
|
||||
*
|
||||
* @author miky
|
||||
*
|
||||
*/
|
||||
public class MainActivity extends Activity {
|
||||
public class MainActivity extends Activity implements WifiOnDialogListener, ConnectRobotDialogListener{
|
||||
// Cosntant fields.
|
||||
private final String TAG = "NXTCAM_MAIN";
|
||||
private final String CLASS_NAME = MainActivity.class.getSimpleName();
|
||||
private static final int REQUEST_ENABLE_BT = 1;
|
||||
|
||||
// Gui components.
|
||||
// Gui components
|
||||
private Button startButton;
|
||||
//private TextView ipField;
|
||||
private Button connectButton;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
// Resources.
|
||||
private BTCommunicator btManager;
|
||||
private WifiManager wifiManager;
|
||||
|
||||
// Variables.
|
||||
private boolean wifiOnByMe;
|
||||
private boolean btOnByMe;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -56,34 +66,59 @@ public class MainActivity extends Activity {
|
||||
|
||||
// Set up fields.
|
||||
wifiOnByMe = false;
|
||||
btOnByMe = false;
|
||||
|
||||
// Set up gui components.
|
||||
startButton = (Button)findViewById(R.id.startButton);
|
||||
startButton.setOnClickListener(startClickListener);
|
||||
// ipField = (TextView)findViewById(R.id.ipAddressField);
|
||||
startButton.setEnabled(false);
|
||||
connectButton = (Button)findViewById(R.id.connectButton);
|
||||
|
||||
// Set up services.
|
||||
btManager = BTCommunicator.getInstance();
|
||||
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
|
||||
if(!wifiManager.isWifiEnabled())
|
||||
setWifi(true);
|
||||
|
||||
if(!btManager.isBTSupported()){
|
||||
// El dispositivo no soporta BlueTooth.
|
||||
Toast.makeText(this, R.string.bt_no_support, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(){
|
||||
super.onResume();
|
||||
|
||||
if(!wifiManager.isWifiEnabled())
|
||||
setWifi(true);
|
||||
if(!btManager.isBTEnabled()){
|
||||
enableBT();
|
||||
}else if(btManager.isBTEnabled() && !wifiManager.isWifiEnabled()){
|
||||
enableWifi();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(){
|
||||
super.onPause();
|
||||
|
||||
if(btManager.isBTEnabled() && btOnByMe)
|
||||
btManager.disableBT();
|
||||
|
||||
if(wifiManager.isWifiEnabled() && wifiOnByMe)
|
||||
setWifi(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(){
|
||||
super.onDestroy();
|
||||
if(btManager.isConnected()){
|
||||
try{
|
||||
btManager.stopConnection();
|
||||
}catch(IOException io){
|
||||
Logger.log_e(TAG, CLASS_NAME + ".onDestroy() :: Error closing the connection with the robot: " + io.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
@@ -91,6 +126,15 @@ public class MainActivity extends Activity {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onActivityResult(int request, int result, Intent data){
|
||||
if(request == REQUEST_ENABLE_BT && result == RESULT_OK){
|
||||
if(!wifiManager.isWifiEnabled())
|
||||
enableWifi();
|
||||
}else{
|
||||
Toast.makeText(this, R.string.bt_on_fail, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the camera capture activity if a server was found through service discovery.
|
||||
*
|
||||
@@ -99,12 +143,12 @@ public class MainActivity extends Activity {
|
||||
*/
|
||||
private void startCamActivity(boolean serverFound, String ipAddress){
|
||||
if(serverFound){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".startCamActivity() :: Launching camera activity.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".startCamActivity() :: Launching camera activity.");
|
||||
Intent intent = new Intent(this, CamActivity.class);
|
||||
intent.putExtra("address", ipAddress);
|
||||
startActivity(intent);
|
||||
}else{
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".startCamActivity() :: Cannot launch camera activity.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".startCamActivity() :: Cannot launch camera activity.");
|
||||
Toast.makeText(this, R.string.badIpToast, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@@ -116,36 +160,127 @@ public class MainActivity extends Activity {
|
||||
*/
|
||||
private void setWifi(boolean radioState){
|
||||
wifiManager.setWifiEnabled(radioState);
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".setWifi() :: setting wifi to " + (radioState ? "on" : "off"));
|
||||
Logger.log_d(TAG, CLASS_NAME + ".setWifi() :: setting wifi to " + (radioState ? "on" : "off"));
|
||||
if(radioState)
|
||||
wifiOnByMe = true;
|
||||
else
|
||||
wifiOnByMe = false;
|
||||
}
|
||||
|
||||
/*private void validateIpAddress(){
|
||||
if(ipField.getText().toString().compareTo("") != 0){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "validateIpAddress() :: Launching verification task.");
|
||||
VerifyIpAddressTask verifyIp = new VerifyIpAddressTask();
|
||||
verifyIp.execute(ipField.getText().toString());
|
||||
}else{
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "validateIpAddress() :: Ip address field is empty.");
|
||||
Toast.makeText(this, R.string.emptyIpToast, Toast.LENGTH_SHORT).show();
|
||||
/**
|
||||
* Shows a WifiOnDialog.
|
||||
*/
|
||||
private void enableWifi(){
|
||||
if(!wifiManager.isWifiEnabled()){
|
||||
DialogFragment wifiOn = new WifiOnDialog();
|
||||
((WifiOnDialog)wifiOn).setWifiManager(wifiManager);
|
||||
wifiOn.show(getFragmentManager(), "wifi_on");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for the connection button.
|
||||
* Launches the standard Bluetooth enable activity.
|
||||
*/
|
||||
private final View.OnClickListener startClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//validateIpAddress();
|
||||
ServiceDiscoveryTask serviceDiscovery = new ServiceDiscoveryTask();
|
||||
serviceDiscovery.execute();
|
||||
}
|
||||
private void enableBT(){
|
||||
Logger.log_d(TAG, CLASS_NAME + ".enableBT() :: Enabling the Bluetooth radio.");
|
||||
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
|
||||
btOnByMe = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commodity method for showing toasts from an AsyncTask.
|
||||
*
|
||||
* @param stringId The id of the string resource to show on the toast.
|
||||
* @param length Time to show the toast.
|
||||
*/
|
||||
protected void showToast(int stringId, int length){
|
||||
Toast.makeText(this, stringId, length).show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Commodity method that builds an standard Android progress dialog.
|
||||
*
|
||||
* The dialog is created as not cancellable and uses an undeterminate spinner as visual style.
|
||||
*
|
||||
* @param msg The descriptive text shown by the dialog.
|
||||
* @return The built dialog.
|
||||
*/
|
||||
private ProgressDialog buildProgressDialog(String msg){
|
||||
ProgressDialog dialog = new ProgressDialog(this);
|
||||
dialog.setMessage(msg);
|
||||
dialog.setCancelable(false);
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
dialog.setProgress(0);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener method for the WifiOnDialog.
|
||||
*
|
||||
* This method is called when the user chooses to accept the dialog. It just shows an information
|
||||
* message with a toast and marks the WiFi radio as turned on by the application.
|
||||
*
|
||||
* @param dialog The dialog that called this method.
|
||||
*/
|
||||
@Override
|
||||
public void onWifiOnDialogPositiveClick(DialogFragment dialog) {
|
||||
Toast.makeText(this, R.string.wifi_on_success, Toast.LENGTH_SHORT).show();
|
||||
wifiOnByMe = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener method for the WifiOnDialog.
|
||||
*
|
||||
* This method is called when the user chooses to cancel the dialog. It just shows an error message
|
||||
* with a toast and finishes the application.
|
||||
*
|
||||
* @param dialog The dialog that called this method.
|
||||
*/
|
||||
@Override
|
||||
public void onWifiOnDialogNegativeClick(DialogFragment dialog) {
|
||||
Toast.makeText(this, R.string.wifi_on_fail, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the robot selection dialog.
|
||||
*
|
||||
* @param view The view that called this method.
|
||||
*/
|
||||
public void connectWithRobot(View view){
|
||||
if(btManager.isBTEnabled()){
|
||||
DialogFragment connectBot = new ConnectRobotDialog();
|
||||
connectBot.show(getFragmentManager(), "connect_bot");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the service discovery task.
|
||||
*/
|
||||
public void startConnections(View view){
|
||||
ServiceDiscoveryTask serviceDiscovery = new ServiceDiscoveryTask();
|
||||
serviceDiscovery.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener method for the ConnectRobotDialog.
|
||||
*
|
||||
* When a user selects a robot to connect to in the dialog, this method launches the connection setup task
|
||||
* defined in the ConnectRobotTask.
|
||||
*
|
||||
* @param dialog The dialog that called this method.
|
||||
* @param robot The robot selected by the user in the format NAME\nMAC_ADDRESS
|
||||
*/
|
||||
@Override
|
||||
public void onConnectRobotDialogItemClick(DialogFragment dialog, String robot) {
|
||||
String macAddress = robot.substring(robot.indexOf('\n')+1);
|
||||
Logger.log_d(TAG, CLASS_NAME + ".onConnectRobotDialogItemClick() :: MAC address: " + macAddress);
|
||||
connectButton.setEnabled(false);
|
||||
ConnectRobotTask robotTask = new ConnectRobotTask(macAddress);
|
||||
robotTask.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous task for ad hoc UDP service discovery.
|
||||
*
|
||||
@@ -166,14 +301,21 @@ public class MainActivity extends Activity {
|
||||
InetAddress group = InetAddress.getByName(ProjectConstants.MULTICAST_ADDRESS);
|
||||
udpSocket.joinGroup(group);
|
||||
}catch(IOException io){
|
||||
Logger.log(Logger.LOG_TYPES.ERROR, TAG ,CLASS_NAME + ".ServiceDiscoveryTask() :: " + io.getMessage());
|
||||
Logger.log_e(TAG ,CLASS_NAME + ".ServiceDiscoveryTask() :: " + io.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute(){
|
||||
super.onPreExecute();
|
||||
progressDialog = buildProgressDialog(getString(R.string.serv_wait));
|
||||
progressDialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params){
|
||||
boolean result, done = false;
|
||||
byte[] buffer = (new String("Server is here")).getBytes();
|
||||
byte[] buffer = (new String("NxtAR server here!")).getBytes();
|
||||
|
||||
// Create a buffer and tell Android we want to receive multicast datagrams.
|
||||
packet = new DatagramPacket(buffer, buffer.length);
|
||||
@@ -187,14 +329,20 @@ public class MainActivity extends Activity {
|
||||
try{
|
||||
while(!done){
|
||||
udpSocket.receive(packet);
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".run() :: Found a server at " + packet.getAddress().getHostAddress());
|
||||
Logger.log_d(TAG, CLASS_NAME + ".run() :: Found a server at " + packet.getAddress().getHostAddress());
|
||||
String received = new String(packet.getData());
|
||||
Logger.log_d(TAG, CLASS_NAME + ".doInBackground() :: Packet payload is\n" + received);
|
||||
if(received.compareTo("NxtAR server here!") == 0)
|
||||
done = true;
|
||||
Socket client1, client2;
|
||||
client1 = new Socket(packet.getAddress(), ProjectConstants.SERVER_TCP_PORT_1);
|
||||
client1.close();
|
||||
client2 = new Socket(packet.getAddress(), ProjectConstants.SERVER_TCP_PORT_2);
|
||||
client2.close();
|
||||
}
|
||||
result = true;
|
||||
}catch(IOException io){
|
||||
Logger.log(Logger.LOG_TYPES.ERROR, TAG, CLASS_NAME + ".doInBackground() :: " + io.getMessage());
|
||||
Logger.log_e(TAG, CLASS_NAME + ".doInBackground() :: " + io.getMessage());
|
||||
result = false;
|
||||
}
|
||||
|
||||
@@ -210,33 +358,72 @@ public class MainActivity extends Activity {
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result){
|
||||
super.onPostExecute(result);
|
||||
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
|
||||
// If a server was found then start the next activity.
|
||||
if(packet != null)
|
||||
startCamActivity(result, packet.getAddress().getHostAddress());
|
||||
else
|
||||
startCamActivity(false, null);
|
||||
}
|
||||
};
|
||||
startButton.setEnabled(false);
|
||||
|
||||
/* private class VerifyIpAddressTask extends AsyncTask<String, Void, Boolean>{
|
||||
private final String CLASS_NAME = VerifyIpAddressTask.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
try{
|
||||
InetAddress.getByName(params[0]);
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "doInBackground() :: IP address is valid.");
|
||||
return true;
|
||||
}catch(UnknownHostException uh){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + "doInBackground() :: IP address is not valid.");
|
||||
return false;
|
||||
if(packet != null){
|
||||
showToast(R.string.serv_connected, Toast.LENGTH_SHORT);
|
||||
// startCamActivity(result, packet.getAddress().getHostAddress());
|
||||
}else{
|
||||
showToast(R.string.serv_fail, Toast.LENGTH_SHORT);
|
||||
// startCamActivity(false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This task handles the establishing of the connection with the NXT robot.
|
||||
*
|
||||
* @author miky
|
||||
*/
|
||||
private class ConnectRobotTask extends AsyncTask<Void, Void, Boolean>{
|
||||
private final String CLASS_NAME = ConnectRobotTask.class.getSimpleName();
|
||||
private String macAddress;
|
||||
|
||||
public ConnectRobotTask(String macAddress){
|
||||
this.macAddress = macAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
startCamActivity(result);
|
||||
protected void onPreExecute(){
|
||||
super.onPreExecute();
|
||||
progressDialog = buildProgressDialog(getString(R.string.bt_wait));
|
||||
progressDialog.show();
|
||||
}
|
||||
};*/
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params){
|
||||
boolean connSet;
|
||||
Logger.log_d(TAG, CLASS_NAME + "doInBackground() :: Establishing connection with the robot.");
|
||||
try{
|
||||
connSet = btManager.establishConnection(macAddress);
|
||||
}catch(IOException e){
|
||||
Logger.log_e(TAG, CLASS_NAME + "doInBackground() :: Error during the connection attempt.");
|
||||
connSet = false;
|
||||
}
|
||||
return connSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result){
|
||||
super.onPostExecute(result);
|
||||
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
|
||||
if(result){
|
||||
Logger.log_d(TAG, CLASS_NAME + "doInBackground() :: Connection successful.");
|
||||
showToast(R.string.conn_established, Toast.LENGTH_SHORT);
|
||||
startButton.setEnabled(true);
|
||||
}else{
|
||||
Logger.log_d(TAG, CLASS_NAME + "doInBackground() :: Connection failed.");
|
||||
showToast(R.string.conn_failed, Toast.LENGTH_LONG);
|
||||
connectButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,29 +22,29 @@ public class CameraImageMonitor{
|
||||
}
|
||||
|
||||
public void setImageData(byte[] image){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".setImageData() :: Copying new image.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".setImageData() :: Copying new image.");
|
||||
synchronized(image){
|
||||
this.image = new byte[image.length];
|
||||
System.arraycopy(image, 0, this.image, 0, image.length);
|
||||
imgChanged = true;
|
||||
image.notifyAll();
|
||||
}
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".setImageData() :: Data copy finished.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".setImageData() :: Data copy finished.");
|
||||
}
|
||||
|
||||
public byte[] getImageData(){
|
||||
byte[] returnImg;
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: Entry point.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".getImageData() :: Entry point.");
|
||||
synchronized(image){
|
||||
while(!imgChanged){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: Waiting for new data.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".getImageData() :: Waiting for new data.");
|
||||
try{ image.wait(); }catch(InterruptedException ie){}
|
||||
}
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: Retrieving new data.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".getImageData() :: Retrieving new data.");
|
||||
returnImg = image.clone();
|
||||
imgChanged = false;
|
||||
}
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".getImageData() :: New data retreived.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".getImageData() :: New data retreived.");
|
||||
return returnImg;
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,7 @@ public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback,
|
||||
private final String CLASS_NAME = CameraPreview.class.getSimpleName();
|
||||
|
||||
private Size mPreviewSize;
|
||||
private List<Size> mSupportedPreviewSizes;
|
||||
private List<Size> mSupportedPreviewSizes;
|
||||
private CameraImageMonitor camMonitor;
|
||||
private Activity parentActivity;
|
||||
private SurfaceView mSurfaceView;
|
||||
@@ -42,7 +42,7 @@ public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback,
|
||||
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB)
|
||||
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
}
|
||||
|
||||
|
||||
public void setCamera(Camera camera){
|
||||
mCamera = camera;
|
||||
if(mCamera != null){
|
||||
@@ -59,7 +59,7 @@ public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback,
|
||||
mCamera.setPreviewDisplay(holder);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, "Error setting camera preview: " + e.getMessage());
|
||||
Logger.log_d(TAG, "Error setting camera preview: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback,
|
||||
}catch (Exception e){ }
|
||||
|
||||
requestLayout();
|
||||
|
||||
|
||||
Camera.Parameters camParams = mCamera.getParameters();
|
||||
/*Size optimal = getOptimalPreviewSize(camParams.getSupportedPreviewSizes(), w, h);
|
||||
if(ProjectConstants.DEBUG)
|
||||
@@ -109,20 +109,20 @@ public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback,
|
||||
mCamera.setDisplayOrientation(result);
|
||||
|
||||
mCamera.setPreviewCallback(this);
|
||||
|
||||
|
||||
try {
|
||||
mCamera.setPreviewDisplay(mHolder);
|
||||
mCamera.startPreview();
|
||||
|
||||
}catch (Exception e){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".surfaceChanged() :: Error starting camera preview: " + e.getMessage());
|
||||
Logger.log_d(TAG, CLASS_NAME + ".surfaceChanged() :: Error starting camera preview: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera camera){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPreviewFrame() :: Preview received");
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".onPreviewFrame() :: Frame has" + (camMonitor.hasChanged() ? "" : " not") + " changed.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".onPreviewFrame() :: Preview received");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".onPreviewFrame() :: Frame has" + (camMonitor.hasChanged() ? "" : " not") + " changed.");
|
||||
if(!camMonitor.hasChanged())
|
||||
camMonitor.setImageData(data);
|
||||
}
|
||||
@@ -132,74 +132,74 @@ public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback,
|
||||
}
|
||||
|
||||
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
|
||||
final double ASPECT_TOLERANCE = 0.1;
|
||||
double targetRatio = (double) w / h;
|
||||
if (sizes == null) return null;
|
||||
final double ASPECT_TOLERANCE = 0.1;
|
||||
double targetRatio = (double) w / h;
|
||||
if (sizes == null) return null;
|
||||
|
||||
Size optimalSize = null;
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
Size optimalSize = null;
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
|
||||
int targetHeight = h;
|
||||
int targetHeight = h;
|
||||
|
||||
// Try to find an size match aspect ratio and size
|
||||
for (Size size : sizes) {
|
||||
double ratio = (double) size.width / size.height;
|
||||
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
|
||||
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||
optimalSize = size;
|
||||
minDiff = Math.abs(size.height - targetHeight);
|
||||
}
|
||||
}
|
||||
// Try to find an size match aspect ratio and size
|
||||
for (Size size : sizes) {
|
||||
double ratio = (double) size.width / size.height;
|
||||
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
|
||||
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||
optimalSize = size;
|
||||
minDiff = Math.abs(size.height - targetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot find the one match the aspect ratio, ignore the requirement
|
||||
if (optimalSize == null) {
|
||||
minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||
optimalSize = size;
|
||||
minDiff = Math.abs(size.height - targetHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimalSize;
|
||||
}
|
||||
// Cannot find the one match the aspect ratio, ignore the requirement
|
||||
if (optimalSize == null) {
|
||||
minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||
optimalSize = size;
|
||||
minDiff = Math.abs(size.height - targetHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimalSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
if (changed && getChildCount() > 0) {
|
||||
final View child = getChildAt(0);
|
||||
final View child = getChildAt(0);
|
||||
|
||||
final int width = r - l;
|
||||
final int height = b - t;
|
||||
final int width = r - l;
|
||||
final int height = b - t;
|
||||
|
||||
int previewWidth = width;
|
||||
int previewHeight = height;
|
||||
if (mPreviewSize != null) {
|
||||
previewWidth = mPreviewSize.width;
|
||||
previewHeight = mPreviewSize.height;
|
||||
}
|
||||
int previewWidth = width;
|
||||
int previewHeight = height;
|
||||
if (mPreviewSize != null) {
|
||||
previewWidth = mPreviewSize.width;
|
||||
previewHeight = mPreviewSize.height;
|
||||
}
|
||||
|
||||
// Center the child SurfaceView within the parent.
|
||||
if (width * previewHeight > height * previewWidth) {
|
||||
final int scaledChildWidth = previewWidth * height / previewHeight;
|
||||
child.layout((width - scaledChildWidth) / 2, 0,
|
||||
(width + scaledChildWidth) / 2, height);
|
||||
} else {
|
||||
final int scaledChildHeight = previewHeight * width / previewWidth;
|
||||
child.layout(0, (height - scaledChildHeight) / 2,
|
||||
width, (height + scaledChildHeight) / 2);
|
||||
}
|
||||
}
|
||||
// Center the child SurfaceView within the parent.
|
||||
if (width * previewHeight > height * previewWidth) {
|
||||
final int scaledChildWidth = previewWidth * height / previewHeight;
|
||||
child.layout((width - scaledChildWidth) / 2, 0,
|
||||
(width + scaledChildWidth) / 2, height);
|
||||
} else {
|
||||
final int scaledChildHeight = previewHeight * width / previewWidth;
|
||||
child.layout(0, (height - scaledChildHeight) / 2,
|
||||
width, (height + scaledChildHeight) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
|
||||
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
|
||||
setMeasuredDimension(width, height);
|
||||
|
||||
if (mSupportedPreviewSizes != null) {
|
||||
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
|
||||
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
|
||||
setMeasuredDimension(width, height);
|
||||
|
||||
if (mSupportedPreviewSizes != null) {
|
||||
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
78
src/ve/ucv/ciens/ccg/nxtcam/dialogs/ConnectRobotDialog.java
Normal file
78
src/ve/ucv/ciens/ccg/nxtcam/dialogs/ConnectRobotDialog.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package ve.ucv.ciens.ccg.nxtcam.dialogs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import ve.ucv.ciens.ccg.nxtcam.R;
|
||||
import ve.ucv.ciens.ccg.nxtcam.network.BTCommunicator;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
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;
|
||||
private BTCommunicator btManager;
|
||||
private List<String> devices;
|
||||
private String[] devicesArray;
|
||||
|
||||
public interface ConnectRobotDialogListener{
|
||||
public void onConnectRobotDialogItemClick(DialogFragment dialog, String item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState){
|
||||
// Use the Builder class for convenient dialog construction
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
|
||||
// Fill a list with all the paired LEGO robots.
|
||||
btManager = BTCommunicator.getInstance();
|
||||
devices = new ArrayList<String>();
|
||||
Set<BluetoothDevice> pairedDevices = btManager.getPairedDevices();
|
||||
for (BluetoothDevice device : pairedDevices) {
|
||||
// Put the device in the list only if it's MAC address belongs to LEGO.
|
||||
if(device.getAddress().substring(0, 8).compareTo(ProjectConstants.OUI_LEGO) == 0)
|
||||
devices.add(device.getName() + "\n" + device.getAddress());
|
||||
}
|
||||
devicesArray = devices.toArray(new String[devices.size()]);
|
||||
|
||||
builder.setTitle(R.string.robot_choice).setItems(devicesArray, new DialogInterface.OnClickListener() {
|
||||
|
||||
public void onClick(DialogInterface dialog, int which){
|
||||
Logger.log_d(TAG, CLASS_NAME + ".setItems().onClick( :: User chose: " + devices.get(which));
|
||||
listener.onConnectRobotDialogItemClick(ConnectRobotDialog.this, devices.get(which));
|
||||
}
|
||||
|
||||
}).setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
|
||||
|
||||
public void onClick(DialogInterface dialog, int id){
|
||||
Logger.log_d(TAG, CLASS_NAME + ".setNegativeButton().onClick( :: User canceled.");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// 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.");
|
||||
}
|
||||
}
|
||||
}
|
74
src/ve/ucv/ciens/ccg/nxtcam/dialogs/WifiOnDialog.java
Normal file
74
src/ve/ucv/ciens/ccg/nxtcam/dialogs/WifiOnDialog.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package ve.ucv.ciens.ccg.nxtcam.dialogs;
|
||||
|
||||
import ve.ucv.ciens.ccg.nxtcam.R;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class WifiOnDialog extends DialogFragment {
|
||||
private final String TAG = "NXTCAM_WIFI_DIALOG";
|
||||
private final String CLASS_NAME = WifiOnDialog.class.getSimpleName();
|
||||
|
||||
private WifiOnDialogListener listener;
|
||||
private WifiManager wifiManager;
|
||||
|
||||
public interface WifiOnDialogListener{
|
||||
public void onWifiOnDialogPositiveClick(DialogFragment dialog);
|
||||
public void onWifiOnDialogNegativeClick(DialogFragment dialog);
|
||||
}
|
||||
|
||||
public void setWifiManager(WifiManager wifiManager){
|
||||
this.wifiManager = wifiManager;
|
||||
}
|
||||
|
||||
@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){
|
||||
if(wifiManager != null){
|
||||
wifiManager.setWifiEnabled(true);
|
||||
Logger.log_d(TAG, CLASS_NAME + ".setPositiveButton().onClick() :: setting wifi to on.");
|
||||
if(listener != null)
|
||||
listener.onWifiOnDialogPositiveClick(WifiOnDialog.this);
|
||||
}else{
|
||||
Logger.log_wtf(TAG, CLASS_NAME + ".setPositiveButton().onClick( :: wifiManager is null! Doing nothing.");
|
||||
if(listener != null)
|
||||
listener.onWifiOnDialogNegativeClick(WifiOnDialog.this);
|
||||
}
|
||||
}
|
||||
|
||||
}).setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
|
||||
|
||||
public void onClick(DialogInterface dialog, int id){
|
||||
Logger.log_d(TAG, CLASS_NAME + ".setPositiveButton().onClick( :: User canceled.");
|
||||
if(listener != null)
|
||||
listener.onWifiOnDialogNegativeClick(WifiOnDialog.this);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Create the AlertDialog object and return it
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity){
|
||||
super.onAttach(activity);
|
||||
|
||||
try{
|
||||
listener = (WifiOnDialogListener)activity;
|
||||
}catch(ClassCastException cce){
|
||||
listener = null;
|
||||
throw new ClassCastException(CLASS_NAME + ".onAttach() :: " + activity.toString() + "Must implement WifiOnDialogListener.");
|
||||
}
|
||||
}
|
||||
}
|
230
src/ve/ucv/ciens/ccg/nxtcam/network/BTCommunicator.java
Normal file
230
src/ve/ucv/ciens/ccg/nxtcam/network/BTCommunicator.java
Normal file
@@ -0,0 +1,230 @@
|
||||
package ve.ucv.ciens.ccg.nxtcam.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants;
|
||||
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 <miguel.astor@ciens.ucv.ve>
|
||||
* @version 1.0
|
||||
* @since 2012-10-15
|
||||
*/
|
||||
public class BTCommunicator{
|
||||
private static final String TAG = "NXTCAM_BTCOMM";
|
||||
private final String CLASS_NAME = BTCommunicator.class.getSimpleName();
|
||||
|
||||
private boolean connected;
|
||||
private BluetoothAdapter btAdapter = null;
|
||||
private BluetoothSocket btSocket = null;
|
||||
private OutputStream nxtOutputStream = null;
|
||||
private InputStream nxtInputStream = 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;
|
||||
btAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
btSocket = null;
|
||||
nxtInputStream = null;
|
||||
nxtOutputStream = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if Bluetooth is available on the device.
|
||||
*
|
||||
* @return true if the default Bluetooth adapter exists, otherwise false.
|
||||
*/
|
||||
public boolean isBTSupported(){
|
||||
return btAdapter != 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 btAdapter.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to the standard method for stopping this device's Bluetooth adapter.
|
||||
*
|
||||
* @see android.bluetooth.BluetoothAdapter
|
||||
*/
|
||||
public void disableBT(){
|
||||
btAdapter.disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the devices paired to the default Bluetooth adapter.
|
||||
*
|
||||
* @return A set containing all devices paired to this device.
|
||||
*/
|
||||
public Set<BluetoothDevice> getPairedDevices(){
|
||||
return btAdapter.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 macAddress The mac address of the target device.
|
||||
* @return true if the connection was established succesfully, otherwise false.
|
||||
* @throws IOException
|
||||
*/
|
||||
public boolean establishConnection(String macAddress) throws IOException{
|
||||
if (!btAdapter.isEnabled()){
|
||||
return false;
|
||||
}
|
||||
if(connected){
|
||||
return false;
|
||||
}
|
||||
if(btAdapter.isEnabled()){
|
||||
if(macAddress == "NONE"){
|
||||
return false;
|
||||
}else{
|
||||
if(macAddress.substring(0, 8).compareTo(ProjectConstants.OUI_LEGO) != 0){
|
||||
Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Not a Lego MAC. Prefix : " + macAddress.substring(0, 8) + " :: OUI : " + ProjectConstants.OUI_LEGO);
|
||||
return false;
|
||||
}else{
|
||||
try{
|
||||
Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Getting device with mac address: " + macAddress);
|
||||
BluetoothDevice nxtDevice = null;
|
||||
nxtDevice = btAdapter.getRemoteDevice(macAddress);
|
||||
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.");
|
||||
btSocket = nxtDevice.createRfcommSocketToServiceRecord(ProjectConstants.SERIAL_PORT_SERVICE_CLASS_UUID);
|
||||
Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Connecting.");
|
||||
btSocket.connect();
|
||||
|
||||
Logger.log_d(TAG, CLASS_NAME + ".establishConnection() :: Opening IO streams.");
|
||||
nxtInputStream = btSocket.getInputStream();
|
||||
nxtOutputStream = btSocket.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(btSocket != null){
|
||||
Logger.log_d(TAG, CLASS_NAME + ".stopConnection() :: Closing connection.");
|
||||
btSocket.close();
|
||||
btSocket = null;
|
||||
nxtInputStream = null;
|
||||
nxtOutputStream = 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{
|
||||
nxtOutputStream.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;
|
||||
}
|
||||
nxtInputStream.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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,14 +10,13 @@ import java.net.Socket;
|
||||
|
||||
import ve.ucv.ciens.ccg.nxtcam.camera.CameraImageMonitor;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.Logger;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.Logger.LOG_TYPES;
|
||||
import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants;
|
||||
|
||||
public class ImageTransferThread extends Thread{
|
||||
private final String TAG = "IM_THREAD";
|
||||
private final String CLASS_NAME = ImageTransferThread.class.getSimpleName();
|
||||
|
||||
private boolean pause, done, connected;
|
||||
private boolean pause, done;
|
||||
private Object threadPauseMonitor;
|
||||
private CameraImageMonitor camMonitor;
|
||||
private Socket socket;
|
||||
@@ -30,7 +29,6 @@ public class ImageTransferThread extends Thread{
|
||||
this.serverIp = serverIp;
|
||||
pause = false;
|
||||
done = false;
|
||||
connected = false;
|
||||
threadPauseMonitor = new Object();
|
||||
socket = null;
|
||||
writer = null;
|
||||
@@ -41,7 +39,7 @@ public class ImageTransferThread extends Thread{
|
||||
public void run(){
|
||||
connectToServer();
|
||||
if(socket.isConnected()){
|
||||
Logger.log(Logger.LOG_TYPES.ERROR, TAG, CLASS_NAME + ".run() :: Not connected to a server. Finishing thread.");
|
||||
Logger.log_e(TAG, CLASS_NAME + ".run() :: Not connected to a server. Finishing thread.");
|
||||
}else{
|
||||
while(!done){
|
||||
checkPause();
|
||||
@@ -53,13 +51,13 @@ public class ImageTransferThread extends Thread{
|
||||
|
||||
private void connectToServer(){
|
||||
try{
|
||||
Logger.log(Logger.LOG_TYPES.INFO, TAG, CLASS_NAME + ".connectToServer() :: Connecting to the server at " + serverIp);
|
||||
Logger.log_i(TAG, CLASS_NAME + ".connectToServer() :: Connecting to the server at " + serverIp);
|
||||
socket = new Socket(InetAddress.getByName(serverIp), ProjectConstants.SERVER_TCP_PORT_1);
|
||||
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
Logger.log(Logger.LOG_TYPES.INFO, TAG, CLASS_NAME + ".connectToServer() :: Connection successful.");
|
||||
Logger.log_i(TAG, CLASS_NAME + ".connectToServer() :: Connection successful.");
|
||||
}catch(IOException io){
|
||||
Logger.log(Logger.LOG_TYPES.ERROR, TAG, CLASS_NAME + ".connectToServer() :: Connection failed with message: " + io.getMessage());
|
||||
Logger.log_e(TAG, CLASS_NAME + ".connectToServer() :: Connection failed with message: " + io.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,20 +66,20 @@ public class ImageTransferThread extends Thread{
|
||||
try{
|
||||
socket.close();
|
||||
}catch (IOException io) {
|
||||
Logger.log(Logger.LOG_TYPES.ERROR, TAG, CLASS_NAME + ".connectToServer() :: " + io.getMessage());
|
||||
Logger.log_e(TAG, CLASS_NAME + ".connectToServer() :: " + io.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void finish(){
|
||||
done = true;
|
||||
Logger.log(Logger.LOG_TYPES.INFO, TAG, CLASS_NAME + ".finish() :: Finishing thread.");
|
||||
Logger.log_i(TAG, CLASS_NAME + ".finish() :: Finishing thread.");
|
||||
}
|
||||
|
||||
private void checkPause(){
|
||||
synchronized (threadPauseMonitor){
|
||||
while(pause){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".checkPause() :: Pause requested.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".checkPause() :: Pause requested.");
|
||||
try{ threadPauseMonitor.wait(); }catch(InterruptedException ie){}
|
||||
}
|
||||
}
|
||||
@@ -89,11 +87,11 @@ public class ImageTransferThread extends Thread{
|
||||
|
||||
public synchronized void pauseThread(){
|
||||
pause = true;
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".pauseThread() :: Pausing thread.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".pauseThread() :: Pausing thread.");
|
||||
}
|
||||
|
||||
public synchronized void resumeThread(){
|
||||
Logger.log(Logger.LOG_TYPES.DEBUG, TAG, CLASS_NAME + ".resumeThread() :: Resuming thread.");
|
||||
Logger.log_d(TAG, CLASS_NAME + ".resumeThread() :: Resuming thread.");
|
||||
synchronized (threadPauseMonitor) {
|
||||
pause = false;
|
||||
threadPauseMonitor.notifyAll();
|
||||
|
@@ -3,30 +3,27 @@ package ve.ucv.ciens.ccg.nxtcam.utils;
|
||||
import android.util.Log;
|
||||
|
||||
public abstract class Logger {
|
||||
public static enum LOG_TYPES{ DEBUG, INFO, WARN, ERROR, VERBOSE, WTF }
|
||||
|
||||
public static void log(LOG_TYPES log_type, String tag, String msg){
|
||||
if(ProjectConstants.DEBUG){
|
||||
switch(log_type){
|
||||
case DEBUG:
|
||||
Log.d(tag, msg);
|
||||
break;
|
||||
case INFO:
|
||||
Log.i(tag, msg);
|
||||
break;
|
||||
case WARN:
|
||||
Log.w(tag, msg);
|
||||
break;
|
||||
case ERROR:
|
||||
Log.e(tag, msg);
|
||||
break;
|
||||
case VERBOSE:
|
||||
Log.v(tag, msg);
|
||||
break;
|
||||
case WTF:
|
||||
Log.wtf(tag, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static void log_d(String tag, String msg){
|
||||
if(ProjectConstants.DEBUG) Log.d(tag, msg);
|
||||
}
|
||||
|
||||
public static void log_i(String tag, String msg){
|
||||
if(ProjectConstants.DEBUG) Log.i(tag, msg);
|
||||
}
|
||||
|
||||
public static void log_v(String tag, String msg){
|
||||
if(ProjectConstants.DEBUG) Log.v(tag, msg);
|
||||
}
|
||||
|
||||
public static void log_w(String tag, String msg){
|
||||
if(ProjectConstants.DEBUG) Log.w(tag, msg);
|
||||
}
|
||||
|
||||
public static void log_e(String tag, String msg){
|
||||
if(ProjectConstants.DEBUG) Log.e(tag, msg);
|
||||
}
|
||||
|
||||
public static void log_wtf(String tag, String msg){
|
||||
if(ProjectConstants.DEBUG) Log.wtf(tag, msg);
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,14 @@
|
||||
package ve.ucv.ciens.ccg.nxtcam.utils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class ProjectConstants {
|
||||
public static final int SERVER_UDP_PORT = 8889;
|
||||
public static final int SERVER_TCP_PORT_1 = 9989;
|
||||
public static final int SERVER_TCP_PORT_2 = 9990;
|
||||
|
||||
public static final UUID SERIAL_PORT_SERVICE_CLASS_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
||||
public static final String OUI_LEGO = "00:16:53";
|
||||
public static final String MULTICAST_ADDRESS = "230.0.0.1";
|
||||
|
||||
|
||||
public static final boolean DEBUG = true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user