1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-12-01 16:51:16 +00:00

Fix service.startForeground on Android 8+ (fixes #18) (fixes #80) (#79)

* Add push APK to device after build script

* Fix typo in SyncthingService comment

* Refactor SettingsActivity - updatePersistentNotification

Call updatePersistentNotification after the settings screen was left and not when the user toggles the alwaysRunInBackgroundAsAService checkbox.

* Automatically start app if push-to-device is enabled

* Remove PREF_NOTIFICATION_TYPE

* Only push APK to device if build succeeded

* Fix notifications and foreground service start/stop

* Use startForegroundService on Android 8+

* Fix startActivity called from non-Activity context (fixes #80)

* Fix comment
This commit is contained in:
Catfriend1 2018-10-08 05:00:59 +02:00 committed by GitHub
parent cd3bca5141
commit c224bcb04a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 229 additions and 133 deletions

3
.gitignore vendored
View file

@ -44,3 +44,6 @@ syncthing/mingit.zip
# External build artifacts # External build artifacts
ext/ ext/
# push-to-device after build marker file
\#enable_push_to_device

View file

@ -58,6 +58,11 @@ android {
signingConfig = signingConfigs.release.storeFile ? signingConfigs.release : null signingConfig = signingConfigs.release.storeFile ? signingConfigs.release : null
} }
debug { debug {
gradle.buildFinished {
buildResult -> if (!buildResult.failure) {
pushToDevice.execute()
}
}
} }
} }
@ -82,3 +87,8 @@ task deleteUnsupportedPlayTranslations(type: Delete) {
delete 'src/main/play/nb' delete 'src/main/play/nb'
delete 'src/main/play/en/' delete 'src/main/play/en/'
} }
task pushToDevice(type: Exec) {
executable = 'python'
args = ['-u', './push-to-device.py']
}

91
app/push-to-device.py Normal file
View file

@ -0,0 +1,91 @@
from __future__ import print_function
import os
import os.path
import sys
import subprocess
import platform
#
# Script Compatibility:
# - Python 2.7.15
# - Python 3.7.0
#
SUPPORTED_PYTHON_PLATFORMS = ['Windows', 'Linux', 'Darwin']
def fail(message, *args, **kwargs):
print((message % args).format(**kwargs))
sys.exit(1)
def which(program):
import os
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
if (sys.platform == 'win32'):
program += ".exe"
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
#
# Push APK to device.
#
if platform.system() not in SUPPORTED_PYTHON_PLATFORMS:
fail('Unsupported python platform %s. Supported platforms: %s', platform.system(),
', '.join(SUPPORTED_PYTHON_PLATFORMS))
print ('')
# Build FullFN of "app-debug.apk".
current_dir = os.path.dirname(os.path.realpath(__file__))
enable_push_to_device = os.path.realpath(os.path.join(current_dir, "..", "#enable_push_to_device"))
# Check if push to device is enabled.
if not enable_push_to_device or not os.path.isfile(enable_push_to_device):
print('[INFO] push-to-device after build is DISABLED. To enable it, create the file \'' + enable_push_to_device + '\'')
sys.exit(0)
debug_apk = os.path.realpath(os.path.join(current_dir, 'build', 'outputs', 'apk', 'debug', 'app-debug.apk'))
if not debug_apk or not os.path.isfile(debug_apk):
fail('[ERROR] app-debug.apk not found.');
print('[INFO] debug_apk=' + debug_apk)
# Check if adb is available.
adb_bin = which("adb");
if not adb_bin:
print('[WARNING] adb is not available on the PATH.')
# install_adb();
# Retry: Check if adb is available.
# adb_bin = which("adb");
# if not adb_bin:
# fail('[ERROR] adb is not available on the PATH.')
print('[INFO] adb_bin=\'' + adb_bin + '\'')
print('[INFO] Connecting to attached usb device ...')
try:
subprocess.check_call([
adb_bin,
'devices'
])
except:
sys.exit(0)
print('[INFO] Installing APK to attached usb device ...')
try:
subprocess.check_call(adb_bin + ' install -r --user 0 ' + debug_apk)
except:
sys.exit(0)
print('[INFO] Starting app ...')
try:
subprocess.check_call(adb_bin + ' shell monkey -p com.github.catfriend1.syncthingandroid.debug 1')
except:
sys.exit(0)

View file

