1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-11-22 20:31:16 +00:00

Show reasons for disabled service in notification dialog (#1264)

This commit is contained in:
Martin Carpella 2019-01-21 22:05:45 +01:00 committed by Audrius Butkevicius
parent 9796d7beb1
commit 700c55e9d3
5 changed files with 233 additions and 37 deletions

View file

@ -5,18 +5,23 @@ import android.content.Intent;
import android.databinding.DataBindingUtil; import android.databinding.DataBindingUtil;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.view.View; import android.view.View;
import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.databinding.DialogLoadingBinding; import com.nutomic.syncthingandroid.databinding.DialogLoadingBinding;
import com.nutomic.syncthingandroid.model.RunConditionCheckResult;
import com.nutomic.syncthingandroid.service.SyncthingService; import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.service.SyncthingService.State; import com.nutomic.syncthingandroid.service.SyncthingService.State;
import com.nutomic.syncthingandroid.util.Util; import com.nutomic.syncthingandroid.util.Util;
import java.util.Collection;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.nutomic.syncthingandroid.model.RunConditionCheckResult.*;
/** /**
* Handles loading/disabled dialogs. * Handles loading/disabled dialogs.
*/ */
@ -32,8 +37,10 @@ public abstract class StateDialogActivity extends SyncthingActivity {
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
registerOnServiceConnectedListener(() -> registerOnServiceConnectedListener(() -> {
getService().registerOnServiceStateChangeListener(this::onServiceStateChange)); getService().registerOnServiceStateChangeListener(this::onServiceStateChange);
getService().registerOnRunConditionCheckResultChange(this::onRunConditionCheckResultChange);
});
} }
@Override @Override
@ -62,6 +69,7 @@ public abstract class StateDialogActivity extends SyncthingActivity {
super.onDestroy(); super.onDestroy();
if (getService() != null) { if (getService() != null) {
getService().unregisterOnServiceStateChangeListener(this::onServiceStateChange); getService().unregisterOnServiceStateChangeListener(this::onServiceStateChange);
getService().unregisterOnRunConditionCheckResultChange(this::onRunConditionCheckResultChange);
} }
dismissDisabledDialog(); dismissDisabledDialog();
} }
@ -89,13 +97,20 @@ public abstract class StateDialogActivity extends SyncthingActivity {
} }
} }
private void onRunConditionCheckResultChange(RunConditionCheckResult result) {
if (mDisabledDialog != null && mDisabledDialog.isShowing()) {
mDisabledDialog.setMessage(getDisabledDialogMessage());
}
}
private void showDisabledDialog() { private void showDisabledDialog() {
if (this.isFinishing() && (mDisabledDialog != null)) { if (this.isFinishing() && (mDisabledDialog != null)) {
return; return;
} }
mDisabledDialog = new AlertDialog.Builder(this) mDisabledDialog = new AlertDialog.Builder(this)
.setTitle(R.string.syncthing_disabled_title) .setTitle(R.string.syncthing_disabled_title)
.setMessage(R.string.syncthing_disabled_message) .setMessage(getDisabledDialogMessage())
.setPositiveButton(R.string.syncthing_disabled_change_settings, .setPositiveButton(R.string.syncthing_disabled_change_settings,
(dialogInterface, i) -> { (dialogInterface, i) -> {
Intent intent = new Intent(this, SettingsActivity.class); Intent intent = new Intent(this, SettingsActivity.class);
@ -110,6 +125,26 @@ public abstract class StateDialogActivity extends SyncthingActivity {
.show(); .show();
} }
@NonNull
private StringBuilder getDisabledDialogMessage() {
StringBuilder message = new StringBuilder();
message.append(this.getResources().getString(R.string.syncthing_disabled_message));
Collection<BlockerReason> reasons = getService().getCurrentRunConditionCheckResult().getBlockReasons();
if (!reasons.isEmpty()) {
message.append("\n");
message.append("\n");
message.append(this.getResources().getString(R.string.syncthing_disabled_reason_heading));
int count = 0;
for (BlockerReason reason : reasons) {
count++;
message.append("\n");
if (reasons.size() > 1) message.append(count + ". ");
message.append(this.getString(reason.getResId()));
}
}
return message;
}
private void dismissDisabledDialog() { private void dismissDisabledDialog() {
Util.dismissDialogSafe(mDisabledDialog, this); Util.dismissDialogSafe(mDisabledDialog, this);
mDisabledDialog = null; mDisabledDialog = null;

View file

@ -0,0 +1,78 @@
package com.nutomic.syncthingandroid.model;
import com.nutomic.syncthingandroid.R;
import java.util.Collections;
import java.util.List;
public class RunConditionCheckResult {
public enum BlockerReason {
ON_BATTERY(R.string.syncthing_disabled_reason_on_battery),
ON_CHARGER(R.string.syncthing_disabled_reason_on_charger),
POWERSAVING_ENABLED(R.string.syncthing_disabled_reason_powersaving),
GLOBAL_SYNC_DISABLED(R.string.syncthing_disabled_reason_android_sync_disabled),
WIFI_SSID_NOT_WHITELISTED(R.string.syncthing_disabled_reason_wifi_ssid_not_whitelisted),
WIFI_WIFI_IS_METERED(R.string.syncthing_disabled_reason_wifi_is_metered),
NO_NETWORK_OR_FLIGHTMODE(R.string.syncthing_disabled_reason_no_network_or_flightmode),
NO_MOBILE_CONNECTION(R.string.syncthing_disabled_reason_no_mobile_connection),
NO_WIFI_CONNECTION(R.string.syncthing_disabled_reason_no_wifi_connection),
NO_ALLOWED_NETWORK(R.string.syncthing_disabled_reason_no_allowed_method);
private final int resId;
BlockerReason(int resId) {
this.resId = resId;
}
public int getResId() {
return resId;
}
}
public static final RunConditionCheckResult SHOULD_RUN = new RunConditionCheckResult();
private final boolean mShouldRun;
private final List<BlockerReason> mBlockReasons;
/**
* Use SHOULD_RUN instead.
* Note: of course anybody could still construct it by providing an empty list to the other
* constructor.
*/
private RunConditionCheckResult() {
this(Collections.emptyList());
}
public RunConditionCheckResult(List<BlockerReason> blockReasons) {
mBlockReasons = Collections.unmodifiableList(blockReasons);
mShouldRun = blockReasons.isEmpty();
}
public List<BlockerReason> getBlockReasons() {
return mBlockReasons;
}
public boolean isShouldRun() {
return mShouldRun;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RunConditionCheckResult that = (RunConditionCheckResult) o;
if (mShouldRun != that.mShouldRun) return false;
return mBlockReasons.equals(that.mBlockReasons);
}
@Override
public int hashCode() {
int result = (mShouldRun ? 1 : 0);
result = 31 * result + mBlockReasons.hashCode();
return result;
}
}

View file

@ -16,19 +16,21 @@ import android.os.BatteryManager;
import android.os.Build; import android.os.Build;
import android.os.PowerManager; import android.os.PowerManager;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log; import android.util.Log;
import com.google.common.collect.Lists;
import com.nutomic.syncthingandroid.SyncthingApp; import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.service.ReceiverManager; import com.nutomic.syncthingandroid.model.RunConditionCheckResult;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import static com.nutomic.syncthingandroid.model.RunConditionCheckResult.*;
import static com.nutomic.syncthingandroid.model.RunConditionCheckResult.BlockerReason.*;
/** /**
* Holds information about the current wifi and charging state of the device. * Holds information about the current wifi and charging state of the device.
* *
@ -52,7 +54,7 @@ public class RunConditionMonitor {
}; };
public interface OnRunConditionChangedListener { public interface OnRunConditionChangedListener {
void onRunConditionChanged(boolean shouldRun); void onRunConditionChanged(RunConditionCheckResult result);
} }
private final Context mContext; private final Context mContext;
@ -60,14 +62,14 @@ public class RunConditionMonitor {
private ReceiverManager mReceiverManager; private ReceiverManager mReceiverManager;
/** /**
* Sending callback notifications through {@link OnDeviceStateChangedListener} is enabled if not null. * Sending callback notifications through {@link OnRunConditionChangedListener} is enabled if not null.
*/ */
private @Nullable OnRunConditionChangedListener mOnRunConditionChangedListener = null; private @Nullable OnRunConditionChangedListener mOnRunConditionChangedListener = null;
/** /**
* Stores the result of the last call to {@link decideShouldRun}. * Stores the result of the last call to {@link #decideShouldRun()}.
*/ */
private boolean lastDeterminedShouldRun = false; private RunConditionCheckResult lastRunConditionCheckResult;
public RunConditionMonitor(Context context, OnRunConditionChangedListener listener) { public RunConditionMonitor(Context context, OnRunConditionChangedListener listener) {
Log.v(TAG, "Created new instance"); Log.v(TAG, "Created new instance");
@ -140,21 +142,25 @@ public class RunConditionMonitor {
} }
public void updateShouldRunDecision() { public void updateShouldRunDecision() {
// Check if the current conditions changed the result of decideShouldRun() // Reason if the current conditions changed the result of decideShouldRun()
// compared to the last determined result. // compared to the last determined result.
boolean newShouldRun = decideShouldRun(); RunConditionCheckResult result = decideShouldRun();
if (newShouldRun != lastDeterminedShouldRun) { boolean change;
synchronized (this) {
change = lastRunConditionCheckResult == null || !lastRunConditionCheckResult.equals(result);
lastRunConditionCheckResult = result;
}
if (change) {
if (mOnRunConditionChangedListener != null) { if (mOnRunConditionChangedListener != null) {
mOnRunConditionChangedListener.onRunConditionChanged(newShouldRun); mOnRunConditionChangedListener.onRunConditionChanged(result);
} }
lastDeterminedShouldRun = newShouldRun;
} }
} }
/** /**
* Determines if Syncthing should currently run. * Determines if Syncthing should currently run.
*/ */
private boolean decideShouldRun() { private RunConditionCheckResult decideShouldRun() {
// Get run conditions preferences. // Get run conditions preferences.
boolean prefRunOnMobileData= mPreferences.getBoolean(Constants.PREF_RUN_ON_MOBILE_DATA, false); boolean prefRunOnMobileData= mPreferences.getBoolean(Constants.PREF_RUN_ON_MOBILE_DATA, false);
boolean prefRunOnWifi= mPreferences.getBoolean(Constants.PREF_RUN_ON_WIFI, true); boolean prefRunOnWifi= mPreferences.getBoolean(Constants.PREF_RUN_ON_WIFI, true);
@ -166,18 +172,20 @@ public class RunConditionMonitor {
boolean prefRespectPowerSaving = mPreferences.getBoolean(Constants.PREF_RESPECT_BATTERY_SAVING, true); boolean prefRespectPowerSaving = mPreferences.getBoolean(Constants.PREF_RESPECT_BATTERY_SAVING, true);
boolean prefRespectMasterSync = mPreferences.getBoolean(Constants.PREF_RESPECT_MASTER_SYNC, false); boolean prefRespectMasterSync = mPreferences.getBoolean(Constants.PREF_RESPECT_MASTER_SYNC, false);
List<BlockerReason> blockerReasons = new ArrayList<>();
// PREF_POWER_SOURCE // PREF_POWER_SOURCE
switch (prefPowerSource) { switch (prefPowerSource) {
case POWER_SOURCE_CHARGER: case POWER_SOURCE_CHARGER:
if (!isCharging()) { if (!isCharging()) {
Log.v(TAG, "decideShouldRun: POWER_SOURCE_AC && !isCharging"); Log.v(TAG, "decideShouldRun: POWER_SOURCE_AC && !isCharging");
return false; blockerReasons.add(ON_BATTERY);
} }
break; break;
case POWER_SOURCE_BATTERY: case POWER_SOURCE_BATTERY:
if (isCharging()) { if (isCharging()) {
Log.v(TAG, "decideShouldRun: POWER_SOURCE_BATTERY && isCharging"); Log.v(TAG, "decideShouldRun: POWER_SOURCE_BATTERY && isCharging");
return false; blockerReasons.add(ON_CHARGER);
} }
break; break;
case POWER_SOURCE_CHARGER_BATTERY: case POWER_SOURCE_CHARGER_BATTERY:
@ -189,35 +197,43 @@ public class RunConditionMonitor {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (prefRespectPowerSaving && isPowerSaving()) { if (prefRespectPowerSaving && isPowerSaving()) {
Log.v(TAG, "decideShouldRun: prefRespectPowerSaving && isPowerSaving"); Log.v(TAG, "decideShouldRun: prefRespectPowerSaving && isPowerSaving");
return false; blockerReasons.add(POWERSAVING_ENABLED);
} }
} }
// Android global AutoSync setting. // Android global AutoSync setting.
if (prefRespectMasterSync && !ContentResolver.getMasterSyncAutomatically()) { if (prefRespectMasterSync && !ContentResolver.getMasterSyncAutomatically()) {
Log.v(TAG, "decideShouldRun: prefRespectMasterSync && !getMasterSyncAutomatically"); Log.v(TAG, "decideShouldRun: prefRespectMasterSync && !getMasterSyncAutomatically");
return false; blockerReasons.add(GLOBAL_SYNC_DISABLED);
} }
// Run on mobile data. // Run on mobile data.
if (prefRunOnMobileData && isMobileDataConnection()) { if (blockerReasons.isEmpty() && prefRunOnMobileData && isMobileDataConnection()) {
Log.v(TAG, "decideShouldRun: prefRunOnMobileData && isMobileDataConnection"); Log.v(TAG, "decideShouldRun: prefRunOnMobileData && isMobileDataConnection");
return true; return SHOULD_RUN;
} }
// Run on wifi. // Run on wifi.
if (prefRunOnWifi && isWifiOrEthernetConnection()) { if (prefRunOnWifi && isWifiOrEthernetConnection()) {
if (prefRunOnMeteredWifi) { if (prefRunOnMeteredWifi) {
// We are on non-metered or metered wifi. Check if wifi whitelist run condition is met. // We are on non-metered or metered wifi. Reason if wifi whitelist run condition is met.
if (wifiWhitelistConditionMet(prefWifiWhitelistEnabled, whitelistedWifiSsids)) { if (wifiWhitelistConditionMet(prefWifiWhitelistEnabled, whitelistedWifiSsids)) {
Log.v(TAG, "decideShouldRun: prefRunOnWifi && isWifiOrEthernetConnection && prefRunOnMeteredWifi && wifiWhitelistConditionMet"); Log.v(TAG, "decideShouldRun: prefRunOnWifi && isWifiOrEthernetConnection && prefRunOnMeteredWifi && wifiWhitelistConditionMet");
return true; if (blockerReasons.isEmpty()) return SHOULD_RUN;
} else {
blockerReasons.add(WIFI_SSID_NOT_WHITELISTED);
} }
} else { } else {
// Check if we are on a non-metered wifi and if wifi whitelist run condition is met. // Reason if we are on a non-metered wifi and if wifi whitelist run condition is met.
if (!isMeteredNetworkConnection() && wifiWhitelistConditionMet(prefWifiWhitelistEnabled, whitelistedWifiSsids)) { if (!isMeteredNetworkConnection()) {
Log.v(TAG, "decideShouldRun: prefRunOnWifi && isWifiOrEthernetConnection && !prefRunOnMeteredWifi && !isMeteredNetworkConnection && wifiWhitelistConditionMet"); if (wifiWhitelistConditionMet(prefWifiWhitelistEnabled, whitelistedWifiSsids)) {
return true; Log.v(TAG, "decideShouldRun: prefRunOnWifi && isWifiOrEthernetConnection && !prefRunOnMeteredWifi && !isMeteredNetworkConnection && wifiWhitelistConditionMet");
if (blockerReasons.isEmpty()) return SHOULD_RUN;
} else {
blockerReasons.add(WIFI_SSID_NOT_WHITELISTED);
}
} else {
blockerReasons.add(WIFI_WIFI_IS_METERED);
} }
} }
} }
@ -225,14 +241,27 @@ public class RunConditionMonitor {
// Run in flight mode. // Run in flight mode.
if (prefRunInFlightMode && isFlightMode()) { if (prefRunInFlightMode && isFlightMode()) {
Log.v(TAG, "decideShouldRun: prefRunInFlightMode && isFlightMode"); Log.v(TAG, "decideShouldRun: prefRunInFlightMode && isFlightMode");
return true; if (blockerReasons.isEmpty()) return SHOULD_RUN;
} }
/** /**
* If none of the above run conditions matched, don't run. * If none of the above run conditions matched, don't run.
*/ */
Log.v(TAG, "decideShouldRun: return false"); Log.v(TAG, "decideShouldRun: return false");
return false; if (blockerReasons.isEmpty()) {
if (isFlightMode()) {
blockerReasons.add(NO_NETWORK_OR_FLIGHTMODE);
} else if (!prefRunOnWifi && !prefRunOnMobileData) {
blockerReasons.add(NO_ALLOWED_NETWORK);
} else if (prefRunOnMobileData) {
blockerReasons.add(NO_MOBILE_CONNECTION);
} else if (prefRunOnWifi) {
blockerReasons.add(NO_WIFI_CONNECTION);
} else {
blockerReasons.add(NO_NETWORK_OR_FLIGHTMODE);
}
}
return new RunConditionCheckResult(blockerReasons);
} }
/** /**

View file

@ -1,33 +1,34 @@
package com.nutomic.syncthingandroid.service; package com.nutomic.syncthingandroid.service;
import android.Manifest;
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.Manifest; import android.content.pm.PackageManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import com.android.PRNGFixes; import com.android.PRNGFixes;
import com.annimon.stream.Stream;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp; import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask; import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask;
import com.nutomic.syncthingandroid.model.Folder; import com.nutomic.syncthingandroid.model.RunConditionCheckResult;
import com.nutomic.syncthingandroid.util.ConfigXml; import com.nutomic.syncthingandroid.util.ConfigXml;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject; import javax.inject.Inject;
@ -99,6 +100,10 @@ public class SyncthingService extends Service {
void onServiceStateChange(State currentState); void onServiceStateChange(State currentState);
} }
public interface OnRunConditionCheckResultListener {
void onRunConditionCheckResultChanged(RunConditionCheckResult result);
}
/** /**
* Indicates the current state of SyncthingService and of Syncthing itself. * Indicates the current state of SyncthingService and of Syncthing itself.
*/ */
@ -124,6 +129,7 @@ public class SyncthingService extends Service {
* {@link onStartCommand}. * {@link onStartCommand}.
*/ */
private State mCurrentState = State.DISABLED; private State mCurrentState = State.DISABLED;
private AtomicReference<RunConditionCheckResult> mCurrentCheckResult = new AtomicReference<>(RunConditionCheckResult.SHOULD_RUN);
private ConfigXml mConfig; private ConfigXml mConfig;
private @Nullable PollWebGuiAvailableTask mPollWebGuiAvailableTask = null; private @Nullable PollWebGuiAvailableTask mPollWebGuiAvailableTask = null;
@ -136,6 +142,7 @@ public class SyncthingService extends Service {
private Handler mHandler; private Handler mHandler;
private final HashSet<OnServiceStateChangeListener> mOnServiceStateChangeListeners = new HashSet<>(); private final HashSet<OnServiceStateChangeListener> mOnServiceStateChangeListeners = new HashSet<>();
private final HashSet<OnRunConditionCheckResultListener> mOnRunConditionCheckResultListeners = new HashSet<>();
private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this); private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this);
@Inject NotificationHandler mNotificationHandler; @Inject NotificationHandler mNotificationHandler;
@ -262,7 +269,13 @@ public class SyncthingService extends Service {
* function is called to notify this class to run/terminate the syncthing binary. * function is called to notify this class to run/terminate the syncthing binary.
* {@link #onServiceStateChange} is called while applying the decision change. * {@link #onServiceStateChange} is called while applying the decision change.
*/ */
private void onUpdatedShouldRunDecision(boolean newShouldRunDecision) { private void onUpdatedShouldRunDecision(RunConditionCheckResult result) {
boolean newShouldRunDecision = result.isShouldRun();
boolean reasonsChanged = !mCurrentCheckResult.getAndSet(result).equals(result);
if (reasonsChanged) {
onRunConditionCheckResultChange(result);
}
if (newShouldRunDecision != mLastDeterminedShouldRun) { if (newShouldRunDecision != mLastDeterminedShouldRun) {
Log.i(TAG, "shouldRun decision changed to " + newShouldRunDecision + " according to configured run conditions."); Log.i(TAG, "shouldRun decision changed to " + newShouldRunDecision + " according to configured run conditions.");
mLastDeterminedShouldRun = newShouldRunDecision; mLastDeterminedShouldRun = newShouldRunDecision;
@ -578,6 +591,30 @@ public class SyncthingService extends Service {
}); });
} }
public void registerOnRunConditionCheckResultChange(OnRunConditionCheckResultListener listener) {
listener.onRunConditionCheckResultChanged(mCurrentCheckResult.get());
mOnRunConditionCheckResultListeners.add(listener);
}
public void unregisterOnRunConditionCheckResultChange(OnRunConditionCheckResultListener listener) {
mOnRunConditionCheckResultListeners.remove(listener);
}
private void onRunConditionCheckResultChange(RunConditionCheckResult result) {
mHandler.post(() -> {
for (Iterator<OnRunConditionCheckResultListener> i = mOnRunConditionCheckResultListeners.iterator();
i.hasNext(); ) {
OnRunConditionCheckResultListener listener = i.next();
if (listener != null) {
listener.onRunConditionCheckResultChanged(result);
} else {
i.remove();
}
}
});
}
public URL getWebGuiUrl() { public URL getWebGuiUrl() {
return mConfig.getWebGuiUrl(); return mConfig.getWebGuiUrl();
} }
@ -586,6 +623,10 @@ public class SyncthingService extends Service {
return mCurrentState; return mCurrentState;
} }
public RunConditionCheckResult getCurrentRunConditionCheckResult() {
return mCurrentCheckResult.get();
}
public NotificationHandler getNotificationHandler() { public NotificationHandler getNotificationHandler() {
return mNotificationHandler; return mNotificationHandler;
} }

View file

@ -653,6 +653,19 @@ Please report any problems you encounter via Github.</string>
<!-- Button text on the "syncthing disabled" dialog, used as menu item to stop syncthing service if "always_run_in_background" is true --> <!-- Button text on the "syncthing disabled" dialog, used as menu item to stop syncthing service if "always_run_in_background" is true -->
<string name="exit">Exit</string> <string name="exit">Exit</string>
<!-- Reasons for "syncthing disabled" dialog -->
<string name="syncthing_disabled_reason_heading">Reasons:</string>
<string name="syncthing_disabled_reason_on_battery">Device is running on battery</string>
<string name="syncthing_disabled_reason_on_charger">Device is running on charger</string>
<string name="syncthing_disabled_reason_powersaving">Device is in power-saving mode</string>
<string name="syncthing_disabled_reason_android_sync_disabled">Global Synchronization is disabled</string>
<string name="syncthing_disabled_reason_wifi_ssid_not_whitelisted">Current WiFi SSID is not whitelisted</string>
<string name="syncthing_disabled_reason_wifi_is_metered">Current WiFi is metered</string>
<string name="syncthing_disabled_reason_no_network_or_flightmode">No network connection or airplane mode enabled</string>
<string name="syncthing_disabled_reason_no_mobile_connection">Not connected to mobile data</string>
<string name="syncthing_disabled_reason_no_wifi_connection">Not connected to WiFi</string>
<string name="syncthing_disabled_reason_no_allowed_method">Not configured to sync on WiFi nor mobile data</string>
<!-- Title of the notification shown while syncthing is running and enabled --> <!-- Title of the notification shown while syncthing is running and enabled -->
<string name="syncthing_active">Syncthing is running</string> <string name="syncthing_active">Syncthing is running</string>