From bbeecc87770a8e56166718569f56593525d5b44b Mon Sep 17 00:00:00 2001 From: Catfriend1 Date: Sat, 25 Aug 2018 17:52:43 +0200 Subject: [PATCH] Add "Uptime" to status tab (#30) --- .../activities/SettingsActivity.java | 8 +-- .../fragments/DrawerFragment.java | 18 +++++-- .../fragments/StatusFragment.java | 51 ++++++++++++++----- .../syncthingandroid/http/GetRequest.java | 18 +++---- .../{SystemInfo.java => SystemStatus.java} | 17 +++++-- .../syncthingandroid/service/RestApi.java | 22 ++++---- app/src/main/res/values/strings.xml | 3 ++ 7 files changed, 91 insertions(+), 46 deletions(-) rename app/src/main/java/com/nutomic/syncthingandroid/model/{SystemInfo.java => SystemStatus.java} (54%) 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 47c7bf9f..61ffc60c 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java @@ -340,8 +340,8 @@ public class SettingsActivity extends SyncthingActivity { mGlobalAnnounceServers.setText(joiner.join(mOptions.globalAnnounceServers)); mAddress.setText(mGui.address); mRestartOnWakeup.setChecked(mOptions.restartOnWakeup); - mApi.getSystemInfo(systemInfo -> - mUrAccepted.setChecked(mOptions.isUsageReportingAccepted(systemInfo.urVersionMax))); + mApi.getSystemStatus(systemStatus -> + mUrAccepted.setChecked(mOptions.isUsageReportingAccepted(systemStatus.urVersionMax))); } @Override @@ -439,9 +439,9 @@ public class SettingsActivity extends SyncthingActivity { mOptions.restartOnWakeup = (boolean) o; break; case "urAccepted": - mApi.getSystemInfo(systemInfo -> { + mApi.getSystemStatus(systemStatus -> { mOptions.urAccepted = ((boolean) o) - ? systemInfo.urVersionMax + ? systemStatus.urVersionMax : Options.USAGE_REPORTING_DENIED; }); break; 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 a6dc68db..26ef40c6 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java @@ -36,7 +36,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi private static final String TAG = "DrawerFragment"; - private TextView mVersion; + private TextView mVersion = null; private TextView mDrawerActionShowQrCode; private TextView mDrawerActionWebGui; private TextView mDrawerActionRestart; @@ -44,7 +44,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi private TextView mExitButton; private MainActivity mActivity; - private SharedPreferences sharedPreferences; + private SharedPreferences sharedPreferences = null; @Override public void onServiceStateChange(SyncthingService.State currentState) { @@ -55,6 +55,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi @Override public void onResume() { super.onResume(); + updateLabels(); updateButtons(); } @@ -83,9 +84,6 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi mDrawerActionSettings = view.findViewById(R.id.drawerActionSettings); mExitButton = view.findViewById(R.id.drawerActionExit); - // Show static content. - mVersion.setText(sharedPreferences.getString(Constants.PREF_LAST_BINARY_VERSION, "")); - // Add listeners to buttons. mDrawerActionShowQrCode.setOnClickListener(this); mDrawerActionWebGui.setOnClickListener(this); @@ -93,6 +91,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi mDrawerActionSettings.setOnClickListener(this); mExitButton.setOnClickListener(this); + updateLabels(); updateButtons(); } @@ -101,6 +100,15 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi super.onActivityCreated(savedInstanceState); } + /** + * Update static info labels. + */ + private void updateLabels() { + if (sharedPreferences != null && mVersion != null) { + mVersion.setText(sharedPreferences.getString(Constants.PREF_LAST_BINARY_VERSION, "")); + } + } + /** * Update action button availability. */ diff --git a/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java b/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java index 3a988951..40727b05 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java @@ -21,13 +21,14 @@ import com.nutomic.syncthingandroid.activities.MainActivity; import com.nutomic.syncthingandroid.activities.SettingsActivity; import com.nutomic.syncthingandroid.activities.SyncthingActivity; import com.nutomic.syncthingandroid.model.Connections; -import com.nutomic.syncthingandroid.model.SystemInfo; +import com.nutomic.syncthingandroid.model.SystemStatus; import com.nutomic.syncthingandroid.model.SystemVersion; import com.nutomic.syncthingandroid.service.Constants; import com.nutomic.syncthingandroid.service.RestApi; import com.nutomic.syncthingandroid.service.SyncthingService; import com.nutomic.syncthingandroid.util.Util; +import java.util.concurrent.TimeUnit; import java.util.ArrayList; import java.util.Locale; import java.util.Map; @@ -67,6 +68,7 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS private String mDownload = ""; private String mUpload = ""; private String mAnnounceServer = ""; + private String mUptime = ""; @Override public void setUserVisibleHint(boolean isVisibleToUser) @@ -173,12 +175,15 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS // Add status holders refreshed by callbacks to the list. if (mServiceState == SyncthingService.State.ACTIVE) { synchronized (mStatusHolderLock) { - if (!TextUtils.isEmpty(mCpuUsage)) { - statusItems.add(getString(R.string.cpu_usage) + ": " + mCpuUsage); + if (!TextUtils.isEmpty(mUptime)) { + statusItems.add(getString(R.string.uptime) + ": " + mUptime); } if (!TextUtils.isEmpty(mRamUsage)) { statusItems.add(getString(R.string.ram_usage) + ": " + mRamUsage); } + if (!TextUtils.isEmpty(mCpuUsage)) { + statusItems.add(getString(R.string.cpu_usage) + ": " + mCpuUsage); + } if (!TextUtils.isEmpty(mDownload)) { statusItems.add(getString(R.string.download_title) + ": " + mDownload); } @@ -218,26 +223,42 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS return; } Log.v(TAG, "Invoking REST status queries"); - restApi.getSystemInfo(this::onReceiveSystemInfo); + restApi.getSystemStatus(this::onReceiveSystemStatus); restApi.getConnections(this::onReceiveConnections); } /** - * Populates status holders with status received via {@link RestApi#getSystemInfo}. + * Populates status holders with status received via {@link RestApi#getSystemStatus}. */ - private void onReceiveSystemInfo(SystemInfo info) { + private void onReceiveSystemStatus(SystemStatus systemStatus) { if (getActivity() == null) { return; } NumberFormat percentFormat = NumberFormat.getPercentInstance(); percentFormat.setMaximumFractionDigits(2); - int announceTotal = info.discoveryMethods; + int announceTotal = systemStatus.discoveryMethods; int announceConnected = - announceTotal - Optional.fromNullable(info.discoveryErrors).transform(Map::size).or(0); + announceTotal - Optional.fromNullable(systemStatus.discoveryErrors).transform(Map::size).or(0); synchronized (mStatusHolderLock) { - mCpuUsage = percentFormat.format(info.cpuPercent / 100); - mRamUsage = Util.readableFileSize(mActivity, info.sys); - mAnnounceServer = String.format(Locale.getDefault(), "%1$d/%2$d", announceConnected, announceTotal); + mCpuUsage = (systemStatus.cpuPercent / 100 < 1) ? "" : percentFormat.format(systemStatus.cpuPercent / 100); + mRamUsage = Util.readableFileSize(mActivity, systemStatus.sys); + mAnnounceServer = (announceTotal == 0) ? + "" : + String.format(Locale.getDefault(), "%1$d/%2$d", announceConnected, announceTotal); + + /** + * Calculate readable uptime. + */ + long uptimeDays = TimeUnit.SECONDS.toDays(systemStatus.uptime); + long uptimeHours = TimeUnit.SECONDS.toHours(systemStatus.uptime) - TimeUnit.DAYS.toHours(uptimeDays); + long uptimeMinutes = TimeUnit.SECONDS.toMinutes(systemStatus.uptime) - TimeUnit.HOURS.toMinutes(uptimeHours) - TimeUnit.DAYS.toMinutes(uptimeDays); + if (uptimeDays > 0) { + mUptime = String.format(Locale.getDefault(), "%dd %02dh %02dm", uptimeDays, uptimeHours, uptimeMinutes); + } else if (uptimeHours > 0) { + mUptime = String.format(Locale.getDefault(), "%dh %02dm", uptimeHours, uptimeMinutes); + } else { + mUptime = String.format(Locale.getDefault(), "%dm", uptimeMinutes); + } } updateStatus(); } @@ -251,8 +272,12 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS } Connections.Connection c = connections.total; synchronized (mStatusHolderLock) { - mDownload = Util.readableTransferRate(mActivity, c.inBits); - mUpload = Util.readableTransferRate(mActivity, c.outBits); + /** + * Hide the rates on the UI if they are lower than 1 KByte/sec. We don't like to + * bother the user looking at discovery or index exchange traffic. + */ + mDownload = (c.inBits / 8 < 1024) ? "" : Util.readableTransferRate(mActivity, c.inBits); + mUpload = (c.outBits / 8 < 1024) ? "" : Util.readableTransferRate(mActivity, c.outBits); } updateStatus(); } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java b/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java index b708c3aa..874189dc 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java @@ -16,15 +16,15 @@ import java.util.Map; */ public class GetRequest extends ApiRequest { - public static final String URI_CONFIG = "/rest/system/config"; - public static final String URI_DEBUG = "/rest/system/debug"; - public static final String URI_VERSION = "/rest/system/version"; - public static final String URI_SYSTEM = "/rest/system/status"; - public static final String URI_CONNECTIONS = "/rest/system/connections"; - public static final String URI_STATUS = "/rest/db/status"; - public static final String URI_DEVICEID = "/rest/svc/deviceid"; - public static final String URI_REPORT = "/rest/svc/report"; - public static final String URI_EVENTS = "/rest/events"; + public static final String URI_CONFIG = "/rest/system/config"; + public static final String URI_DEBUG = "/rest/system/debug"; + public static final String URI_VERSION = "/rest/system/version"; + public static final String URI_SYSTEM_STATUS = "/rest/system/status"; + public static final String URI_CONNECTIONS = "/rest/system/connections"; + public static final String URI_DB_STATUS = "/rest/db/status"; + public static final String URI_DEVICEID = "/rest/svc/deviceid"; + public static final String URI_REPORT = "/rest/svc/report"; + public static final String URI_EVENTS = "/rest/events"; public GetRequest(Context context, URL url, String path, String apiKey, @Nullable Map params, OnSuccessListener listener) { diff --git a/app/src/main/java/com/nutomic/syncthingandroid/model/SystemInfo.java b/app/src/main/java/com/nutomic/syncthingandroid/model/SystemStatus.java similarity index 54% rename from app/src/main/java/com/nutomic/syncthingandroid/model/SystemInfo.java rename to app/src/main/java/com/nutomic/syncthingandroid/model/SystemStatus.java index 9bb085d8..f0c83bbe 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/model/SystemInfo.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/model/SystemStatus.java @@ -1,15 +1,24 @@ package com.nutomic.syncthingandroid.model; +import java.util.List; import java.util.Map; -public class SystemInfo { +/** + * REST API endpoint "/rest/system/status" + */ +public class SystemStatus { public long alloc; public double cpuPercent; + public Map>> connectionServiceStatus; + public boolean discoveryEnabled; + public Map discoveryErrors; + public int discoveryMethods; public int goroutines; public String myID; + public String pathSeparator; + public String startTime; public long sys; - public boolean discoveryEnabled; - public int discoveryMethods; - public Map discoveryErrors; + public String tilde; + public long uptime; public int urVersionMax; } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java index 58a1bda5..4c5b4ba5 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java @@ -31,7 +31,7 @@ import com.nutomic.syncthingandroid.model.Event; import com.nutomic.syncthingandroid.model.Folder; import com.nutomic.syncthingandroid.model.FolderStatus; import com.nutomic.syncthingandroid.model.Options; -import com.nutomic.syncthingandroid.model.SystemInfo; +import com.nutomic.syncthingandroid.model.SystemStatus; import com.nutomic.syncthingandroid.model.SystemVersion; import com.nutomic.syncthingandroid.service.Constants; @@ -112,11 +112,11 @@ public class RestApi { */ private Boolean asyncQueryConfigComplete = false; private Boolean asyncQueryVersionComplete = false; - private Boolean asyncQuerySystemInfoComplete = false; + private Boolean asyncQuerySystemStatusComplete = false; /** * Object that must be locked upon accessing the following variables: - * asyncQueryConfigComplete, asyncQueryVersionComplete, asyncQuerySystemInfoComplete + * asyncQueryConfigComplete, asyncQueryVersionComplete, asyncQuerySystemStatusComplete */ private final Object mAsyncQueryCompleteLock = new Object(); @@ -163,7 +163,7 @@ public class RestApi { synchronized (mAsyncQueryCompleteLock) { asyncQueryVersionComplete = false; asyncQueryConfigComplete = false; - asyncQuerySystemInfoComplete = false; + asyncQuerySystemStatusComplete = false; } new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mApiKey, null, result -> { JsonObject json = new JsonParser().parse(result).getAsJsonObject(); @@ -182,18 +182,18 @@ public class RestApi { checkReadConfigFromRestApiCompleted(); } }); - getSystemInfo(info -> { + getSystemStatus(info -> { mLocalDeviceId = info.myID; mUrVersionMax = info.urVersionMax; synchronized (mAsyncQueryCompleteLock) { - asyncQuerySystemInfoComplete = true; + asyncQuerySystemStatusComplete = true; checkReadConfigFromRestApiCompleted(); } }); } private void checkReadConfigFromRestApiCompleted() { - if (asyncQueryVersionComplete && asyncQueryConfigComplete && asyncQuerySystemInfoComplete) { + if (asyncQueryVersionComplete && asyncQueryConfigComplete && asyncQuerySystemStatusComplete) { Log.v(TAG, "Reading config from REST completed."); mOnApiAvailableListener.onApiAvailable(); } @@ -502,9 +502,9 @@ public class RestApi { /** * Requests and parses information about current system status and resource usage. */ - public void getSystemInfo(OnResultListener1 listener) { - new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM, mApiKey, null, result -> - listener.onResult(new Gson().fromJson(result, SystemInfo.class))); + public void getSystemStatus(OnResultListener1 listener) { + new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM_STATUS, mApiKey, null, result -> + listener.onResult(new Gson().fromJson(result, SystemStatus.class))); } public boolean isConfigLoaded() { @@ -558,7 +558,7 @@ public class RestApi { * Returns status information about the folder with the given id. */ public void getFolderStatus(final String folderId, final OnResultListener2 listener) { - new GetRequest(mContext, mUrl, GetRequest.URI_STATUS, mApiKey, + new GetRequest(mContext, mUrl, GetRequest.URI_DB_STATUS, mApiKey, ImmutableMap.of("folder", folderId), result -> { FolderStatus m = new Gson().fromJson(result, FolderStatus.class); mCachedFolderStatuses.put(folderId, m); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 35a92b0b..c5144123 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -158,6 +158,9 @@ Please report any problems you encounter via Github. Configured Announce Server + + Uptime + Restart Do you want to restart Syncthing?