@ -196,7 +196,12 @@ public class MainActivity extends SyncthingActivity
// SyncthingService needs to be started from this activity as the user // SyncthingService needs to be started from this activity as the user
// can directly launch this activity from the recent activity switcher. // can directly launch this activity from the recent activity switcher.
startService(new Intent(this, SyncthingService.class)); Intent serviceIntent = new Intent(this, SyncthingService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}
onNewIntent(getIntent()); onNewIntent(getIntent());
} }

View file

@ -87,7 +87,7 @@ public class SettingsActivity extends SyncthingActivity {
public static class SettingsFragment extends PreferenceFragment public static class SettingsFragment extends PreferenceFragment
implements SyncthingActivity.OnServiceConnectedListener, implements SyncthingActivity.OnServiceConnectedListener,
SyncthingService.OnServiceStateChangeListener, Preference.OnPreferenceChangeListener, SyncthingService.OnServiceStateChangeListener, Preference.OnPreferenceChangeListener,
Preference.OnPreferenceClickListener, SharedPreferences.OnSharedPreferenceChangeListener { Preference.OnPreferenceClickListener {
private static final String TAG = "SettingsFragment"; private static final String TAG = "SettingsFragment";
private static final String KEY_EXPORT_CONFIG = "export_config"; private static final String KEY_EXPORT_CONFIG = "export_config";
@ -100,7 +100,7 @@ public class SettingsActivity extends SyncthingActivity {
@Inject SharedPreferences mPreferences; @Inject SharedPreferences mPreferences;
private Preference mCategoryRunConditions; private Preference mCategoryRunConditions;
private CheckBoxPreference mAlwaysRunInBackground; private CheckBoxPreference mStartServiceOnBoot;
private ListPreference mPowerSource; private ListPreference mPowerSource;
private CheckBoxPreference mRunOnMobileData; private CheckBoxPreference mRunOnMobileData;
private CheckBoxPreference mRunOnWifi; private CheckBoxPreference mRunOnWifi;
@ -150,7 +150,6 @@ public class SettingsActivity extends SyncthingActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
((SyncthingApp) getActivity().getApplication()).component().inject(this); ((SyncthingApp) getActivity().getApplication()).component().inject(this);
((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this); ((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this);
mPreferences.registerOnSharedPreferenceChangeListener(this);
} }
/** /**
@ -164,8 +163,8 @@ public class SettingsActivity extends SyncthingActivity {
addPreferencesFromResource(R.xml.app_settings); addPreferencesFromResource(R.xml.app_settings);
PreferenceScreen screen = getPreferenceScreen(); PreferenceScreen screen = getPreferenceScreen();
mAlwaysRunInBackground = mStartServiceOnBoot =
(CheckBoxPreference) findPreference(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND); (CheckBoxPreference) findPreference(Constants.PREF_START_SERVICE_ON_BOOT);
mPowerSource = mPowerSource =
(ListPreference) findPreference(Constants.PREF_POWER_SOURCE); (ListPreference) findPreference(Constants.PREF_POWER_SOURCE);
mRunOnMobileData = mRunOnMobileData =
@ -194,10 +193,6 @@ public class SettingsActivity extends SyncthingActivity {
}); });
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
categoryBehaviour.removePreference(findPreference(Constants.PREF_NOTIFICATION_TYPE));
}
mDeviceName = (EditTextPreference) findPreference("deviceName"); mDeviceName = (EditTextPreference) findPreference("deviceName");
mListenAddresses = (EditTextPreference) findPreference("listenAddresses"); mListenAddresses = (EditTextPreference) findPreference("listenAddresses");
mMaxRecvKbps = (EditTextPreference) findPreference("maxRecvKbps"); mMaxRecvKbps = (EditTextPreference) findPreference("maxRecvKbps");
@ -348,7 +343,6 @@ public class SettingsActivity extends SyncthingActivity {
@Override @Override
public void onDestroy() { public void onDestroy() {
mPreferences.unregisterOnSharedPreferenceChangeListener(this);
if (mSyncthingService != null) { if (mSyncthingService != null) {
mSyncthingService.unregisterOnServiceStateChangeListener(this); mSyncthingService.unregisterOnServiceStateChangeListener(this);
} }
@ -457,15 +451,16 @@ public class SettingsActivity extends SyncthingActivity {
@Override @Override
public void onStop() { public void onStop() {
if (mPendingConfig) { if (mSyncthingService != null) {
if (mSyncthingService != null && mApi != null && mNotificationHandler.updatePersistentNotification(mSyncthingService);
mSyncthingService.getCurrentState() != SyncthingService.State.DISABLED) { if (mPendingConfig) {
mApi.saveConfigAndRestart(); if (mApi != null &&
mPendingConfig = false; mSyncthingService.getCurrentState() != SyncthingService.State.DISABLED) {
mApi.saveConfigAndRestart();
mPendingConfig = false;
}
} }
} if (mPendingRunConditions) {
if (mPendingRunConditions) {
if (mSyncthingService != null) {
mSyncthingService.evaluateRunConditions(); mSyncthingService.evaluateRunConditions();
} }
} }
@ -631,21 +626,6 @@ public class SettingsActivity extends SyncthingActivity {
} }
} }
/**
* Update notification after that preference changes. We can't use onPreferenceChange() as
* the preference value isn't persisted there, and the NotificationHandler accesses the
* preference directly.
*
* This function is called when the activity is opened, so we need to make sure the service
* is connected.
*/
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(Constants.PREF_NOTIFICATION_TYPE) && mSyncthingService != null) {
mNotificationHandler.updatePersistentNotification(mSyncthingService);
}
}
/** /**
* Enables or disables {@link #mUseRoot} preference depending whether root is available. * Enables or disables {@link #mUseRoot} preference depending whether root is available.
*/ */

View file

@ -148,7 +148,12 @@ public class WebGuiActivity extends SyncthingActivity
// SyncthingService needs to be started from this activity as the user // SyncthingService needs to be started from this activity as the user
// can directly launch this activity from the recent activity switcher. // can directly launch this activity from the recent activity switcher.
startService(new Intent(this, SyncthingService.class)); Intent serviceIntent = new Intent(this, SyncthingService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}
} }
@Override @Override

