Moved Syncthing constants to seperate file

This commit is contained in:
Felix Ableitner 2017-10-04 17:44:56 +09:00
parent 4c2b325676
commit 1fd86211dc
18 changed files with 164 additions and 165 deletions

View File

@ -22,6 +22,7 @@ import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.model.Config;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.model.Options;
import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.RestApi;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.util.Languages;
@ -94,13 +95,13 @@ public class SettingsActivity extends SyncthingActivity {
addPreferencesFromResource(R.xml.app_settings);
PreferenceScreen screen = getPreferenceScreen();
mAlwaysRunInBackground =
(CheckBoxPreference) findPreference(SyncthingService.PREF_ALWAYS_RUN_IN_BACKGROUND);
(CheckBoxPreference) findPreference(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND);
mSyncOnlyCharging =
(CheckBoxPreference) findPreference(SyncthingService.PREF_SYNC_ONLY_CHARGING);
(CheckBoxPreference) findPreference(Constants.PREF_SYNC_ONLY_CHARGING);
mSyncOnlyWifi =
(CheckBoxPreference) findPreference(SyncthingService.PREF_SYNC_ONLY_WIFI);
(CheckBoxPreference) findPreference(Constants.PREF_SYNC_ONLY_WIFI);
mSyncOnlyOnSSIDs =
(WifiSsidPreference) findPreference(SyncthingService.PREF_SYNC_ONLY_WIFI_SSIDS);
(WifiSsidPreference) findPreference(Constants.PREF_SYNC_ONLY_WIFI_SSIDS);
mSyncOnlyCharging.setEnabled(mAlwaysRunInBackground.isChecked());
mSyncOnlyWifi.setEnabled(mAlwaysRunInBackground.isChecked());
@ -140,8 +141,8 @@ public class SettingsActivity extends SyncthingActivity {
Preference environmentVariables = findPreference("environment_variables");
Preference stReset = findPreference("streset");
mUseRoot = (CheckBoxPreference) findPreference(SyncthingService.PREF_USE_ROOT);
Preference useWakelock = findPreference(SyncthingService.PREF_USE_WAKE_LOCK);
mUseRoot = (CheckBoxPreference) findPreference(Constants.PREF_USE_ROOT);
Preference useWakelock = findPreference(Constants.PREF_USE_WAKE_LOCK);
Preference foregroundService = findPreference("run_as_foreground_service");
Preference useTor = findPreference("use_tor");
@ -284,7 +285,7 @@ public class SettingsActivity extends SyncthingActivity {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
switch (preference.getKey()) {
case SyncthingService.PREF_ALWAYS_RUN_IN_BACKGROUND:
case Constants.PREF_ALWAYS_RUN_IN_BACKGROUND:
boolean value = (Boolean) o;
mAlwaysRunInBackground.setSummary((value)
? R.string.always_run_in_background_enabled
@ -298,7 +299,7 @@ public class SettingsActivity extends SyncthingActivity {
mSyncOnlyWifi.setChecked(false);
}
break;
case SyncthingService.PREF_SYNC_ONLY_WIFI:
case Constants.PREF_SYNC_ONLY_WIFI:
mSyncOnlyOnSSIDs.setEnabled((Boolean) o);
break;
case KEY_STTRACE:
@ -328,7 +329,7 @@ public class SettingsActivity extends SyncthingActivity {
@Override
public boolean onPreferenceClick(Preference preference) {
switch (preference.getKey()) {
case SyncthingService.PREF_USE_ROOT:
case Constants.PREF_USE_ROOT:
if (mUseRoot.isChecked()) {
// Only check preference after root was granted.
mUseRoot.setChecked(false);
@ -345,7 +346,7 @@ public class SettingsActivity extends SyncthingActivity {
mSyncthingService.exportConfig();
Toast.makeText(getActivity(),
getString(R.string.config_export_successful,
SyncthingService.EXPORT_PATH), Toast.LENGTH_LONG).show();
Constants.EXPORT_PATH), Toast.LENGTH_LONG).show();
})
.setNegativeButton(android.R.string.no, null)
.show();
@ -363,7 +364,7 @@ public class SettingsActivity extends SyncthingActivity {
} else {
Toast.makeText(getActivity(),
getString(R.string.config_import_failed,
SyncthingService.EXPORT_PATH), Toast.LENGTH_LONG).show();
Constants.EXPORT_PATH), Toast.LENGTH_LONG).show();
}
})
.setNegativeButton(android.R.string.no, null)

View File

@ -17,9 +17,11 @@ import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.util.ConfigXml;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -157,7 +159,7 @@ public class WebGuiActivity extends StateDialogActivity
private void loadCaCert() {
InputStream inStream = null;
try {
String httpsCertPath = getFilesDir() + "/" + SyncthingService.HTTPS_CERT_FILE;
File httpsCertPath = Constants.getHttpsCertFile(this);
inStream = new FileInputStream(httpsCertPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
mCaCert = (X509Certificate)

View File

@ -14,6 +14,7 @@ import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.activities.DeviceActivity;
import com.nutomic.syncthingandroid.activities.SyncthingActivity;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.views.DevicesAdapter;
@ -58,7 +59,7 @@ public class DeviceListFragment extends ListFragment implements SyncthingService
getActivity().runOnUiThread(DeviceListFragment.this::updateList);
}
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
}, 0, Constants.GUI_UPDATE_INTERVAL);
}
@Override

View File

@ -20,11 +20,11 @@ import com.nutomic.syncthingandroid.http.ImageGetRequest;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.SystemInfo;
import com.nutomic.syncthingandroid.model.SystemVersion;
import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.RestApi;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.util.Util;
import java.io.File;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Locale;
@ -57,7 +57,7 @@ public class DrawerFragment extends Fragment implements View.OnClickListener {
updateGui();
}
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
}, 0, Constants.GUI_UPDATE_INTERVAL);
}
@Override
@ -197,12 +197,11 @@ public class DrawerFragment extends Fragment implements View.OnClickListener {
private void showQrCode() {
//The QRCode request takes one paramteer called "text", which is the text to be converted to a QRCode.
File httpsCertPath = new File(mActivity.getFilesDir(), SyncthingService.HTTPS_CERT_FILE);
String apiKey = mActivity.getApi().getGui().apiKey;
String deviceId = mActivity.getApi().getLocalDevice().deviceID;
URL url = mActivity.getApi().getUrl();
new ImageGetRequest(mActivity, url, ImageGetRequest.QR_CODE_GENERATOR, httpsCertPath,
apiKey, ImmutableMap.of("text", deviceId),qrCodeBitmap -> {
new ImageGetRequest(mActivity, url, ImageGetRequest.QR_CODE_GENERATOR, apiKey,
ImmutableMap.of("text", deviceId),qrCodeBitmap -> {
mActivity.showQrCodeDialog(deviceId, qrCodeBitmap);
mActivity.closeDrawer();
}, error -> Toast.makeText(mActivity, R.string.could_not_access_deviceid, Toast.LENGTH_SHORT).show());

View File

@ -13,6 +13,7 @@ import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.activities.FolderActivity;
import com.nutomic.syncthingandroid.activities.SyncthingActivity;
import com.nutomic.syncthingandroid.model.Folder;
import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.views.FoldersAdapter;
@ -53,7 +54,7 @@ public class FolderListFragment extends ListFragment implements SyncthingService
getActivity().runOnUiThread(FolderListFragment.this::updateList);
}
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
}, 0, Constants.GUI_UPDATE_INTERVAL);
}
@Override

