Extracted SyncthingRunnable into seperate file.

This commit is contained in:
Felix Ableitner 2014-08-01 23:36:41 +02:00
parent 690190850e
commit b0006db5c8
2 changed files with 144 additions and 114 deletions

View File

@ -0,0 +1,136 @@
package com.nutomic.syncthingandroid.syncthing;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.util.Log;
import android.view.WindowManager;
import com.nutomic.syncthingandroid.R;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Runs the syncthing binary from command line, and prints its output to logcat.
*/
public class SyncthingRunnable implements Runnable {
private static final String TAG = "SyncthingRunnable";
private static final String TAG_NATIVE = "SyncthingNativeCode";
/**
* Path to the native, integrated syncthing binary, relative to the data folder
*/
private static final String BINARY_NAME = "lib/libsyncthing.so";
private Handler mHandler;
private Context mContext;
public SyncthingRunnable(Context context) {
mContext = context;
mHandler = new Handler();
}
@Override
public void run() {
DataOutputStream dos = null;
int ret = 1;
Process process = null;
try {
process = Runtime.getRuntime().exec("sh");
dos = new DataOutputStream(process.getOutputStream());
// Set home directory to data folder for syncthing to use.
dos.writeBytes("HOME=" + mContext.getFilesDir() + " ");
// Call syncthing with -home (as it would otherwise use "~/.config/syncthing/".
dos.writeBytes(mContext.getApplicationInfo().dataDir + "/" + BINARY_NAME + " " +
"-home " + mContext.getFilesDir() + "\n");
dos.writeBytes("exit\n");
dos.flush();
log(process.getErrorStream());
ret = process.waitFor();
}
catch(IOException e) {
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
}
catch(InterruptedException e) {
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
}
finally {
try {
dos.close();
}
catch (IOException e) {
Log.w(TAG, "Failed to close shell stream", e);
}
process.destroy();
final int retVal = ret;
if (ret != 0) {
Log.w(TAG_NATIVE, "Syncthing binary crashed with error code " + Integer.toString(retVal));
postCrashDialog(retVal);
}
}
}
/**
* Displays a dialog with an info message and the return value.
*
* @param retVal
*/
private void postCrashDialog(final int retVal) {
mHandler.post(new Runnable() {
public void run() {
AlertDialog dialog = new AlertDialog.Builder(mContext)
.setTitle(R.string.binary_crashed_title)
.setMessage(mContext.getString(R.string.binary_crashed_message, retVal))
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface,
int i) {
System.exit(0);
}
})
.create();
dialog.getWindow()
.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
}
});
}
/**
* Logs the outputs of a stream to logcat and mNativeLog.
*
* @param is The stream to log.
*/
private void log(final InputStream is) {
new Thread(new Runnable() {
@Override
public void run() {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
try {
while ((line = br.readLine()) != null) {
Log.i(TAG_NATIVE, line);
}
}
catch (IOException e) {
// NOTE: This is sometimes called on shutdown, as
// Process.destroy() closes the stream.
Log.w(TAG, "Failed to read syncthing command line output", e);
}
}
}).start();
}
}

View File