View file

@ -174,7 +174,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
mActivity.closeDrawer(); mActivity.closeDrawer();
break; break;
case R.id.drawerActionExit: case R.id.drawerActionExit:
if (sharedPreferences != null && sharedPreferences.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false)) { if (sharedPreferences != null && sharedPreferences.getBoolean(Constants.PREF_START_SERVICE_ON_BOOT, false)) {
/** /**
* App is running as a service. Show an explanation why exiting syncthing is an * App is running as a service. Show an explanation why exiting syncthing is an
* extraordinary request, then ask the user to confirm. * extraordinary request, then ask the user to confirm.

View file

@ -25,7 +25,7 @@ public class AppConfigReceiver extends BroadcastReceiver {
/** /**
* Stop the Syncthing-Service * Stop the Syncthing-Service
* If alwaysRunInBackground is enabled the service must not be stopped. Instead a * If startServiceOnBoot is enabled the service must not be stopped. Instead a
* notification is presented to the user. * notification is presented to the user.
*/ */
private static final String ACTION_STOP = "com.nutomic.syncthingandroid.action.STOP"; private static final String ACTION_STOP = "com.nutomic.syncthingandroid.action.STOP";
@ -40,7 +40,7 @@ public class AppConfigReceiver extends BroadcastReceiver {
BootReceiver.startServiceCompat(context); BootReceiver.startServiceCompat(context);
break; break;
case ACTION_STOP: case ACTION_STOP:
if (alwaysRunInBackground(context)) { if (startServiceOnBoot(context)) {
mNotificationHandler.showStopSyncthingWarningNotification(); mNotificationHandler.showStopSyncthingWarningNotification();
} else { } else {
context.stopService(new Intent(context, SyncthingService.class)); context.stopService(new Intent(context, SyncthingService.class));
@ -49,8 +49,8 @@ public class AppConfigReceiver extends BroadcastReceiver {
} }
} }
private static boolean alwaysRunInBackground(Context context) { private static boolean startServiceOnBoot(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return sp.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false); return sp.getBoolean(Constants.PREF_START_SERVICE_ON_BOOT, false);
} }
} }

View file