View File

@ -18,23 +18,15 @@ import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.nutomic.syncthingandroid.service.Constants;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
@ -43,7 +35,6 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public abstract class ApiRequest {
@ -79,14 +70,12 @@ public abstract class ApiRequest {
private final Context mContext;
private final URL mUrl;
private final String mPath;
private final File mHttpsCertPath;
private final String mApiKey;
public ApiRequest(Context context, URL url, String path, File httpsCertPath, String apiKey) {
public ApiRequest(Context context, URL url, String path, String apiKey) {
mContext = context;
mUrl = url;
mPath = path;
mHttpsCertPath = httpsCertPath;
mApiKey = apiKey;
}
@ -177,7 +166,8 @@ public abstract class ApiRequest {
private SSLSocketFactory getSslSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{new SyncthingTrustManager(mHttpsCertPath)},
File httpsCertPath = Constants.getHttpsCertFile(mContext);
sslContext.init(null, new TrustManager[]{new SyncthingTrustManager(httpsCertPath)},
new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {

View File

@ -7,7 +7,6 @@ import android.support.annotation.Nullable;
import com.android.volley.Request;
import com.google.common.base.Optional;
import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
@ -26,9 +25,9 @@ public class GetRequest extends ApiRequest {
public static final String URI_REPORT = "/rest/svc/report";
public static final String URI_EVENTS = "/rest/events";
public GetRequest(Context context, URL url, String path, File httpsCertPath, String apiKey,
public GetRequest(Context context, URL url, String path, String apiKey,
@Nullable Map<String, String> params, OnSuccessListener listener) {
super(context, url, path, httpsCertPath, apiKey);
super(context, url, path, apiKey);
Map<String, String> safeParams = Optional.fromNullable(params).or(Collections.emptyMap());
Uri uri = buildUri(safeParams);
connect(Request.Method.GET, uri, null, listener, null);

View File

@ -6,7 +6,6 @@ import android.support.annotation.Nullable;
import com.google.common.base.Optional;
import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
@ -15,9 +14,10 @@ public class ImageGetRequest extends ApiRequest {
public static final String QR_CODE_GENERATOR = "/qr/";
public ImageGetRequest(Context context, URL url, String path, File httpsCertPath, String apiKey,
@Nullable Map<String, String> params, OnImageSuccessListener onSuccessListener, OnErrorListener onErrorListener) {
super(context, url, path, httpsCertPath, apiKey);
public ImageGetRequest(Context context, URL url, String path, String apiKey,
@Nullable Map<String, String> params,
OnImageSuccessListener onSuccessListener, OnErrorListener onErrorListener) {
super(context, url, path, apiKey);
Map<String, String> safeParams = Optional.fromNullable(params).or(Collections.emptyMap());
Uri uri = buildUri(safeParams);
makeImageRequest(uri, onSuccessListener, onErrorListener);

View File

@ -8,7 +8,6 @@ import android.os.Handler;
import com.android.volley.Request;
import com.android.volley.VolleyError;
import java.io.File;
import java.net.URL;
import java.util.Collections;
@ -26,9 +25,9 @@ public class PollWebGuiAvailableTask extends ApiRequest {
private final OnSuccessListener mListener;
private final Handler mHandler = new Handler();
public PollWebGuiAvailableTask(Context context, URL url, File httpsCertPath, String apiKey,
public PollWebGuiAvailableTask(Context context, URL url, String apiKey,
OnSuccessListener listener) {
super(context, url, "", httpsCertPath, apiKey);
super(context, url, "", apiKey);
mListener = listener;
performRequest();
}

View File

@ -5,7 +5,6 @@ import android.net.Uri;
import com.android.volley.Request;
import java.io.File;
import java.net.URL;
import java.util.Collections;
@ -13,9 +12,9 @@ public class PostConfigRequest extends ApiRequest {
private static final String URI_CONFIG = "/rest/system/config";
public PostConfigRequest(Context context, URL url, File httpsCertPath, String apiKey, String config,
public PostConfigRequest(Context context, URL url, String apiKey, String config,
OnSuccessListener listener) {
super(context, url, URI_CONFIG, httpsCertPath, apiKey);
super(context, url, URI_CONFIG, apiKey);
Uri uri = buildUri(Collections.emptyMap());
connect(Request.Method.POST, uri, config, listener, null);
}

View File

@ -6,16 +6,15 @@ import android.net.Uri;
import com.android.volley.Request;
import com.google.common.collect.ImmutableMap;
import java.io.File;
import java.net.URL;
public class PostScanRequest extends ApiRequest {
private static final String URI_SCAN = "/rest/db/scan";
public PostScanRequest(Context context, URL url, File httpsCertPath, String apiKey,
public PostScanRequest(Context context, URL url, String apiKey,
String folder, String sub) {
super(context, url, URI_SCAN, httpsCertPath, apiKey);
super(context, url, URI_SCAN, apiKey);
Uri uri = buildUri(ImmutableMap.of("folder", folder, "sub", sub));
connect(Request.Method.POST, uri, null, null, null);
}

View File

@ -0,0 +1,69 @@
package com.nutomic.syncthingandroid.service;
import android.content.Context;
import android.os.Environment;
import java.io.File;
import java.util.concurrent.TimeUnit;
public class Constants {
public static final String PREF_ALWAYS_RUN_IN_BACKGROUND = "always_run_in_background";
public static final String PREF_SYNC_ONLY_WIFI = "sync_only_wifi";
public static final String PREF_SYNC_ONLY_WIFI_SSIDS = "sync_only_wifi_ssids_set";
public static final String PREF_SYNC_ONLY_CHARGING = "sync_only_charging";
public static final String PREF_RESPECT_BATTERY_SAVING = "respect_battery_saving";
public static final String PREF_USE_ROOT = "use_root";
public static final String PREF_NOTIFICATION_TYPE = "notification_type";
public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running";
public static final String PREF_FOREGROUND_SERVICE = "run_as_foreground_service";
/**
* Interval in ms at which the GUI is updated (eg {@link com.nutomic.syncthingandroid.fragments.DrawerFragment}).
*/
public static final long GUI_UPDATE_INTERVAL = TimeUnit.SECONDS.toMillis(5);
/**
* Directory where config is exported to and imported from.
*/
public static final File EXPORT_PATH =
new File(Environment.getExternalStorageDirectory(), "backups/syncthing");
/**
* File in the config folder that contains configuration.
*/
static String CONFIG_FILE = "config.xml";
public static File getConfigFile(Context context) {
return new File(context.getFilesDir(), CONFIG_FILE);
}
/**
* Name of the public key file in the data directory.
*/
static String PUBLIC_KEY_FILE = "cert.pem";
static File getPublicKeyFile(Context context) {
return new File(context.getFilesDir(), PUBLIC_KEY_FILE);
}
/**
* Name of the private key file in the data directory.
*/
static final String PRIVATE_KEY_FILE = "key.pem";
static File getPrivateKeyFile(Context context) {
return new File(context.getFilesDir(), PRIVATE_KEY_FILE);
}
/**
* Name of the public HTTPS CA file in the data directory.
*/
public static File getHttpsCertFile(Context context) {
return new File(context.getFilesDir(), "https-cert.pem");
}
static File getSyncthingBinary(Context context) {
return new File(context.getApplicationInfo().nativeLibraryDir, "libsyncthing.so");
}
}

View File

@ -115,8 +115,8 @@ public class DeviceStateHolder {
return false;
if (SyncthingService.alwaysRunInBackground(mContext)) {
boolean prefStopMobileData = mPreferences.getBoolean(SyncthingService.PREF_SYNC_ONLY_WIFI, false);
boolean prefStopNotCharging = mPreferences.getBoolean(SyncthingService.PREF_SYNC_ONLY_CHARGING, false);
boolean prefStopMobileData = mPreferences.getBoolean(Constants.PREF_SYNC_ONLY_WIFI, false);
boolean prefStopNotCharging = mPreferences.getBoolean(Constants.PREF_SYNC_ONLY_CHARGING, false);
if (prefStopMobileData && !isWhitelistedNetworkConnection())
return false;
@ -131,7 +131,7 @@ public class DeviceStateHolder {
private boolean isWhitelistedNetworkConnection() {
boolean wifiConnected = mIsAllowedNetworkConnection;
if (wifiConnected) {
Set<String> ssids = mPreferences.getStringSet(SyncthingService.PREF_SYNC_ONLY_WIFI_SSIDS, new HashSet<>());
Set<String> ssids = mPreferences.getStringSet(Constants.PREF_SYNC_ONLY_WIFI_SSIDS, new HashSet<>());
if (ssids.isEmpty()) {
Log.d(TAG, "All SSIDs allowed for syncing");
return true;

View File

@ -35,11 +35,11 @@ public class NotificationHandler {
/**
* Shows or hides the persistent notification based on running state and
* {@link SyncthingService#PREF_NOTIFICATION_TYPE}.
* {@link Constants#PREF_NOTIFICATION_TYPE}.
*/
public void updatePersistentNotification(SyncthingService service, SyncthingService.State currentState) {
String type = mPreferences.getString(SyncthingService.PREF_NOTIFICATION_TYPE, "low_priority");
boolean foreground = mPreferences.getBoolean(SyncthingService.PREF_FOREGROUND_SERVICE, false);
String type = mPreferences.getString(Constants.PREF_NOTIFICATION_TYPE, "low_priority");
boolean foreground = mPreferences.getBoolean(Constants.PREF_FOREGROUND_SERVICE, false);
if ("none".equals(type) && foreground) {
// foreground priority requires any notification
// so this ensures that we either have a "default" or "low_priority" notification,

View File

@ -32,7 +32,6 @@ import com.nutomic.syncthingandroid.model.SystemInfo;
import com.nutomic.syncthingandroid.model.SystemVersion;
import com.nutomic.syncthingandroid.util.FolderObserver;
import java.io.File;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.Collections;
@ -78,7 +77,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
private final Context mContext;
private final URL mUrl;
private final String mApiKey;
private final File mHttpsCertPath;
private String mVersion;
private Config mConfig;
@ -110,7 +108,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
mContext = context;
mUrl = url;
mApiKey = apiKey;
mHttpsCertPath = new File(mContext.getFilesDir(), SyncthingService.HTTPS_CERT_FILE);
mOnApiAvailableListener = apiListener;
mOnConfigChangedListener = configListener;
}
@ -139,13 +136,13 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
@Override
public void onWebGuiAvailable() {
mAvailableCount.set(0);
new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> {
new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mApiKey, null, result -> {
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
mVersion = json.get("version").getAsString();
Log.i(TAG, "Syncthing version is " + mVersion);
tryIsAvailable();
});
new GetRequest(mContext, mUrl, GetRequest.URI_CONFIG, mHttpsCertPath, mApiKey, null, result -> {
new GetRequest(mContext, mUrl, GetRequest.URI_CONFIG, mApiKey, null, result -> {
mConfig = new Gson().fromJson(result, Config.class);
tryIsAvailable();
});
@ -186,14 +183,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Sends current config to Syncthing.
*/
private void sendConfig() {
new PostConfigRequest(mContext, mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), null);
new PostConfigRequest(mContext, mUrl, mApiKey, new Gson().toJson(mConfig), null);
}
/**
* Sends current config and restarts Syncthing.
*/
public void restart() {
new PostConfigRequest(mContext, mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), result -> {
new PostConfigRequest(mContext, mUrl, mApiKey, new Gson().toJson(mConfig), result -> {
Intent intent = new Intent(mContext, SyncthingService.class)
.setAction(SyncthingService.ACTION_RESTART);
mContext.startService(intent);
@ -326,7 +323,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Requests and parses information about current system status and resource usage.
*/
public void getSystemInfo(OnResultListener1<SystemInfo> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM, mHttpsCertPath, mApiKey, null, result ->
new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM, mApiKey, null, result ->
listener.onResult(new Gson().fromJson(result, SystemInfo.class)));
}
@ -338,7 +335,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Requests and parses system version information.
*/
public void getSystemVersion(OnResultListener1<SystemVersion> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> {
new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mApiKey, null, result -> {
SystemVersion systemVersion = new Gson().fromJson(result, SystemVersion.class);
listener.onResult(systemVersion);
});
@ -348,10 +345,10 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Returns connection info for the local device and all connected devices.
*/
public void getConnections(final OnResultListener1<Connections> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_CONNECTIONS, mHttpsCertPath, mApiKey, null, result -> {
new GetRequest(mContext, mUrl, GetRequest.URI_CONNECTIONS, mApiKey, null, result -> {
Long now = System.currentTimeMillis();
Long msElapsed = now - mPreviousConnectionTime;
if (msElapsed < SyncthingService.GUI_UPDATE_INTERVAL) {
if (msElapsed < Constants.GUI_UPDATE_INTERVAL) {
listener.onResult(deepCopy(mPreviousConnections.get(), Connections.class));
return;
}
@ -411,7 +408,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Returns status information about the folder with the given id.
*/
public void getModel(final String folderId, final OnResultListener2<String, Model> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_MODEL, mHttpsCertPath, mApiKey,
new GetRequest(mContext, mUrl, GetRequest.URI_MODEL, mApiKey,
ImmutableMap.of("folder", folderId), result -> {
Model m = new Gson().fromJson(result, Model.class);
mCachedModelInfo.put(folderId, m);
@ -444,7 +441,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
public final void getEvents(final long sinceId, final long limit, final OnReceiveEventListener listener) {
Map<String, String> params =
ImmutableMap.of("since", String.valueOf(sinceId), "limit", String.valueOf(limit));
new GetRequest(mContext, mUrl, GetRequest.URI_EVENTS, mHttpsCertPath, mApiKey, params, result -> {
new GetRequest(mContext, mUrl, GetRequest.URI_EVENTS, mApiKey, params, result -> {
JsonArray jsonEvents = new JsonParser().parse(result).getAsJsonArray();
long lastId = 0;
@ -467,7 +464,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
*/
public void normalizeDeviceId(String id, OnResultListener1<String> listener,
OnResultListener1<String> errorListener) {
new GetRequest(mContext, mUrl, GetRequest.URI_DEVICEID, mHttpsCertPath, mApiKey,
new GetRequest(mContext, mUrl, GetRequest.URI_DEVICEID, mApiKey,
ImmutableMap.of("id", id), result -> {
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
JsonElement normalizedId = json.get("id");
@ -484,14 +481,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
*/
@Override
public void onFolderFileChange(String folderId, String relativePath) {
new PostScanRequest(mContext, mUrl, mHttpsCertPath, mApiKey, folderId, relativePath);
new PostScanRequest(mContext, mUrl, mApiKey, folderId, relativePath);
}
/**
* Returns prettyfied usage report.
*/
public void getUsageReport(final OnResultListener1<String> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_REPORT, mHttpsCertPath, mApiKey, null, result -> {
new GetRequest(mContext, mUrl, GetRequest.URI_REPORT, mApiKey, null, result -> {
JsonElement json = new JsonParser().parse(result);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
listener.onResult(gson.toJson(json));

View File

@ -43,12 +43,11 @@ public class SyncthingRunnable implements Runnable {
private static final String TAG_NATIVE = "SyncthingNativeCode";
private static final String TAG_NICE = "SyncthingRunnableIoNice";
private static final String TAG_KILL = "SyncthingRunnableKill";
private static final String BINARY_NAME = "libsyncthing.so";
private static final int LOG_FILE_MAX_LINES = 10;
private static final AtomicReference<Process> mSyncthing = new AtomicReference<>();
private final Context mContext;
private final String mSyncthingBinary;
private final File mSyncthingBinary;
private String[] mCommand;
private final File mLogFile;
@Inject SharedPreferences mPreferences;
@ -69,18 +68,18 @@ public class SyncthingRunnable implements Runnable {
public SyncthingRunnable(Context context, Command command) {
((SyncthingApp) context.getApplicationContext()).component().inject(this);
mContext = context;
mSyncthingBinary = mContext.getApplicationInfo().nativeLibraryDir + "/" + BINARY_NAME;
mSyncthingBinary = Constants.getSyncthingBinary(mContext);
mLogFile = new File(mContext.getExternalFilesDir(null), "syncthing.log");
mUseRoot = mPreferences.getBoolean(SyncthingService.PREF_USE_ROOT, false) && Shell.SU.available();
mUseRoot = mPreferences.getBoolean(Constants.PREF_USE_ROOT, false) && Shell.SU.available();
switch (command) {
case generate:
mCommand = new String[]{ mSyncthingBinary, "-generate", mContext.getFilesDir().toString() };
mCommand = new String[]{ mSyncthingBinary.getPath(), "-generate", mContext.getFilesDir().toString() };
break;
case main:
mCommand = new String[]{ mSyncthingBinary, "-home", mContext.getFilesDir().toString(), "-no-browser" };
mCommand = new String[]{ mSyncthingBinary.getPath(), "-home", mContext.getFilesDir().toString(), "-no-browser" };
break;
case reset:
mCommand = new String[]{ mSyncthingBinary, "-home", mContext.getFilesDir().toString(), "-reset" };
mCommand = new String[]{ mSyncthingBinary.getPath(), "-home", mContext.getFilesDir().toString(), "-reset" };
break;
default:
throw new InvalidParameterException("Unknown command option");
@ -93,7 +92,7 @@ public class SyncthingRunnable implements Runnable {
int ret;
// Make sure Syncthing is executable
try {
ProcessBuilder pb = new ProcessBuilder("chmod", "500", mSyncthingBinary);
ProcessBuilder pb = new ProcessBuilder("chmod", "500", mSyncthingBinary.getPath());
Process p = pb.start();
p.waitFor();
} catch (IOException|InterruptedException e) {
@ -171,7 +170,7 @@ public class SyncthingRunnable implements Runnable {
* Returns true if the experimental setting for using wake locks has been enabled in settings.
*/
private boolean useWakeLock() {
return mPreferences.getBoolean(SyncthingService.PREF_USE_WAKE_LOCK, false);
return mPreferences.getBoolean(Constants.PREF_USE_WAKE_LOCK, false);
}
/**

View File

@ -9,7 +9,6 @@ import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
@ -35,7 +34,6 @@ import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
@ -59,42 +57,6 @@ public class SyncthingService extends Service implements
public static final String ACTION_RESET =
"com.nutomic.syncthingandroid.service.SyncthingService.RESET";
/**
* Interval in ms at which the GUI is updated (eg {@link com.nutomic.syncthingandroid.fragments.DrawerFragment}).
*/
public static final long GUI_UPDATE_INTERVAL = TimeUnit.SECONDS.toMillis(5);
/**
* name of the public key file in the data directory.
*/
public static final String PUBLIC_KEY_FILE = "cert.pem";
/**
* name of the private key file in the data directory.
*/
public static final String PRIVATE_KEY_FILE = "key.pem";
/**
* name of the public HTTPS CA file in the data directory.
*/
public static final String HTTPS_CERT_FILE = "https-cert.pem";
/**
* Directory where config is exported to and imported from.
*/
public static final File EXPORT_PATH =
new File(Environment.getExternalStorageDirectory(), "backups/syncthing");
public static final String PREF_ALWAYS_RUN_IN_BACKGROUND = "always_run_in_background";
public static final String PREF_SYNC_ONLY_WIFI = "sync_only_wifi";
public static final String PREF_SYNC_ONLY_WIFI_SSIDS = "sync_only_wifi_ssids_set";
public static final String PREF_SYNC_ONLY_CHARGING = "sync_only_charging";
public static final String PREF_RESPECT_BATTERY_SAVING = "respect_battery_saving";
public static final String PREF_USE_ROOT = "use_root";
public static final String PREF_NOTIFICATION_TYPE = "notification_type";
public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running";
public static final String PREF_FOREGROUND_SERVICE = "run_as_foreground_service";
/**
* Callback for when the Syncthing web interface becomes first available after service start.
*/
@ -109,9 +71,6 @@ public class SyncthingService extends Service implements
void onApiChange(State currentState);
}
private final HashSet<OnApiChangeListener> mOnApiChangeListeners =
new HashSet<>();
/**
* Indicates the current state of SyncthingService and of Syncthing itself.
*/
@ -131,25 +90,25 @@ public class SyncthingService extends Service implements
private State mCurrentState = State.INIT;
private ConfigXml mConfig;
private RestApi mApi;
private EventProcessor mEventProcessor;
private DeviceStateHolder mDeviceStateHolder;
private SyncthingRunnable mSyncthingRunnable;
private final LinkedList<FolderObserver> mObservers = new LinkedList<>();
private final HashSet<OnApiChangeListener> mOnApiChangeListeners = new HashSet<>();
private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this);
private final NetworkReceiver mNetworkReceiver = new NetworkReceiver();
private final BroadcastReceiver mPowerSaveModeChangedReceiver = new PowerSaveModeChangedReceiver();
@Inject NotificationHandler mNotificationHandler;
@Inject SharedPreferences mPreferences;
/**
* Object that can be locked upon when accessing mCurrentState
* Currently used to male onDestroy() and PollWebGuiAvailableTaskImpl.onPostExcecute() tread-safe
*/
private final Object stateLock = new Object();
private final Object mStateLock = new Object();
/**
* True if a stop was requested while syncthing is starting, in that case, perform stop in
@ -157,12 +116,6 @@ public class SyncthingService extends Service implements
*/
private boolean mStopScheduled = false;
private DeviceStateHolder mDeviceStateHolder;
private SyncthingRunnable mSyncthingRunnable;
@Inject SharedPreferences mPreferences;
/**
* Handles intents, either {@link #ACTION_RESTART}, or intents having
* {@link DeviceStateHolder#EXTRA_IS_ALLOWED_NETWORK_CONNECTION} or
@ -218,10 +171,10 @@ public class SyncthingService extends Service implements
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(PREF_NOTIFICATION_TYPE) || key.equals(PREF_FOREGROUND_SERVICE))
if (key.equals(Constants.PREF_NOTIFICATION_TYPE) || key.equals(Constants.PREF_FOREGROUND_SERVICE))
mNotificationHandler.updatePersistentNotification(this, mCurrentState);
else if (key.equals(PREF_SYNC_ONLY_CHARGING) || key.equals(PREF_SYNC_ONLY_WIFI)
|| key.equals(PREF_SYNC_ONLY_WIFI_SSIDS) || key.equals(PREF_RESPECT_BATTERY_SAVING)) {
else if (key.equals(Constants.PREF_SYNC_ONLY_CHARGING) || key.equals(Constants.PREF_SYNC_ONLY_WIFI)
|| key.equals(Constants.PREF_SYNC_ONLY_WIFI_SSIDS) || key.equals(Constants.PREF_RESPECT_BATTERY_SAVING)) {
updateState();
}
}
@ -328,7 +281,7 @@ public class SyncthingService extends Service implements
@Override
public void onDestroy() {
synchronized (stateLock) {
synchronized (mStateLock) {
if (mCurrentState == State.INIT || mCurrentState == State.STARTING) {
Log.i(TAG, "Delay shutting down service until initialisation of Syncthing finished");
mStopScheduled = true;
@ -424,9 +377,8 @@ public class SyncthingService extends Service implements
* for SyncthingService.onDestroy for details.
*/
private void pollWebGui() {
new PollWebGuiAvailableTask(this, getWebGuiUrl(), new File(getFilesDir(), HTTPS_CERT_FILE),
mConfig.getApiKey(), result -> {
synchronized (stateLock) {
new PollWebGuiAvailableTask(this, getWebGuiUrl(), mConfig.getApiKey(), result -> {
synchronized (mStateLock) {
if (mStopScheduled) {
shutdown(State.DISABLED, () -> {});
mStopScheduled = false;
@ -469,42 +421,42 @@ public class SyncthingService extends Service implements
*/
public static boolean alwaysRunInBackground(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return sp.getBoolean(PREF_ALWAYS_RUN_IN_BACKGROUND, false);
return sp.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false);
}
/**
* Exports the local config and keys to {@link #EXPORT_PATH}.
* Exports the local config and keys to {@link Constants#EXPORT_PATH}.
*/
public void exportConfig() {
EXPORT_PATH.mkdirs();
Constants.EXPORT_PATH.mkdirs();
try {
Files.copy(new File(getFilesDir(), ConfigXml.CONFIG_FILE),
new File(EXPORT_PATH, ConfigXml.CONFIG_FILE));
Files.copy(new File(getFilesDir(), PRIVATE_KEY_FILE),
new File(EXPORT_PATH, PRIVATE_KEY_FILE));
Files.copy(new File(getFilesDir(), PUBLIC_KEY_FILE),
new File(EXPORT_PATH, PUBLIC_KEY_FILE));
Files.copy(Constants.getConfigFile(this),
new File(Constants.EXPORT_PATH, Constants.CONFIG_FILE));
Files.copy(Constants.getPrivateKeyFile(this),
new File(Constants.EXPORT_PATH, Constants.PRIVATE_KEY_FILE));
Files.copy(Constants.getPublicKeyFile(this),
new File(Constants.EXPORT_PATH, Constants.PUBLIC_KEY_FILE));
} catch (IOException e) {
Log.w(TAG, "Failed to export config", e);
}
}
/**
* Imports config and keys from {@link #EXPORT_PATH}.
* Imports config and keys from {@link Constants#EXPORT_PATH}.
*
* @return True if the import was successful, false otherwise (eg if files aren't found).
*/
public boolean importConfig() {
File config = new File(EXPORT_PATH, ConfigXml.CONFIG_FILE);
File privateKey = new File(EXPORT_PATH, PRIVATE_KEY_FILE);
File publicKey = new File(EXPORT_PATH, PUBLIC_KEY_FILE);
File config = new File(Constants.EXPORT_PATH, Constants.CONFIG_FILE);
File privateKey = new File(Constants.EXPORT_PATH, Constants.PRIVATE_KEY_FILE);
File publicKey = new File(Constants.EXPORT_PATH, Constants.PUBLIC_KEY_FILE);
if (!config.exists() || !privateKey.exists() || !publicKey.exists())
return false;
shutdown(State.INIT, () -> {
try {
Files.copy(config, new File(getFilesDir(), ConfigXml.CONFIG_FILE));
Files.copy(privateKey, new File(getFilesDir(), PRIVATE_KEY_FILE));
Files.copy(publicKey, new File(getFilesDir(), PUBLIC_KEY_FILE));
Files.copy(config, Constants.getConfigFile(this));
Files.copy(privateKey, Constants.getPrivateKeyFile(this));
Files.copy(publicKey, Constants.getPublicKeyFile(this));
} catch (IOException e) {
Log.w(TAG, "Failed to import config", e);
}

View File

@ -7,6 +7,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.SyncthingRunnable;
import org.mindrot.jbcrypt.BCrypt;
@ -43,11 +44,6 @@ public class ConfigXml {
private static final String TAG = "ConfigXml";
/**
* File in the config folder that contains configuration.
*/
public static final String CONFIG_FILE = "config.xml";
private final Context mContext;
private final File mConfigFile;
@ -56,7 +52,7 @@ public class ConfigXml {
public ConfigXml(Context context) throws OpenConfigException {
mContext = context;
mConfigFile = getConfigFile(context);
mConfigFile = Constants.getConfigFile(mContext);
boolean isFirstStart = !mConfigFile.exists();
if (isFirstStart) {
Log.i(TAG, "App started for the first time. Generating keys and config.");
@ -89,10 +85,6 @@ public class ConfigXml {
new SyncthingRunnable(context, SyncthingRunnable.Command.generate).run();
}
public static File getConfigFile(Context context) {
return new File(context.getFilesDir(), CONFIG_FILE);
}
public URL getWebGuiUrl() {
try {
return new URL("https://" + getGuiElement().getElementsByTagName("address").item(0).getTextContent());