From c224bcb04a1045d0b8110622ba2386ecbeee30e5 Mon Sep 17 00:00:00 2001 From: Catfriend1 Date: Mon, 8 Oct 2018 05:00:59 +0200 Subject: [PATCH] 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 --- .gitignore | 3 + app/build.gradle | 10 ++ app/push-to-device.py | 91 +++++++++++ .../activities/MainActivity.java | 7 +- .../activities/SettingsActivity.java | 46 ++---- .../activities/WebGuiActivity.java | 7 +- .../fragments/DrawerFragment.java | 2 +- .../receiver/AppConfigReceiver.java | 8 +- .../receiver/BootReceiver.java | 8 +- .../syncthingandroid/service/Constants.java | 3 +- .../service/NotificationHandler.java | 149 ++++++++++-------- .../service/SyncthingService.java | 14 +- app/src/main/res/values/arrays.xml | 6 - app/src/main/res/xml/app_settings.xml | 8 - 14 files changed, 229 insertions(+), 133 deletions(-) create mode 100644 app/push-to-device.py diff --git a/.gitignore b/.gitignore index 4921d3a2..1d419d55 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ syncthing/mingit.zip # External build artifacts ext/ + +# push-to-device after build marker file +\#enable_push_to_device diff --git a/app/build.gradle b/app/build.gradle index d7cb84ff..2f697eb2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -58,6 +58,11 @@ android { signingConfig = signingConfigs.release.storeFile ? signingConfigs.release : null } 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/en/' } + +task pushToDevice(type: Exec) { + executable = 'python' + args = ['-u', './push-to-device.py'] +} diff --git a/app/push-to-device.py b/app/push-to-device.py new file mode 100644 index 00000000..b0b4aaf3 --- /dev/null +++ b/app/push-to-device.py @@ -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) diff --git a/app/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java b/app/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java index bbf6fca6..d1c724b6 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java @@ -196,7 +196,12 @@ public class MainActivity extends SyncthingActivity // SyncthingService needs to be started from this activity as the user // 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()); } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java b/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java index 704a1831..44b69934 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java @@ -87,7 +87,7 @@ public class SettingsActivity extends SyncthingActivity { public static class SettingsFragment extends PreferenceFragment implements SyncthingActivity.OnServiceConnectedListener, SyncthingService.OnServiceStateChangeListener, Preference.OnPreferenceChangeListener, - Preference.OnPreferenceClickListener, SharedPreferences.OnSharedPreferenceChangeListener { + Preference.OnPreferenceClickListener { private static final String TAG = "SettingsFragment"; private static final String KEY_EXPORT_CONFIG = "export_config"; @@ -100,7 +100,7 @@ public class SettingsActivity extends SyncthingActivity { @Inject SharedPreferences mPreferences; private Preference mCategoryRunConditions; - private CheckBoxPreference mAlwaysRunInBackground; + private CheckBoxPreference mStartServiceOnBoot; private ListPreference mPowerSource; private CheckBoxPreference mRunOnMobileData; private CheckBoxPreference mRunOnWifi; @@ -150,7 +150,6 @@ public class SettingsActivity extends SyncthingActivity { super.onCreate(savedInstanceState); ((SyncthingApp) getActivity().getApplication()).component().inject(this); ((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this); - mPreferences.registerOnSharedPreferenceChangeListener(this); } /** @@ -164,8 +163,8 @@ public class SettingsActivity extends SyncthingActivity { addPreferencesFromResource(R.xml.app_settings); PreferenceScreen screen = getPreferenceScreen(); - mAlwaysRunInBackground = - (CheckBoxPreference) findPreference(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND); + mStartServiceOnBoot = + (CheckBoxPreference) findPreference(Constants.PREF_START_SERVICE_ON_BOOT); mPowerSource = (ListPreference) findPreference(Constants.PREF_POWER_SOURCE); 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"); mListenAddresses = (EditTextPreference) findPreference("listenAddresses"); mMaxRecvKbps = (EditTextPreference) findPreference("maxRecvKbps"); @@ -348,7 +343,6 @@ public class SettingsActivity extends SyncthingActivity { @Override public void onDestroy() { - mPreferences.unregisterOnSharedPreferenceChangeListener(this); if (mSyncthingService != null) { mSyncthingService.unregisterOnServiceStateChangeListener(this); } @@ -457,15 +451,16 @@ public class SettingsActivity extends SyncthingActivity { @Override public void onStop() { - if (mPendingConfig) { - if (mSyncthingService != null && mApi != null && - mSyncthingService.getCurrentState() != SyncthingService.State.DISABLED) { - mApi.saveConfigAndRestart(); - mPendingConfig = false; + if (mSyncthingService != null) { + mNotificationHandler.updatePersistentNotification(mSyncthingService); + if (mPendingConfig) { + if (mApi != null && + mSyncthingService.getCurrentState() != SyncthingService.State.DISABLED) { + mApi.saveConfigAndRestart(); + mPendingConfig = false; + } } - } - if (mPendingRunConditions) { - if (mSyncthingService != null) { + if (mPendingRunConditions) { 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. */ diff --git a/app/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java b/app/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java index c719d2c3..891946a8 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java @@ -148,7 +148,12 @@ public class WebGuiActivity extends SyncthingActivity // SyncthingService needs to be started from this activity as the user // 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 diff --git a/app/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java b/app/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java index 66872b59..18e34393 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java @@ -174,7 +174,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi mActivity.closeDrawer(); break; 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 * extraordinary request, then ask the user to confirm. diff --git a/app/src/main/java/com/nutomic/syncthingandroid/receiver/AppConfigReceiver.java b/app/src/main/java/com/nutomic/syncthingandroid/receiver/AppConfigReceiver.java index ccfcd26a..3e2265e5 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/receiver/AppConfigReceiver.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/receiver/AppConfigReceiver.java @@ -25,7 +25,7 @@ public class AppConfigReceiver extends BroadcastReceiver { /** * 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. */ private static final String ACTION_STOP = "com.nutomic.syncthingandroid.action.STOP"; @@ -40,7 +40,7 @@ public class AppConfigReceiver extends BroadcastReceiver { BootReceiver.startServiceCompat(context); break; case ACTION_STOP: - if (alwaysRunInBackground(context)) { + if (startServiceOnBoot(context)) { mNotificationHandler.showStopSyncthingWarningNotification(); } else { 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); - return sp.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false); + return sp.getBoolean(Constants.PREF_START_SERVICE_ON_BOOT, false); } } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/receiver/BootReceiver.java b/app/src/main/java/com/nutomic/syncthingandroid/receiver/BootReceiver.java index 67b835a8..1b0d7e50 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/receiver/BootReceiver.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/receiver/BootReceiver.java @@ -18,14 +18,14 @@ public class BootReceiver extends BroadcastReceiver { !intent.getAction().equals(Intent.ACTION_MY_PACKAGE_REPLACED)) return; - if (!alwaysRunInBackground(context)) + if (!startServiceOnBoot(context)) return; 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 */ @@ -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); - return sp.getBoolean(Constants.PREF_ALWAYS_RUN_IN_BACKGROUND, false); + return sp.getBoolean(Constants.PREF_START_SERVICE_ON_BOOT, false); } } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java index 7a267151..b4d8c879 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java @@ -11,7 +11,7 @@ public class Constants { public static final String FILENAME_SYNCTHING_BINARY = "libsyncthing.so"; // 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_WIFI = "run_on_wifi"; public static final String PREF_RUN_ON_METERED_WIFI = "run_on_metered_wifi"; @@ -24,7 +24,6 @@ public class Constants { // Preferences - Behaviour 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_NOTIFICATION_TYPE = "notification_type"; 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_USE_WAKE_LOCK = "wakelock_while_binary_running"; diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/NotificationHandler.java b/app/src/main/java/com/nutomic/syncthingandroid/service/NotificationHandler.java index f939b6cf..32db4f77 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/NotificationHandler.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/NotificationHandler.java @@ -8,7 +8,6 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; -import android.preference.PreferenceManager; import android.support.annotation.StringRes; import android.support.v4.app.NotificationCompat; import android.util.Log; @@ -43,6 +42,9 @@ public class NotificationHandler { private final NotificationChannel mPersistentChannelWaiting; private final NotificationChannel mInfoChannel; + private Boolean lastStartForegroundService = false; + private Boolean appShutdownInProgress = false; + public NotificationHandler(Context context) { ((SyncthingApp) context.getApplicationContext()).component().inject(this); mContext = context; @@ -88,84 +90,100 @@ public class NotificationHandler { } /** - * Shows or hides the persistent notification based on running state and - * {@link Constants#PREF_NOTIFICATION_TYPE}. + * Shows, updates or hides the notification. */ public void updatePersistentNotification(SyncthingService service) { - String type = mPreferences.getString(Constants.PREF_NOTIFICATION_TYPE, "low_priority"); - - // 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"; - } - + boolean startServiceOnBoot = mPreferences.getBoolean(Constants.PREF_START_SERVICE_ON_BOOT, false); State currentServiceState = service.getCurrentState(); boolean syncthingRunning = currentServiceState == SyncthingService.State.ACTIVE || currentServiceState == SyncthingService.State.STARTING; - if (foreground || (syncthingRunning && !type.equals("none"))) { - int title = R.string.syncthing_terminated; - switch (currentServiceState) { - case ERROR: - case INIT: - break; - case DISABLED: - title = R.string.syncthing_disabled; - break; - case STARTING: - case ACTIVE: - title = R.string.syncthing_active; - break; - default: - break; + boolean startForegroundService = false; + if (!appShutdownInProgress) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + /** + * Android 7 and lower: + * The app may run in background and monitor run conditions even if it is not + * running as a foreground service. For that reason, we can use a normal + * notification if syncthing is DISABLED. + */ + startForegroundService = startServiceOnBoot || syncthingRunning; + } else { + /** + * Android 8+: + * Always use startForeground. + * 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; } + } - /** - * We no longer need to launch FirstStartActivity instead of MainActivity as - * {@link SyncthingService#onStartCommand} will check for denied permissions. - */ - Intent intent = new Intent(mContext, MainActivity.class); + // Check if we have to stopForeground. + if (startForegroundService != lastStartForegroundService) { + if (!startForegroundService) { + Log.v(TAG, "Stopping foreground service"); + service.stopForeground(false); + } + } - // 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; - NotificationChannel channel = syncthingRunning ? mPersistentChannel : mPersistentChannelWaiting; - NotificationCompat.Builder builder = getNotificationBuilder(channel) - .setContentTitle(mContext.getString(title)) - .setSmallIcon(R.drawable.ic_stat_notify) - .setOngoing(true) - .setOnlyAlertOnce(true) - .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0)); - if (type.equals("low_priority")) - builder.setPriority(NotificationCompat.PRIORITY_MIN); + // Prepare notification builder. + int title = R.string.syncthing_terminated; + switch (currentServiceState) { + case ERROR: + case INIT: + break; + case DISABLED: + title = R.string.syncthing_disabled; + break; + case STARTING: + title = R.string.syncthing_starting; + break; + 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()); } else { - service.stopForeground(false); // ensure no longer running with foreground priority + Log.v(TAG, "Updating notification"); 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()) - return; - - service.stopForeground(false); - mNotificationManager.cancel(ID_PERSISTENT); - mNotificationManager.cancel(ID_PERSISTENT_WAITING); + /** + * Called by {@link SyncthingService#onStart} {@link SyncthingService#onDestroy} + * to indicate app startup and shutdown. + */ + public void setAppShutdownInProgress(Boolean newValue) { + appShutdownInProgress = newValue; } public void showCrashedNotification(@StringRes int title, String extraInfo) { @@ -278,9 +296,4 @@ public class NotificationHandler { } 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); - } } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java b/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java index e82840c9..2d55e9cb 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java @@ -219,6 +219,10 @@ public class SyncthingService extends Service { mStoragePermissionGranted = (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); + + if (mNotificationHandler != null) { + mNotificationHandler.setAppShutdownInProgress(false); + } } /** @@ -505,6 +509,9 @@ public class SyncthingService extends Service { */ mRunConditionMonitor.shutdown(); } + if (mNotificationHandler != null) { + mNotificationHandler.setAppShutdownInProgress(true); + } if (mStoragePermissionGranted) { synchronized (mStateLock) { if (mCurrentState == State.STARTING) { @@ -559,10 +566,6 @@ public class SyncthingService extends Service { mApi = null; } - if (mNotificationHandler != null) { - mNotificationHandler.cancelPersistentNotification(this); - } - if (mSyncthingRunnable != null) { mSyncthingRunnable.killSyncthing(); 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) { Log.v(TAG, "onServiceStateChange: from " + mCurrentState + " to " + newState); @@ -766,6 +769,7 @@ public class SyncthingService extends Service { switch (prefKey) { // Preferences that are no longer used and left-overs from previous versions of the app. case "first_start": + case "notification_type": case "notify_crashes": Log.v(TAG, "importConfig: Ignoring deprecated pref \"" + prefKey + "\"."); break; diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index feb79c9a..a61c2a44 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -15,10 +15,4 @@ battery_power - - normal - low_priority - none - - diff --git a/app/src/main/res/xml/app_settings.xml b/app/src/main/res/xml/app_settings.xml index e7444f03..29ae1758 100644 --- a/app/src/main/res/xml/app_settings.xml +++ b/app/src/main/res/xml/app_settings.xml @@ -79,14 +79,6 @@ android:summary="@string/advanced_folder_picker_summary" android:defaultValue="false" /> - -