@ -18,14 +18,14 @@ public class BootReceiver extends BroadcastReceiver {
!intent.getAction().equals(Intent.ACTION_MY_PACKAGE_REPLACED)) !intent.getAction().equals(Intent.ACTION_MY_PACKAGE_REPLACED))
return; return;
if (!alwaysRunInBackground(context)) if (!startServiceOnBoot(context))
return; return;
startServiceCompat(context); startServiceCompat(context);
} }
/** /**
* Workaround for starting service from background on Android 8. * Workaround for starting service from background on Android 8+.
* *
* https://stackoverflow.com/a/44505719/1837158 * https://stackoverflow.com/a/44505719/1837158
*/ */
@ -39,8 +39,8 @@ public class BootReceiver extends BroadcastReceiver {
} }
} }
private static boolean alwaysRunInBackground(Context context) { private static boolean startServiceOnBoot(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return sp.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false); return sp.getBoolean(Constants.PREF_START_SERVICE_ON_BOOT, false);
} }
} }

View file

@ -11,7 +11,7 @@ public class Constants {
public static final String FILENAME_SYNCTHING_BINARY = "libsyncthing.so"; public static final String FILENAME_SYNCTHING_BINARY = "libsyncthing.so";
// Preferences - Run conditions // Preferences - Run conditions
public static final String PREF_ALWAYS_RUN_IN_BACKGROUND = "always_run_in_background"; public static final String PREF_START_SERVICE_ON_BOOT = "always_run_in_background";
public static final String PREF_RUN_ON_MOBILE_DATA = "run_on_mobile_data"; public static final String PREF_RUN_ON_MOBILE_DATA = "run_on_mobile_data";
public static final String PREF_RUN_ON_WIFI = "run_on_wifi"; public static final String PREF_RUN_ON_WIFI = "run_on_wifi";
public static final String PREF_RUN_ON_METERED_WIFI = "run_on_metered_wifi"; public static final String PREF_RUN_ON_METERED_WIFI = "run_on_metered_wifi";
@ -24,7 +24,6 @@ public class Constants {
// Preferences - Behaviour // Preferences - Behaviour
public static final String PREF_START_INTO_WEB_GUI = "start_into_web_gui"; public static final String PREF_START_INTO_WEB_GUI = "start_into_web_gui";
public static final String PREF_USE_ROOT = "use_root"; public static final String PREF_USE_ROOT = "use_root";
public static final String PREF_NOTIFICATION_TYPE = "notification_type";
public static final String PREF_ENVIRONMENT_VARIABLES = "environment_variables"; public static final String PREF_ENVIRONMENT_VARIABLES = "environment_variables";
public static final String PREF_DEBUG_FACILITIES_ENABLED = "debug_facilities_enabled"; public static final String PREF_DEBUG_FACILITIES_ENABLED = "debug_facilities_enabled";
public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running"; public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running";

View file

@ -8,7 +8,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.preference.PreferenceManager;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.Log; import android.util.Log;
@ -43,6 +42,9 @@ public class NotificationHandler {
private final NotificationChannel mPersistentChannelWaiting; private final NotificationChannel mPersistentChannelWaiting;
private final NotificationChannel mInfoChannel; private final NotificationChannel mInfoChannel;
private Boolean lastStartForegroundService = false;
private Boolean appShutdownInProgress = false;
public NotificationHandler(Context context) { public NotificationHandler(Context context) {
((SyncthingApp) context.getApplicationContext()).component().inject(this); ((SyncthingApp) context.getApplicationContext()).component().inject(this);
mContext = context; mContext = context;
@ -88,84 +90,100 @@ public class NotificationHandler {
} }
/** /**
* Shows or hides the persistent notification based on running state and * Shows, updates or hides the notification.
* {@link Constants#PREF_NOTIFICATION_TYPE}.
*/ */
public void updatePersistentNotification(SyncthingService service) { public void updatePersistentNotification(SyncthingService service) {
String type = mPreferences.getString(Constants.PREF_NOTIFICATION_TYPE, "low_priority"); boolean startServiceOnBoot = mPreferences.getBoolean(Constants.PREF_START_SERVICE_ON_BOOT, false);
// Always use startForeground() if app is set to always run. This makes sure the app
// is not killed, and we don't miss wifi/charging events.
// On Android 8, this behaviour is mandatory to receive broadcasts.
// https://stackoverflow.com/a/44505719/1837158
boolean foreground = mPreferences.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false);
// Foreground priority requires a notification so this ensures that we either have a
// "default" or "low_priority" notification, but not "none".
if ("none".equals(type) && foreground) {
type = "low_priority";
}
State currentServiceState = service.getCurrentState(); State currentServiceState = service.getCurrentState();
boolean syncthingRunning = currentServiceState == SyncthingService.State.ACTIVE || boolean syncthingRunning = currentServiceState == SyncthingService.State.ACTIVE ||
currentServiceState == SyncthingService.State.STARTING; currentServiceState == SyncthingService.State.STARTING;
if (foreground || (syncthingRunning && !type.equals("none"))) { boolean startForegroundService = false;
int title = R.string.syncthing_terminated; if (!appShutdownInProgress) {
switch (currentServiceState) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
case ERROR: /**
case INIT: * Android 7 and lower:
break; * The app may run in background and monitor run conditions even if it is not
case DISABLED: * running as a foreground service. For that reason, we can use a normal
title = R.string.syncthing_disabled; * notification if syncthing is DISABLED.
break; */
case STARTING: startForegroundService = startServiceOnBoot || syncthingRunning;
case ACTIVE: } else {
title = R.string.syncthing_active; /**
break; * Android 8+:
default: * Always use startForeground.
break; * This makes sure the app is not killed, and we don't miss run condition events.
* On Android 8+, this behaviour is mandatory to receive broadcasts.
* https://stackoverflow.com/a/44505719/1837158
* Foreground priority requires a notification so this ensures that we either have a
* "default" or "low_priority" notification, but not "none".
*/
startForegroundService = true;
} }
}
/** // Check if we have to stopForeground.
* We no longer need to launch FirstStartActivity instead of MainActivity as if (startForegroundService != lastStartForegroundService) {
* {@link SyncthingService#onStartCommand} will check for denied permissions. if (!startForegroundService) {
*/ Log.v(TAG, "Stopping foreground service");
Intent intent = new Intent(mContext, MainActivity.class); service.stopForeground(false);
}
}
// Reason for two separate IDs: if one of the notification channels is hidden then // Prepare notification builder.
// the startForeground() below won't update the notification but use the old one int title = R.string.syncthing_terminated;
int idToShow = syncthingRunning ? ID_PERSISTENT : ID_PERSISTENT_WAITING; switch (currentServiceState) {
int idToCancel = syncthingRunning ? ID_PERSISTENT_WAITING : ID_PERSISTENT; case ERROR:
NotificationChannel channel = syncthingRunning ? mPersistentChannel : mPersistentChannelWaiting; case INIT:
NotificationCompat.Builder builder = getNotificationBuilder(channel) break;
.setContentTitle(mContext.getString(title)) case DISABLED:
.setSmallIcon(R.drawable.ic_stat_notify) title = R.string.syncthing_disabled;
.setOngoing(true) break;
.setOnlyAlertOnce(true) case STARTING:
.setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0)); title = R.string.syncthing_starting;
if (type.equals("low_priority")) break;
builder.setPriority(NotificationCompat.PRIORITY_MIN); case ACTIVE:
title = R.string.syncthing_active;
break;
default:
break;
}
if (foreground) { /**
* Reason for two separate IDs: if one of the notification channels is hidden then
* the startForeground() below won't update the notification but use the old one.
*/
int idToShow = syncthingRunning ? ID_PERSISTENT : ID_PERSISTENT_WAITING;
int idToCancel = syncthingRunning ? ID_PERSISTENT_WAITING : ID_PERSISTENT;
Intent intent = new Intent(mContext, MainActivity.class);
NotificationChannel channel = syncthingRunning ? mPersistentChannel : mPersistentChannelWaiting;
NotificationCompat.Builder builder = getNotificationBuilder(channel)
.setContentTitle(mContext.getString(title))
.setSmallIcon(R.drawable.ic_stat_notify)
.setOngoing(true)
.setOnlyAlertOnce(true)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setContentIntent(PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
if (!appShutdownInProgress) {
if (startForegroundService) {
Log.v(TAG, "Starting foreground service or updating notification");
service.startForeground(idToShow, builder.build()); service.startForeground(idToShow, builder.build());
} else { } else {
service.stopForeground(false); // ensure no longer running with foreground priority Log.v(TAG, "Updating notification");
mNotificationManager.notify(idToShow, builder.build()); mNotificationManager.notify(idToShow, builder.build());
} }
mNotificationManager.cancel(idToCancel);
} else {
// ensure no longer running with foreground priority
cancelPersistentNotification(service);
} }
mNotificationManager.cancel(idToCancel);
// Remember last notification visibility.
lastStartForegroundService = startForegroundService;
} }
public void cancelPersistentNotification(SyncthingService service) { /**
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && alwaysRunInBackground()) * Called by {@link SyncthingService#onStart} {@link SyncthingService#onDestroy}
return; * to indicate app startup and shutdown.
*/
service.stopForeground(false); public void setAppShutdownInProgress(Boolean newValue) {
mNotificationManager.cancel(ID_PERSISTENT); appShutdownInProgress = newValue;
mNotificationManager.cancel(ID_PERSISTENT_WAITING);
} }
public void showCrashedNotification(@StringRes int title, String extraInfo) { public void showCrashedNotification(@StringRes int title, String extraInfo) {
@ -278,9 +296,4 @@ public class NotificationHandler {
} }
mNotificationManager.notify(ID_STOP_BACKGROUND_WARNING, nb.build()); mNotificationManager.notify(ID_STOP_BACKGROUND_WARNING, nb.build());
} }
private boolean alwaysRunInBackground() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
return sp.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false);
}
} }

