Skip to content

Commit

Permalink
Simplify code for erasing a folder, and handling error messages diffe…
Browse files Browse the repository at this point in the history
…rently to debug messages.
  • Loading branch information
medape committed Oct 4, 2019
1 parent b936139 commit 7d54a6a
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 112 deletions.
155 changes: 54 additions & 101 deletions app/src/main/java/com/simonramstedt/yoke/YokeActivity.java
Expand Up @@ -42,8 +42,6 @@
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -82,67 +80,34 @@ private void log(String m) {
Log.d("Yoke", m);
}

protected boolean deleteByManifest(File joypadPath) {
String errorMessage;
try {
File manifestPath = new File(joypadPath, "manifest");
if (manifestPath.exists()) {
BufferedReader inputBR = new BufferedReader(
new FileReader(manifestPath)
);
String line = "";
StringBuilder manifestSB = new StringBuilder();
while ((line = inputBR.readLine()) != null) {
manifestSB.append(line).append("\n");
}
JSONObject manifestJSON = new JSONObject(manifestSB.toString());
private void logToast(String m) {
Log.e("Yoke", m);
YokeActivity.this.runOnUiThread(() -> {
Toast.makeText(YokeActivity.this, m, Toast.LENGTH_LONG).show();
});
}

JSONArray erasables = manifestJSON.getJSONArray("files");
for (int i = erasables.length() - 1; i >= 0; i--) {
File currentFile = new File(joypadPath, erasables.getString(i));
if (!currentFile.delete()) {
throw new IOException(String.format(res.getString(R.string.log_could_not_delete), currentFile.toString()));
}
}
erasables = manifestJSON.getJSONArray("folders");
String[] folders = new String[erasables.length()];
for (int i = folders.length - 1; i >= 0; i--) {
folders[i] = erasables.getString(i);
}
Arrays.sort(folders, new ByFolderDepth());
for (int i = folders.length - 1; i >= 0; i--) {
File currentFile = new File(joypadPath, folders[i]);
if (!currentFile.delete()) {
throw new IOException(String.format(res.getString(R.string.log_could_not_delete), currentFile));
}
}
if (!manifestPath.delete()) {
throw new IOException(String.format(res.getString(R.string.log_could_not_delete), manifestPath.toString()));
protected void deleteRecursively(File joypadPath) throws IOException {
ArrayList<File> erasables = new ArrayList<>();
erasables.add(joypadPath);
for (int i = 0; i < erasables.size(); i++) {
// don't optimize the line above. The ArrayList will be modified at every iteration.
File folder = erasables.get(i);
if (folder.isDirectory()) {
for (String entry : folder.list()) {
erasables.add(new File(folder, entry));
}
}
if (!joypadPath.delete()) {
throw new IOException(String.format(res.getString(R.string.log_could_not_delete), joypadPath.toString()));
}
// Files should already be ordered by depth, so we iterate backwards:
for (int i = erasables.size() - 1; i >= 0; i--) {
File currentFile = erasables.get(i);
if (!currentFile.delete()) {
throw new IOException(String.format(res.getString(R.string.error_could_not_delete), currentFile));
}
return true;
} catch (IOException e) {
errorMessage = String.format(res.getString(R.string.log_could_not_delete), e.getMessage());
log(errorMessage);
Toast.makeText(YokeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
return false;
} catch (JSONException e) {
errorMessage = String.format(res.getString(R.string.log_json_exception), e.getLocalizedMessage());
log(errorMessage);
Toast.makeText(YokeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
return false;
} catch (SecurityException e) {
errorMessage = String.format(res.getString(R.string.log_security_exception), e.getLocalizedMessage());
log(errorMessage);
Toast.makeText(YokeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
return false;
}
}


class WebAppInterface {
Context mContext;

Expand All @@ -159,13 +124,6 @@ public void update_vals(String vals) {
}
}

static class ByFolderDepth implements Comparator<String> {
public int compare(String f1, String f2) {
return (f1.toString().split(File.pathSeparator).length) -
(f2.toString().split(File.pathSeparator).length);
}
}

// https://stackoverflow.com/questions/15758856/android-how-to-download-file-from-webserver/
class DownloadFilesFromURL extends AsyncTask<String, String, String> {
public String errorMessage = null;
Expand All @@ -175,21 +133,18 @@ protected void onPreExecute() {
super.onPreExecute();
mTextView.setText(res.getString(R.string.toolbar_downloading));
try {
if (futureJoypadPath.exists() && !deleteByManifest(futureJoypadPath)) {
throw new IOException();
if (futureJoypadPath.exists()) {
deleteRecursively(futureJoypadPath);
}
log(String.format(res.getString(R.string.log_creating_folder), futureJoypadPath.getAbsolutePath()));
if (!futureJoypadPath.mkdirs()) {
errorMessage = String.format(res.getString(R.string.log_could_not_create), futureJoypadPath.getAbsolutePath());
log(errorMessage);
Toast.makeText(YokeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
throw new IOException(String.format(res.getString(R.string.error_could_not_create), futureJoypadPath.getAbsolutePath()));
}
} catch (SecurityException e) {
errorMessage = String.format(res.getString(R.string.log_security_exception), e.getLocalizedMessage());
log(errorMessage);
Toast.makeText(YokeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
logToast(String.format(res.getString(R.string.error_security_exception), e.getMessage()));
cancel(true);
} catch (IOException e) {
//already reported, no need to do anything except abort the thread
logToast(String.format(res.getString(R.string.error_io_exception), e.getMessage()));
cancel(true);
}
}
Expand Down Expand Up @@ -219,18 +174,18 @@ protected String doInBackground(String... f_url) {

long totalBytes = manifestJSON.optLong("size", -1);
JSONArray entries = manifestJSON.getJSONArray("folders");
for (int i=entries.length() - 1; i >= 0; i--) {
for (int i = 0, length = entries.length(); i < length; i++) {
File newFolder = new File(futureJoypadPath, entries.getString(i));
log(String.format(res.getString(R.string.log_creating_folder), newFolder.getAbsolutePath()));
if (!newFolder.mkdirs()) {
errorMessage = String.format(res.getString(R.string.log_could_not_create), newFolder.getAbsolutePath());
errorMessage = String.format(res.getString(R.string.error_could_not_create), newFolder.getAbsolutePath());
cancel(true);
}
}

entries = manifestJSON.getJSONArray("files");
long cumulativeBytes = 0;
for (int i=entries.length() - 1; i >= 0; i--) {
for (int i = 0, length=entries.length(); i < length; i++) {
File newFile = new File(futureJoypadPath, entries.getString(i));
log(String.format(res.getString(R.string.log_downloading_file), newFile.getAbsolutePath()));
url = new URL(f_url[0] + entries.getString(i));
Expand All @@ -248,17 +203,16 @@ protected String doInBackground(String... f_url) {
input.close();
}
} catch (IOException e) {
errorMessage = String.format(res.getString(R.string.log_io_exception), e.getLocalizedMessage());
logToast(String.format(res.getString(R.string.error_io_exception), e.getMessage()));
cancel(true);
} catch (JSONException e) {
errorMessage = String.format(res.getString(R.string.log_json_exception), e.getLocalizedMessage());
logToast(String.format(res.getString(R.string.error_json_exception), e.getMessage()));
log(manifestSB.toString());
cancel(true);
} catch (SecurityException e) {
errorMessage = String.format(res.getString(R.string.log_security_exception), e.getLocalizedMessage());
logToast(String.format(res.getString(R.string.error_security_exception), e.getMessage()));
cancel(true);
}

return null;
}

Expand All @@ -268,10 +222,18 @@ protected void onProgressUpdate(String... progress) {

@Override
protected void onPostExecute(String file_url) {
if (currentJoypadPath.exists()) {
deleteByManifest(currentJoypadPath);
try {
if (currentJoypadPath.exists()) {
deleteRecursively(currentJoypadPath);
}
if (!futureJoypadPath.renameTo(currentJoypadPath)) {
logToast(String.format(res.getString(R.string.error_could_not_rename), futureJoypadPath.getAbsolutePath()));
cancel(true);
}
} catch (IOException e) {
logToast(String.format(res.getString(R.string.error_io_exception), e.getMessage()));
cancel(true);
}
futureJoypadPath.renameTo(currentJoypadPath);
String url = "file://" + new File(currentJoypadPath, "main.html").toString();
mTextView.setText(res.getString(R.string.toolbar_connected_to));
wv.loadUrl(url);
Expand All @@ -280,11 +242,7 @@ protected void onPostExecute(String file_url) {

@Override
protected void onCancelled() {
if (errorMessage != null) {
log(errorMessage);
Toast.makeText(YokeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
}
mTextView.setText(res.getString(R.string.toolbar_connected_to));
mTextView.setText(res.getString(R.string.toolbar_connected_to));
}
}

Expand Down Expand Up @@ -473,9 +431,9 @@ public void send(byte[] msg) {
try {
mSocket.send(new DatagramPacket(msg, msg.length));
} catch (IOException e) {
log(String.format(res.getString(R.string.log_send_error), e.getLocalizedMessage()));
logToast(String.format(res.getString(R.string.error_io_exception_while_sending), e.getMessage()));
} catch (NullPointerException e) {
log(String.format(res.getString(R.string.log_send_error), e.getLocalizedMessage()));
logToast(String.format(res.getString(R.string.error_null_pointer_exception_while_sending), e.getMessage()));
}
}

Expand Down Expand Up @@ -531,23 +489,18 @@ public void openSocket(String host, int port) {
mSocket.connect(InetAddress.getByName(host), port);

log(res.getString(R.string.log_open_udp_success));
YokeActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
new DownloadFilesFromURL().execute(
"http://" + host + ":" + port + "/"
);
}
YokeActivity.this.runOnUiThread(() -> {
new DownloadFilesFromURL().execute(
"http://" + host + ":" + port + "/"
);
});

} catch (SocketException | UnknownHostException e) {
mSocket = null;
YokeActivity.this.runOnUiThread(() -> {
mSpinner.setSelection(mAdapter.getPosition(NOTHING));
Toast.makeText(YokeActivity.this, String.format(res.getString(R.string.toast_could_not_connect), host, port), Toast.LENGTH_LONG).show();
});
log(res.getString(R.string.log_open_udp_error));
e.printStackTrace();
logToast(String.format(res.getString(R.string.error_open_udp_error), host, port));
}
}

Expand Down Expand Up @@ -591,13 +544,13 @@ public void onDiscoveryStopped(String serviceType) {

@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
log(String.format(res.getString(R.string.log_discovery_error), errorCode));
logToast(String.format(res.getString(R.string.error_discovery_failed), errorCode));
mNsdManager.stopServiceDiscovery(this);
}

@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
log(String.format(res.getString(R.string.log_discovery_error), errorCode));
logToast(String.format(res.getString(R.string.error_discovery_failed), errorCode));
mNsdManager.stopServiceDiscovery(this);
}

Expand Down
26 changes: 15 additions & 11 deletions app/src/main/res/values/strings.xml
Expand Up @@ -12,9 +12,9 @@
<!-- Downloading new layout -->
<string name="toolbar_downloading">Downloading from</string>

<!-- Toasts shown on error -->
<!-- Toasts shown on user mistake -->
<string name="toast_could_not_connect">Failed to connect to %1$s:%2$d.</string>
<string name="toast_invalid_address">Invalid address</string>
<string name="toast_invalid_address">Invalid address.</string>
<string name="toast_cant_reconnect_if_not_connected">Please use the dropdown menu to connect to a machine.</string>

<!-- These strings are displayed when the user opens the spinner to select a machine to connect to -->
Expand All @@ -28,26 +28,30 @@
<string name="enter_ip_ok">OK</string>
<string name="enter_ip_cancel">Cancel</string>

<!-- Error messages. The same string is displayed to the user than in the logcat.
(If they're not going to be able to fix it, better be specific) -->
<string name="error_discovery_failed">Service discovery failed with error code %1$d.</string>
<string name="error_open_udp_error">Failed to open UDP socket to %1$s:%2$d.</string>
<string name="error_could_not_create">Could not create %1$s</string>
<string name="error_could_not_delete">Could not delete %1$s</string>
<string name="error_could_not_rename">Could not rename %1$s</string>
<string name="error_io_exception">Read/write error (IOException): %1$s.</string>
<string name="error_json_exception">Error parsing manifest (JSONException): %1$s.</string>
<string name="error_security_exception">Security Manager prevents reading or writing (SecurityException): %1$s.</string>
<string name="error_io_exception_while_sending">Error sending status (IOException). Reason: %1$s</string>
<string name="error_null_pointer_exception_while_sending">Error sending status (NullPointerException). Reason: %1$s</string>

<!-- Debug messages -->
<string name="log_adding_address">Adding %1$s…</string>
<string name="log_could_not_create">Could not create %1$s</string>
<string name="log_could_not_delete">Could not delete %1$s</string>
<string name="log_could_not_rename">Could not rename %1$s</string>
<string name="log_creating_folder">Creating local folder %1$s</string>
<string name="log_directly_connecting">Connecting directly to IP address %1$s…</string>
<string name="log_downloading_file">Downloading file to %1$s</string>
<string name="log_discovery_error">Service discovery failed with error code %1$d.</string>
<string name="log_discovery_started">Service discovery \"%1$s\" started.</string>
<string name="log_discovery_stopped">Service discovery \"%1$s\" stopped.</string>
<string name="log_io_exception">I/O Exception: %1$s.</string>
<string name="log_json_exception">JSON Exception: %1$s.</string>
<string name="log_loading_url">Loading from %1$s</string>
<string name="log_nothing_selected">Nothing selected.</string>
<string name="log_open_udp_error">Failed to open UDP socket. Error message following:</string>
<string name="log_open_udp_success">Connected.</string>
<string name="log_opening_udp">Trying to open UDP socket to %1$s on port %2$d…</string>
<string name="log_security_exception">Security Exception: %1$s.</string>
<string name="log_send_error">Error while sending message \"%1$s\".</string>
<string name="log_service_found">Service found. </string>
<string name="log_service_lost">Service lost. </string>
<string name="log_service_not_null">SERVICE NOT NULL!!!</string>
Expand Down

0 comments on commit 7d54a6a

Please sign in to comment.