mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-12-01 16:51:16 +00:00
* 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:
parent
cd3bca5141
commit
c224bcb04a
14 changed files with 229 additions and 133 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -44,3 +44,6 @@ syncthing/mingit.zip
|
|||
|
||||
# External build artifacts
|
||||
ext/
|
||||
|
||||
# push-to-device after build marker file
|
||||
\#enable_push_to_device
|
||||
|
|
|
@ -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']
|
||||
}
|
||||
|
|
91
app/push-to-device.py
Normal file
91
app/push-to-device.py
Normal 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)
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,10 +15,4 @@
|
|||
<item>battery_power</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="notification_type_entry_values">
|
||||
<item>normal</item>
|
||||
<item>low_priority</item>
|
||||
<item>none</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -79,14 +79,6 @@
|
|||
android:summary="@string/advanced_folder_picker_summary"
|
||||
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
|
||||
android:key="pref_current_language"
|
||||
android:title="@string/preference_language_title"
|
||||
|
|
Loading…
Reference in a new issue