View file

@ -219,6 +219,10 @@ public class SyncthingService extends Service {
mStoragePermissionGranted = (ContextCompat.checkSelfPermission(this, mStoragePermissionGranted = (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_GRANTED); PackageManager.PERMISSION_GRANTED);
if (mNotificationHandler != null) {
mNotificationHandler.setAppShutdownInProgress(false);
}
} }
/** /**
@ -505,6 +509,9 @@ public class SyncthingService extends Service {
*/ */
mRunConditionMonitor.shutdown(); mRunConditionMonitor.shutdown();
} }
if (mNotificationHandler != null) {
mNotificationHandler.setAppShutdownInProgress(true);
}
if (mStoragePermissionGranted) { if (mStoragePermissionGranted) {
synchronized (mStateLock) { synchronized (mStateLock) {
if (mCurrentState == State.STARTING) { if (mCurrentState == State.STARTING) {
@ -559,10 +566,6 @@ public class SyncthingService extends Service {
mApi = null; mApi = null;
} }
if (mNotificationHandler != null) {
mNotificationHandler.cancelPersistentNotification(this);
}
if (mSyncthingRunnable != null) { if (mSyncthingRunnable != null) {
mSyncthingRunnable.killSyncthing(); mSyncthingRunnable.killSyncthing();
if (mSyncthingRunnableThread != null) { if (mSyncthingRunnableThread != null) {
@ -621,7 +624,7 @@ public class SyncthingService extends Service {
} }
/** /**
* Called to notifiy listeners of an API change. * Called to notify listeners of an API change.
*/ */
private void onServiceStateChange(State newState) { private void onServiceStateChange(State newState) {
Log.v(TAG, "onServiceStateChange: from " + mCurrentState + " to " + newState); Log.v(TAG, "onServiceStateChange: from " + mCurrentState + " to " + newState);
@ -766,6 +769,7 @@ public class SyncthingService extends Service {
switch (prefKey) { switch (prefKey) {
// Preferences that are no longer used and left-overs from previous versions of the app. // Preferences that are no longer used and left-overs from previous versions of the app.
case "first_start": case "first_start":
case "notification_type":
case "notify_crashes": case "notify_crashes":
Log.v(TAG, "importConfig: Ignoring deprecated pref \"" + prefKey + "\"."); Log.v(TAG, "importConfig: Ignoring deprecated pref \"" + prefKey + "\".");
break; break;

View file

@ -15,10 +15,4 @@
<item>battery_power</item> <item>battery_power</item>
</string-array> </string-array>
<string-array name="notification_type_entry_values">
<item>normal</item>
<item>low_priority</item>
<item>none</item>
</string-array>
</resources> </resources>

View file

@ -79,14 +79,6 @@
android:summary="@string/advanced_folder_picker_summary" android:summary="@string/advanced_folder_picker_summary"
android:defaultValue="false" /> android:defaultValue="false" />
<ListPreference
android:key="notification_type"
android:title="@string/notification_type_title"
android:entryValues="@array/notification_type_entry_values"
android:entries="@array/notification_type_entries"
android:summary="@string/notification_type_summary"
android:defaultValue="low_priority" />
<ListPreference <ListPreference
android:key="pref_current_language" android:key="pref_current_language"
android:title="@string/preference_language_title" android:title="@string/preference_language_title"