400 lines
13 KiB
Java
400 lines
13 KiB
Java
/**
|
|
* Copyright 2011 Guenther Hoelzl
|
|
*
|
|
* This file is part of MINDdroid.
|
|
*
|
|
* MINDdroid is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* MINDdroid is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with MINDdroid. If not, see <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
package com.lego.minddroid;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.app.ProgressDialog;
|
|
import android.bluetooth.BluetoothAdapter;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.view.View;
|
|
import android.view.View.OnClickListener;
|
|
import android.widget.Button;
|
|
import android.widget.TextView;
|
|
import android.widget.Toast;
|
|
|
|
/**
|
|
* This class is for uploading programs to the NXT brick via Bluetooth.
|
|
* Special programs will be able to communicate with MINDdroid, so no PC
|
|
* is required for playing with a robot.
|
|
*/
|
|
public class NXJUploader extends Activity implements UploadThreadListener, DialogListener, BTConnectable
|
|
{
|
|
private static final int DIALOG_NXT = 0;
|
|
private static final int DIALOG_FILE = 1;
|
|
|
|
// preinstalled modules on res/raw/directoy
|
|
private static String[] preinstalledNXJstring = new String[]
|
|
{ "AlphaRex.nxj",
|
|
"MINDGameZ.nxj"
|
|
};
|
|
|
|
private static final int REQUEST_CONNECT_DEVICE = 1000;
|
|
private static final int REQUEST_ENABLE_BT = 2000;
|
|
|
|
private BTCommunicator mNXT;
|
|
private UploadThread uploadThread;
|
|
private Handler handler;
|
|
private ProgressDialog progressDialog;
|
|
private int uploadStatus;
|
|
private int runningDialog;
|
|
private boolean pairing;
|
|
private boolean btErrorPending = false;
|
|
private static boolean btOnByUs = false;
|
|
|
|
/**
|
|
* Called when the activity is first created.
|
|
*/
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState)
|
|
{
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.nxjuploader);
|
|
initLayout();
|
|
|
|
// Create objects for communication
|
|
mNXT = new BTCommunicator(this, null, BluetoothAdapter.getDefaultAdapter(), getResources());
|
|
handler = new Handler();
|
|
// Create and launch the upload thread
|
|
uploadThread = new UploadThread(this, getResources());
|
|
uploadThread.setBluetoothCommunicator(mNXT);
|
|
uploadThread.start();
|
|
}
|
|
|
|
@Override
|
|
protected void onStart() {
|
|
super.onStart();
|
|
|
|
if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
|
|
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
|
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when the activity is destroyed.
|
|
*/
|
|
@Override
|
|
protected void onDestroy() {
|
|
super.onDestroy();
|
|
|
|
// request the uploadthread to stop
|
|
uploadThread.requestStop();
|
|
}
|
|
|
|
/**
|
|
* Asks if bluetooth was switched on during the runtime of the app. For saving
|
|
* battery we switch it off when the app is terminated.
|
|
* @return true, when bluetooth was switched on by the app
|
|
*/
|
|
public static boolean isBtOnByUs() {
|
|
return btOnByUs;
|
|
}
|
|
|
|
/**
|
|
* Sets a flag when bluetooth was switched on durin runtime
|
|
* @param btOnByUs true, when bluetooth was switched on by the app
|
|
*/
|
|
public static void setBtOnByUs(boolean btOnByUs) {
|
|
NXJUploader.btOnByUs = btOnByUs;
|
|
}
|
|
|
|
/**
|
|
* @return true, when currently pairing
|
|
*/
|
|
@Override
|
|
public boolean isPairing() {
|
|
return pairing;
|
|
}
|
|
|
|
/**
|
|
* Displays a message as a toast
|
|
*/
|
|
public void showToast(String message) {
|
|
Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
|
|
toast.show();
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Displays a message from resID as a toast
|
|
*/
|
|
public void showToast(int resID) {
|
|
Toast toast = Toast.makeText(this, resID, Toast.LENGTH_SHORT);
|
|
toast.show();
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Displays resp. updates a progress dialog
|
|
*/
|
|
public void showProgressDialog(String message, int maxProgress, int currentProgress) {
|
|
boolean initialized = false;
|
|
if (progressDialog == null) {
|
|
initialized = true;
|
|
progressDialog = new ProgressDialog(this);
|
|
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
|
progressDialog.setCancelable(false);
|
|
progressDialog.setMessage(message);
|
|
}
|
|
progressDialog.setMax(maxProgress);
|
|
progressDialog.setProgress(currentProgress);
|
|
if (initialized)
|
|
progressDialog.show();
|
|
}
|
|
|
|
/**
|
|
* Displays resp. updates a progress dialog
|
|
*/
|
|
public void showProgressDialog(String message) {
|
|
if (progressDialog == null) {
|
|
progressDialog = new ProgressDialog(this);
|
|
progressDialog.setCancelable(false);
|
|
progressDialog.setMessage(message);
|
|
progressDialog.show();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dismisses an existing progress dialog
|
|
*/
|
|
public void dismissProgressDialog() {
|
|
if (progressDialog != null) {
|
|
progressDialog.dismiss();
|
|
progressDialog = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes the values on the main screen
|
|
*/
|
|
private void initLayout() {
|
|
initNXTButton();
|
|
initFileButton();
|
|
initUploadButton();
|
|
}
|
|
|
|
/**
|
|
* Initializes the "SELECT NXT" button
|
|
*/
|
|
private void initNXTButton() {
|
|
Button fileButton = (Button) findViewById(R.id.nxt_button);
|
|
fileButton.setOnClickListener(new OnClickListener() {
|
|
public void onClick(View v) {
|
|
selectNXT();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes the "SELECT FILE" button
|
|
*/
|
|
private void initFileButton() {
|
|
Button fileButton = (Button) findViewById(R.id.file_button);
|
|
fileButton.setOnClickListener(new OnClickListener() {
|
|
public void onClick(View v) {
|
|
showFileDialog();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Starts the NXT selection activity
|
|
*/
|
|
private void selectNXT() {
|
|
Intent serverIntent = new Intent(this, DeviceListActivity.class);
|
|
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
|
|
}
|
|
|
|
/**
|
|
* Shows the file dialog
|
|
*/
|
|
private void showFileDialog() {
|
|
NXJFileDialog fileDialog = new NXJFileDialog(this, this);
|
|
if (fileDialog.refreshFileList(preinstalledNXJstring) == 0)
|
|
showToast(R.string.nxj_no_files);
|
|
else {
|
|
runningDialog = DIALOG_FILE;
|
|
fileDialog.show();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This is the method for returning values of dialogs
|
|
* @param the selected text
|
|
*/
|
|
@Override
|
|
public void dialogUpdate(String text) {
|
|
TextView textView;
|
|
switch (runningDialog) {
|
|
case DIALOG_NXT:
|
|
textView = (TextView) findViewById(R.id.nxt_name);
|
|
textView.setText(text);
|
|
break;
|
|
|
|
case DIALOG_FILE:
|
|
textView = (TextView) findViewById(R.id.nxj_file_name);
|
|
textView.setText(text);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes the "UPLOAD" button
|
|
*/
|
|
private void initUploadButton() {
|
|
Button uploadButton = (Button) findViewById(R.id.upload_button);
|
|
uploadButton.setOnClickListener(new OnClickListener() {
|
|
public void onClick(View v) {
|
|
TextView nxtTextView = (TextView) findViewById(R.id.nxt_name);
|
|
String macAddress = nxtTextView.getText().toString();
|
|
if (macAddress.compareTo("") == 0) {
|
|
showToast(R.string.nxj_please_select_nxt);
|
|
return;
|
|
}
|
|
macAddress = macAddress.substring(macAddress.lastIndexOf('-')+1);
|
|
TextView nxjTextView = (TextView) findViewById(R.id.nxj_file_name);
|
|
String fileName = nxjTextView.getText().toString();
|
|
if (fileName.compareTo("") == 0) {
|
|
showToast(R.string.nxj_please_select_file);
|
|
return;
|
|
}
|
|
uploadThread.enqueueUpload(macAddress, fileName);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* This will be called by the UploadThread to signal an update of the
|
|
* current status.
|
|
* @param status The current state of the UploadThread
|
|
*/
|
|
@Override
|
|
public void handleUploadThreadUpdate(final int status) {
|
|
handler.post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (status != uploadStatus) {
|
|
dismissProgressDialog();
|
|
uploadStatus = status;
|
|
}
|
|
showUploadStatus();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Shows the current status of the uploader either in
|
|
* a progress bar or in toast in case of an error.
|
|
*/
|
|
private void showUploadStatus() {
|
|
|
|
switch (uploadStatus) {
|
|
case UploadThread.CONNECTING:
|
|
showProgressDialog(getResources().getString(R.string.nxj_connecting));
|
|
break;
|
|
case UploadThread.UPLOADING:
|
|
showProgressDialog(getResources().getString(R.string.nxj_uploading),
|
|
uploadThread.getFileLength(),
|
|
uploadThread.getBytesUploaded());
|
|
break;
|
|
default:
|
|
dismissProgressDialog();
|
|
}
|
|
|
|
switch (uploadThread.getErrorCode()) {
|
|
case UploadThread.NO_ERROR:
|
|
break;
|
|
case UploadThread.OPEN_BT_ERROR:
|
|
if (pairing)
|
|
showToast(R.string.nxj_bluetooth_pairing);
|
|
else
|
|
showBTErrorDialog();
|
|
break;
|
|
case UploadThread.CLOSE_BT_ERROR:
|
|
showBTErrorDialog();
|
|
break;
|
|
case UploadThread.OPEN_FILE_ERROR:
|
|
showToast(R.string.nxj_file_open_error);
|
|
break;
|
|
case UploadThread.UPLOAD_ERROR:
|
|
showBTErrorDialog();
|
|
break;
|
|
default:
|
|
showToast(R.string.nxj_other_error);
|
|
}
|
|
uploadThread.resetErrorCode();
|
|
}
|
|
|
|
/**
|
|
* Shows an error dialog when there's an error regarding
|
|
* bluettooth transfer.
|
|
*/
|
|
private void showBTErrorDialog() {
|
|
if (btErrorPending == false) {
|
|
btErrorPending = true;
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setTitle(getResources().getString(R.string.bt_error_dialog_title))
|
|
.setMessage(getResources().getString(R.string.bt_error_dialog_message)).setCancelable(false)
|
|
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
btErrorPending = false;
|
|
dialog.cancel();
|
|
}
|
|
});
|
|
builder.create().show();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
switch (requestCode) {
|
|
case REQUEST_CONNECT_DEVICE:
|
|
// When DeviceListActivity returns with a device to connect
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
// Get the device infos
|
|
String infos = data.getExtras().getString(DeviceListActivity.DEVICE_NAME_AND_ADDRESS);
|
|
pairing = data.getExtras().getBoolean(DeviceListActivity.PAIRING);
|
|
TextView textView = (TextView) findViewById(R.id.nxt_name);
|
|
textView.setText(infos);
|
|
}
|
|
break;
|
|
|
|
case REQUEST_ENABLE_BT:
|
|
// When the request to enable Bluetooth returns
|
|
switch (resultCode) {
|
|
case Activity.RESULT_OK:
|
|
btOnByUs = true;
|
|
break;
|
|
case Activity.RESULT_CANCELED:
|
|
showToast(R.string.bt_needs_to_be_enabled);
|
|
finish();
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|