@ -10,13 +10,11 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.view.WindowManager;
import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.gui.MainActivity; import com.nutomic.syncthingandroid.gui.MainActivity;
@ -30,14 +28,11 @@ import org.apache.http.client.methods.HttpHead;
import org.apache.http.conn.HttpHostConnectException; import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -49,8 +44,6 @@ public class SyncthingService extends Service {
private static final String TAG = "SyncthingService"; private static final String TAG = "SyncthingService";
private static final String TAG_NATIVE = "SyncthingNativeCode";
private static final int NOTIFICATION_RUNNING = 1; private static final int NOTIFICATION_RUNNING = 1;
/** /**
@ -63,11 +56,6 @@ public class SyncthingService extends Service {
*/ */
public static final int GUI_UPDATE_INTERVAL = 1000; public static final int GUI_UPDATE_INTERVAL = 1000;
/**
* Path to the native, integrated syncthing binary, relative to the data folder
*/
private static final String BINARY_NAME = "lib/libsyncthing.so";
/** /**
* Interval in ms, at which connections to the web gui are performed on first start * Interval in ms, at which connections to the web gui are performed on first start
* to find out if it's online. * to find out if it's online.
@ -185,7 +173,7 @@ public class SyncthingService extends Service {
mCurrentState = State.STARTING; mCurrentState = State.STARTING;
registerOnWebGuiAvailableListener(mApi); registerOnWebGuiAvailableListener(mApi);
new PollWebGuiAvailableTask().execute(); new PollWebGuiAvailableTask().execute();
new Thread(new SyncthingRunnable()).start(); new Thread(new SyncthingRunnable(this)).start();
} }
// Stop syncthing. // Stop syncthing.
else { else {
@ -204,100 +192,6 @@ public class SyncthingService extends Service {
onApiChange(); onApiChange();
} }
private Handler mMainThreadHandler;
/**
* Runs the syncthing binary from command line, and prints its output to logcat (on exit).
*/
private class SyncthingRunnable implements Runnable {
@Override
public void run() {
DataOutputStream dos = null;
int ret = 1;
Process process = null;
try {
process = Runtime.getRuntime().exec("sh");
dos = new DataOutputStream(process.getOutputStream());
// Set home directory to data folder for syncthing to use.
dos.writeBytes("HOME=" + getFilesDir() + " ");
// Call syncthing with -home (as it would otherwise use "~/.config/syncthing/".
dos.writeBytes(getApplicationInfo().dataDir + "/" + BINARY_NAME + " " +
"-home " + getFilesDir() + "\n");
dos.writeBytes("exit\n");
dos.flush();
log(process.getInputStream());
ret = process.waitFor();
}
catch(IOException e) {
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
}
catch(InterruptedException e) {
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
}
finally {
try {
dos.close();
}
catch (IOException e) {
Log.w(TAG, "Failed to close shell stream", e);
}
process.destroy();
final int retVal = ret;
if (ret != 0) {
mMainThreadHandler.post(new Runnable() {
public void run() {
Log.w(TAG_NATIVE, "Syncthing binary crashed with error code " +
Integer.toString(retVal));
AlertDialog dialog = new AlertDialog.Builder(SyncthingService.this)
.setTitle(R.string.binary_crashed_title)
.setMessage(getString(R.string.binary_crashed_message, retVal))
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface,
int i) {
System.exit(0);
}
})
.create();
dialog.getWindow()
.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
}
});
}
}
}
}
/**
* Logs the outputs of a stream to logcat and mNativeLog.
*
* @param is The stream to log.
*/
private void log(final InputStream is) {
new Thread(new Runnable() {
@Override
public void run() {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
try {
while ((line = br.readLine()) != null) {
Log.i(TAG_NATIVE, line);
}
}
catch (IOException e) {
// NOTE: This is sometimes called on shutdown, as
// Process.destroy() closes the stream.
Log.w(TAG, "Failed to read syncthing command line output", e);
}
}
}).start();
}
/** /**
* Polls SYNCTHING_URL until it returns HTTP status OK, then calls all listeners * Polls SYNCTHING_URL until it returns HTTP status OK, then calls all listeners
* in mOnWebGuiAvailableListeners and clears it. * in mOnWebGuiAvailableListeners and clears it.
@ -401,7 +295,6 @@ public class SyncthingService extends Service {
n.flags |= Notification.FLAG_ONGOING_EVENT; n.flags |= Notification.FLAG_ONGOING_EVENT;
startForeground(NOTIFICATION_RUNNING, n); startForeground(NOTIFICATION_RUNNING, n);
mMainThreadHandler = new Handler();
mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this); mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this);
registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
new StartupTask().execute(); new StartupTask().execute();
@ -573,7 +466,8 @@ public class SyncthingService extends Service {
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
activity.finish(); activity.finish();
} }
}) }
)
.show() .show()
.setCancelable(false); .setCancelable(false);
} }