mirror of
https://github.com/syncthing/syncthing-android.git
synced 2025-01-25 11:26:32 +00:00
Streamline SyncthingRunnable
Conflicts: src/androidTest/java/com/nutomic/syncthingandroid/test/syncthing/RestApiTest.java src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingRunnable.java src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java src/main/res/values/strings.xml
This commit is contained in:
parent
09331780b3
commit
5d5cf0b903
10 changed files with 114 additions and 23 deletions
|
@ -30,8 +30,7 @@ public class PollWebGuiAvailableTaskTest extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPolling() throws InterruptedException {
|
public void testPolling() throws InterruptedException {
|
||||||
new SyncthingRunnable(new MockContext(null),
|
mSyncthing = new SyncthingRunnable(new MockContext(null), SyncthingRunnable.Command.main);
|
||||||
getContext().getApplicationInfo().dataDir + "/" + SyncthingService.BINARY_NAME);
|
|
||||||
|
|
||||||
String httpsCertPath = getContext().getFilesDir() + "/" + SyncthingService.HTTPS_CERT_FILE;
|
String httpsCertPath = getContext().getFilesDir() + "/" + SyncthingService.HTTPS_CERT_FILE;
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,7 @@ public class RestApiTest extends AndroidTestCase {
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
new SyncthingRunnable(new MockContext(null),
|
mSyncthing = new SyncthingRunnable(new MockContext(null), SyncthingRunnable.Command.main);
|
||||||
getContext().getApplicationInfo().dataDir + "/" + SyncthingService.BINARY_NAME);
|
|
||||||
|
|
||||||
ConfigXml config = new ConfigXml(new MockContext(getContext()));
|
ConfigXml config = new ConfigXml(new MockContext(getContext()));
|
||||||
config.changeDefaultFolder();
|
config.changeDefaultFolder();
|
||||||
|
|
|
@ -17,9 +17,9 @@ public class SyncthingRunnableTest extends AndroidTestCase {
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testRunning() throws InterruptedException {
|
public void testRunning() throws InterruptedException {
|
||||||
MockContext context = new MockContext(getContext());
|
MockContext context = new MockContext(getContext());
|
||||||
File testFile = new File(context.getFilesDir(), "was_running");
|
File testFile = new File(context.getFilesDir(), SyncthingRunnable.UNIT_TEST_PATH);
|
||||||
assertFalse(testFile.exists());
|
assertFalse(testFile.exists());
|
||||||
// Inject a differenct command instead of the syncthing binary for testing.
|
// Inject a different command instead of the Syncthing binary for testing.
|
||||||
new SyncthingRunnable(context, "touch " + testFile.getAbsolutePath() + "; exit\n").run();
|
new SyncthingRunnable(context, "touch " + testFile.getAbsolutePath() + "; exit\n").run();
|
||||||
assertTrue(testFile.exists());
|
assertTrue(testFile.exists());
|
||||||
testFile.delete();
|
testFile.delete();
|
||||||
|
|
|
@ -37,6 +37,7 @@ public class SettingsFragment extends PreferenceFragment
|
||||||
private static final String EXPORT_CONFIG = "export_config";
|
private static final String EXPORT_CONFIG = "export_config";
|
||||||
private static final String IMPORT_CONFIG = "import_config";
|
private static final String IMPORT_CONFIG = "import_config";
|
||||||
private static final String STTRACE = "sttrace";
|
private static final String STTRACE = "sttrace";
|
||||||
|
private static final String SYNCTHING_RESET = "streset";
|
||||||
|
|
||||||
private static final String SYNCTHING_VERSION_KEY = "syncthing_version";
|
private static final String SYNCTHING_VERSION_KEY = "syncthing_version";
|
||||||
|
|
||||||
|
@ -139,12 +140,13 @@ public class SettingsFragment extends PreferenceFragment
|
||||||
mSyncOnlyWifi.setOnPreferenceChangeListener(this);
|
mSyncOnlyWifi.setOnPreferenceChangeListener(this);
|
||||||
screen.findPreference(EXPORT_CONFIG).setOnPreferenceClickListener(this);
|
screen.findPreference(EXPORT_CONFIG).setOnPreferenceClickListener(this);
|
||||||
screen.findPreference(IMPORT_CONFIG).setOnPreferenceClickListener(this);
|
screen.findPreference(IMPORT_CONFIG).setOnPreferenceClickListener(this);
|
||||||
|
screen.findPreference(SYNCTHING_RESET).setOnPreferenceClickListener(this);
|
||||||
user.setOnPreferenceChangeListener(this);
|
user.setOnPreferenceChangeListener(this);
|
||||||
password.setOnPreferenceChangeListener(this);
|
password.setOnPreferenceChangeListener(this);
|
||||||
// Force summary update and wifi/charging preferences enable/disable.
|
|
||||||
onPreferenceChange(mAlwaysRunInBackground, mAlwaysRunInBackground.isChecked());
|
|
||||||
sttrace.setOnPreferenceChangeListener(this);
|
sttrace.setOnPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
// Force summary update and wifi/charging preferences enable/disable.
|
||||||
|
onPreferenceChange(mAlwaysRunInBackground, mAlwaysRunInBackground.isChecked());
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
user.setSummary(sp.getString("gui_user", ""));
|
user.setSummary(sp.getString("gui_user", ""));
|
||||||
sttrace.setSummary(sp.getString("sttrace", ""));
|
sttrace.setSummary(sp.getString("sttrace", ""));
|
||||||
|
@ -272,6 +274,9 @@ public class SettingsFragment extends PreferenceFragment
|
||||||
SyncthingService.EXPORT_PATH), Toast.LENGTH_LONG).show();
|
SyncthingService.EXPORT_PATH), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case SYNCTHING_RESET:
|
||||||
|
((SyncthingActivity) getActivity()).getApi().resetSyncthing(getActivity());
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,6 +379,33 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset Syncthing's indexes when confirmed by a dialog.
|
||||||
|
*/
|
||||||
|
@TargetApi(11)
|
||||||
|
public void resetSyncthing(final Activity activity) {
|
||||||
|
final Intent intent = new Intent(mContext, SyncthingService.class)
|
||||||
|
.setAction(SyncthingService.ACTION_RESET);
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||||
|
? new AlertDialog.Builder(activity, AlertDialog.THEME_HOLO_LIGHT)
|
||||||
|
: new AlertDialog.Builder(activity);
|
||||||
|
builder.setTitle(R.string.streset_title);
|
||||||
|
builder.setMessage(R.string.streset_question)
|
||||||
|
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
mContext.startService(intent);
|
||||||
|
Toast.makeText(activity, R.string.streset_done, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) { }
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a notification prompting the user to restart the app.
|
* Creates a notification prompting the user to restart the app.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,18 +27,52 @@ public class SyncthingRunnable implements Runnable {
|
||||||
|
|
||||||
private static final String TAG_NATIVE = "SyncthingNativeCode";
|
private static final String TAG_NATIVE = "SyncthingNativeCode";
|
||||||
|
|
||||||
|
public static final String UNIT_TEST_PATH = "was running";
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
|
private boolean mGenerate;
|
||||||
|
|
||||||
private String mCommand;
|
private String mCommand;
|
||||||
|
|
||||||
|
public enum Command {
|
||||||
|
generate, // Generate keys, a config file and immediately exit.
|
||||||
|
main, // Run the main Syncthing application.
|
||||||
|
reset, // Reset Syncthing's indexes
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs instance.
|
* Constructs instance.
|
||||||
*
|
*
|
||||||
* @param command The exact command to be executed on the shell.
|
* @param command Which type of Syncthing command to execute.
|
||||||
*/
|
*/
|
||||||
public SyncthingRunnable(Context context, String command) {
|
public SyncthingRunnable(Context context, Command command) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mCommand = command;
|
String syncthing = mContext.getApplicationInfo().dataDir + "/" + SyncthingService.BINARY_NAME;
|
||||||
|
switch (command) {
|
||||||
|
case generate:
|
||||||
|
mCommand = syncthing + " -generate='" + mContext.getFilesDir() + "' -no-browser";
|
||||||
|
break;
|
||||||
|
case main:
|
||||||
|
mCommand = syncthing + " -home='" + mContext.getFilesDir() + "' -no-browser";
|
||||||
|
break;
|
||||||
|
case reset:
|
||||||
|
mCommand = syncthing + " -home='" + mContext.getFilesDir() + "' -reset";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.w(TAG, "Unknown command option");
|
||||||
|
mCommand = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs instance.
|
||||||
|
*
|
||||||
|
* @param manualCommand The exact command to be executed on the shell. Used for tests only.
|
||||||
|
*/
|
||||||
|
public SyncthingRunnable(Context context, String manualCommand) {
|
||||||
|
mContext = context;
|
||||||
|
mCommand = manualCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,7 +82,7 @@ public class SyncthingRunnable implements Runnable {
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
Process process = null;
|
Process process = null;
|
||||||
try {
|
try {
|
||||||
// Loop to handle syncthing restarts (these always have an error code of 3).
|
// Loop to handle Syncthing restarts (these always have an error code of 3).
|
||||||
do {
|
do {
|
||||||
ProcessBuilder pb = new ProcessBuilder("sh");
|
ProcessBuilder pb = new ProcessBuilder("sh");
|
||||||
Map<String, String> env = pb.environment();
|
Map<String, String> env = pb.environment();
|
||||||
|
@ -62,9 +96,13 @@ public class SyncthingRunnable implements Runnable {
|
||||||
process = pb.start();
|
process = pb.start();
|
||||||
|
|
||||||
dos = new DataOutputStream(process.getOutputStream());
|
dos = new DataOutputStream(process.getOutputStream());
|
||||||
// Call syncthing with -home (as it would otherwise use "~/.config/syncthing/".
|
// Set (Android) home directory to data folder for syncthing to use.
|
||||||
dos.writeBytes(mCommand + " -home " + mContext.getFilesDir() + "\n");
|
dos.writeBytes("HOME=" + Environment.getExternalStorageDirectory() + " ");
|
||||||
dos.writeBytes("exit\n");
|
dos.writeBytes("STTRACE=" + pm.getString("sttrace", "") + " ");
|
||||||
|
dos.writeBytes("STNORESTART=1 ");
|
||||||
|
dos.writeBytes("STNOUPGRADE=1 ");
|
||||||
|
dos.writeBytes(mCommand);
|
||||||
|
dos.writeBytes("\nexit\n");
|
||||||
dos.flush();
|
dos.flush();
|
||||||
|
|
||||||
log(process.getInputStream(), Log.INFO);
|
log(process.getInputStream(), Log.INFO);
|
||||||
|
|
|
@ -45,10 +45,16 @@ public class SyncthingService extends Service {
|
||||||
private static final String TAG = "SyncthingService";
|
private static final String TAG = "SyncthingService";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intent action to perform a syncthing restart.
|
* Intent action to perform a Syncthing restart.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_RESTART = "restart";
|
public static final String ACTION_RESTART = "restart";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intent action to reset Syncthing's database.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_RESET = "reset";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interval in ms at which the GUI is updated (eg {@link com.nutomic.syncthingandroid.fragments.DrawerFragment}).
|
* Interval in ms at which the GUI is updated (eg {@link com.nutomic.syncthingandroid.fragments.DrawerFragment}).
|
||||||
*/
|
*/
|
||||||
|
@ -150,8 +156,12 @@ public class SyncthingService extends Service {
|
||||||
mApi.shutdown();
|
mApi.shutdown();
|
||||||
mCurrentState = State.INIT;
|
mCurrentState = State.INIT;
|
||||||
updateState();
|
updateState();
|
||||||
}
|
} else if (ACTION_RESET.equals(intent.getAction())) {
|
||||||
else if (mCurrentState != State.INIT) {
|
mApi.shutdown();
|
||||||
|
new SyncthingRunnable(this, SyncthingRunnable.Command.reset).run();
|
||||||
|
mCurrentState = State.INIT;
|
||||||
|
updateState();
|
||||||
|
} else if (mCurrentState != State.INIT) {
|
||||||
mDeviceStateHolder.update(intent);
|
mDeviceStateHolder.update(intent);
|
||||||
updateState();
|
updateState();
|
||||||
}
|
}
|
||||||
|
@ -200,8 +210,7 @@ public class SyncthingService extends Service {
|
||||||
mCurrentState = State.STARTING;
|
mCurrentState = State.STARTING;
|
||||||
registerOnWebGuiAvailableListener(mApi);
|
registerOnWebGuiAvailableListener(mApi);
|
||||||
new PollWebGuiAvailableTaskImpl(getFilesDir() + "/" + HTTPS_CERT_FILE).execute(mConfig.getWebGuiUrl());
|
new PollWebGuiAvailableTaskImpl(getFilesDir() + "/" + HTTPS_CERT_FILE).execute(mConfig.getWebGuiUrl());
|
||||||
new Thread(new SyncthingRunnable(
|
new Thread(new SyncthingRunnable(this, SyncthingRunnable.Command.main)).start();
|
||||||
this, getApplicationInfo().dataDir + "/" + BINARY_NAME)).start();
|
|
||||||
Notification n = new NotificationCompat.Builder(this)
|
Notification n = new NotificationCompat.Builder(this)
|
||||||
.setContentTitle(getString(R.string.syncthing_active))
|
.setContentTitle(getString(R.string.syncthing_active))
|
||||||
.setSmallIcon(R.drawable.ic_stat_notify)
|
.setSmallIcon(R.drawable.ic_stat_notify)
|
||||||
|
|
|
@ -78,9 +78,7 @@ public class ConfigXml {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateKeysConfig(Context context) {
|
private void generateKeysConfig(Context context) {
|
||||||
new SyncthingRunnable(context, context.getApplicationInfo().dataDir + "/" +
|
new SyncthingRunnable(context, SyncthingRunnable.Command.generate).run();
|
||||||
SyncthingService.BINARY_NAME + " -generate='" + context.getFilesDir() + "'")
|
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getConfigFile(Context context) {
|
public static File getConfigFile(Context context) {
|
||||||
|
|
|
@ -286,6 +286,17 @@ Please report any problems you encounter via Github.</string>
|
||||||
<!-- Toast after entering invalid password -->
|
<!-- Toast after entering invalid password -->
|
||||||
<string name="toast_invalid_password">Characters : and \' are not allowed in password</string>
|
<string name="toast_invalid_password">Characters : and \' are not allowed in password</string>
|
||||||
|
|
||||||
|
<!-- Title for the preference to reset Syncthing indexes -->
|
||||||
|
<string name="streset_title">Reset Database</string>
|
||||||
|
|
||||||
|
<!-- Syncthing was reset -->
|
||||||
|
<string name="streset_question">This action should only be performed based on a recommendation from our support team.
|
||||||
|
\nAre you sure you want to clear Syncthing\'s index database?
|
||||||
|
</string>
|
||||||
|
|
||||||
|
<!-- Syncthing was reset -->
|
||||||
|
<string name="streset_done">Successfully reset Syncthing\'s database</string>
|
||||||
|
|
||||||
<string name="category_about">About</string>
|
<string name="category_about">About</string>
|
||||||
|
|
||||||
<!-- Settings item that opens the log activity -->
|
<!-- Settings item that opens the log activity -->
|
||||||
|
|
|
@ -115,6 +115,11 @@
|
||||||
android:title="@string/sttrace_title"
|
android:title="@string/sttrace_title"
|
||||||
android:singleLine="true" />
|
android:singleLine="true" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="streset"
|
||||||
|
android:title="@string/streset_title"
|
||||||
|
android:singleLine="true" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
|
Loading…
Reference in a new issue