1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2025-02-03 15:51:37 +00:00

Add "Uptime" to status tab (#30)

This commit is contained in:
Catfriend1 2018-08-25 17:52:43 +02:00 committed by GitHub
parent b666ada7d2
commit bbeecc8777
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 46 deletions

View file

@ -340,8 +340,8 @@ public class SettingsActivity extends SyncthingActivity {
mGlobalAnnounceServers.setText(joiner.join(mOptions.globalAnnounceServers)); mGlobalAnnounceServers.setText(joiner.join(mOptions.globalAnnounceServers));
mAddress.setText(mGui.address); mAddress.setText(mGui.address);
mRestartOnWakeup.setChecked(mOptions.restartOnWakeup); mRestartOnWakeup.setChecked(mOptions.restartOnWakeup);
mApi.getSystemInfo(systemInfo -> mApi.getSystemStatus(systemStatus ->
mUrAccepted.setChecked(mOptions.isUsageReportingAccepted(systemInfo.urVersionMax))); mUrAccepted.setChecked(mOptions.isUsageReportingAccepted(systemStatus.urVersionMax)));
} }
@Override @Override
@ -439,9 +439,9 @@ public class SettingsActivity extends SyncthingActivity {
mOptions.restartOnWakeup = (boolean) o; mOptions.restartOnWakeup = (boolean) o;
break; break;
case "urAccepted": case "urAccepted":
mApi.getSystemInfo(systemInfo -> { mApi.getSystemStatus(systemStatus -> {
mOptions.urAccepted = ((boolean) o) mOptions.urAccepted = ((boolean) o)
? systemInfo.urVersionMax ? systemStatus.urVersionMax
: Options.USAGE_REPORTING_DENIED; : Options.USAGE_REPORTING_DENIED;
}); });
break; break;

View file

@ -36,7 +36,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
private static final String TAG = "DrawerFragment"; private static final String TAG = "DrawerFragment";
private TextView mVersion; private TextView mVersion = null;
private TextView mDrawerActionShowQrCode; private TextView mDrawerActionShowQrCode;
private TextView mDrawerActionWebGui; private TextView mDrawerActionWebGui;
private TextView mDrawerActionRestart; private TextView mDrawerActionRestart;
@ -44,7 +44,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
private TextView mExitButton; private TextView mExitButton;
private MainActivity mActivity; private MainActivity mActivity;
private SharedPreferences sharedPreferences; private SharedPreferences sharedPreferences = null;
@Override @Override
public void onServiceStateChange(SyncthingService.State currentState) { public void onServiceStateChange(SyncthingService.State currentState) {
@ -55,6 +55,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
updateLabels();
updateButtons(); updateButtons();
} }
@ -83,9 +84,6 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
mDrawerActionSettings = view.findViewById(R.id.drawerActionSettings); mDrawerActionSettings = view.findViewById(R.id.drawerActionSettings);
mExitButton = view.findViewById(R.id.drawerActionExit); mExitButton = view.findViewById(R.id.drawerActionExit);
// Show static content.
mVersion.setText(sharedPreferences.getString(Constants.PREF_LAST_BINARY_VERSION, ""));
// Add listeners to buttons. // Add listeners to buttons.
mDrawerActionShowQrCode.setOnClickListener(this); mDrawerActionShowQrCode.setOnClickListener(this);
mDrawerActionWebGui.setOnClickListener(this); mDrawerActionWebGui.setOnClickListener(this);
@ -93,6 +91,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
mDrawerActionSettings.setOnClickListener(this); mDrawerActionSettings.setOnClickListener(this);
mExitButton.setOnClickListener(this); mExitButton.setOnClickListener(this);
updateLabels();
updateButtons(); updateButtons();
} }
@ -101,6 +100,15 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
super.onActivityCreated(savedInstanceState); 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. * Update action button availability.
*/ */

View file

@ -21,13 +21,14 @@ import com.nutomic.syncthingandroid.activities.MainActivity;
import com.nutomic.syncthingandroid.activities.SettingsActivity; import com.nutomic.syncthingandroid.activities.SettingsActivity;
import com.nutomic.syncthingandroid.activities.SyncthingActivity; import com.nutomic.syncthingandroid.activities.SyncthingActivity;
import com.nutomic.syncthingandroid.model.Connections; 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.model.SystemVersion;
import com.nutomic.syncthingandroid.service.Constants; import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.RestApi; import com.nutomic.syncthingandroid.service.RestApi;
import com.nutomic.syncthingandroid.service.SyncthingService; import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.util.Util; import com.nutomic.syncthingandroid.util.Util;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -67,6 +68,7 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS
private String mDownload = ""; private String mDownload = "";
private String mUpload = ""; private String mUpload = "";
private String mAnnounceServer = ""; private String mAnnounceServer = "";
private String mUptime = "";
@Override @Override
public void setUserVisibleHint(boolean isVisibleToUser) 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. // Add status holders refreshed by callbacks to the list.
if (mServiceState == SyncthingService.State.ACTIVE) { if (mServiceState == SyncthingService.State.ACTIVE) {
synchronized (mStatusHolderLock) { synchronized (mStatusHolderLock) {
if (!TextUtils.isEmpty(mCpuUsage)) { if (!TextUtils.isEmpty(mUptime)) {
statusItems.add(getString(R.string.cpu_usage) + ": " + mCpuUsage); statusItems.add(getString(R.string.uptime) + ": " + mUptime);
} }
if (!TextUtils.isEmpty(mRamUsage)) { if (!TextUtils.isEmpty(mRamUsage)) {
statusItems.add(getString(R.string.ram_usage) + ": " + 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)) { if (!TextUtils.isEmpty(mDownload)) {
statusItems.add(getString(R.string.download_title) + ": " + mDownload); statusItems.add(getString(R.string.download_title) + ": " + mDownload);
} }
@ -218,26 +223,42 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS
return; return;
} }
Log.v(TAG, "Invoking REST status queries"); Log.v(TAG, "Invoking REST status queries");
restApi.getSystemInfo(this::onReceiveSystemInfo); restApi.getSystemStatus(this::onReceiveSystemStatus);
restApi.getConnections(this::onReceiveConnections); 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) { if (getActivity() == null) {
return; return;
} }
NumberFormat percentFormat = NumberFormat.getPercentInstance(); NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMaximumFractionDigits(2); percentFormat.setMaximumFractionDigits(2);
int announceTotal = info.discoveryMethods; int announceTotal = systemStatus.discoveryMethods;
int announceConnected = int announceConnected =
announceTotal - Optional.fromNullable(info.discoveryErrors).transform(Map::size).or(0); announceTotal - Optional.fromNullable(systemStatus.discoveryErrors).transform(Map::size).or(0);
synchronized (mStatusHolderLock) { synchronized (mStatusHolderLock) {
mCpuUsage = percentFormat.format(info.cpuPercent / 100); mCpuUsage = (systemStatus.cpuPercent / 100 < 1) ? "" : percentFormat.format(systemStatus.cpuPercent / 100);
mRamUsage = Util.readableFileSize(mActivity, info.sys); mRamUsage = Util.readableFileSize(mActivity, systemStatus.sys);
mAnnounceServer = String.format(Locale.getDefault(), "%1$d/%2$d", announceConnected, announceTotal); 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(); updateStatus();
} }
@ -251,8 +272,12 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS
} }
Connections.Connection c = connections.total; Connections.Connection c = connections.total;
synchronized (mStatusHolderLock) { 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(); updateStatus();
} }

View file

@ -19,9 +19,9 @@ public class GetRequest extends ApiRequest {
public static final String URI_CONFIG = "/rest/system/config"; public static final String URI_CONFIG = "/rest/system/config";
public static final String URI_DEBUG = "/rest/system/debug"; public static final String URI_DEBUG = "/rest/system/debug";
public static final String URI_VERSION = "/rest/system/version"; public static final String URI_VERSION = "/rest/system/version";
public static final String URI_SYSTEM = "/rest/system/status"; public static final String URI_SYSTEM_STATUS = "/rest/system/status";
public static final String URI_CONNECTIONS = "/rest/system/connections"; public static final String URI_CONNECTIONS = "/rest/system/connections";
public static final String URI_STATUS = "/rest/db/status"; public static final String URI_DB_STATUS = "/rest/db/status";
public static final String URI_DEVICEID = "/rest/svc/deviceid"; public static final String URI_DEVICEID = "/rest/svc/deviceid";
public static final String URI_REPORT = "/rest/svc/report"; public static final String URI_REPORT = "/rest/svc/report";
public static final String URI_EVENTS = "/rest/events"; public static final String URI_EVENTS = "/rest/events";

View file

@ -1,15 +1,24 @@
package com.nutomic.syncthingandroid.model; package com.nutomic.syncthingandroid.model;
import java.util.List;
import java.util.Map; import java.util.Map;
public class SystemInfo { /**
* REST API endpoint "/rest/system/status"
*/
public class SystemStatus {
public long alloc; public long alloc;
public double cpuPercent; public double cpuPercent;
public Map<String, Map<String, List<String>>> connectionServiceStatus;
public boolean discoveryEnabled;
public Map<String, String> discoveryErrors;
public int discoveryMethods;
public int goroutines; public int goroutines;
public String myID; public String myID;
public String pathSeparator;
public String startTime;
public long sys; public long sys;
public boolean discoveryEnabled; public String tilde;
public int discoveryMethods; public long uptime;
public Map<String, String> discoveryErrors;
public int urVersionMax; public int urVersionMax;
} }

View file

@ -31,7 +31,7 @@ import com.nutomic.syncthingandroid.model.Event;
import com.nutomic.syncthingandroid.model.Folder; import com.nutomic.syncthingandroid.model.Folder;
import com.nutomic.syncthingandroid.model.FolderStatus; import com.nutomic.syncthingandroid.model.FolderStatus;
import com.nutomic.syncthingandroid.model.Options; 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.model.SystemVersion;
import com.nutomic.syncthingandroid.service.Constants; import com.nutomic.syncthingandroid.service.Constants;
@ -112,11 +112,11 @@ public class RestApi {
*/ */
private Boolean asyncQueryConfigComplete = false; private Boolean asyncQueryConfigComplete = false;
private Boolean asyncQueryVersionComplete = false; private Boolean asyncQueryVersionComplete = false;
private Boolean asyncQuerySystemInfoComplete = false; private Boolean asyncQuerySystemStatusComplete = false;
/** /**
* Object that must be locked upon accessing the following variables: * Object that must be locked upon accessing the following variables:
* asyncQueryConfigComplete, asyncQueryVersionComplete, asyncQuerySystemInfoComplete * asyncQueryConfigComplete, asyncQueryVersionComplete, asyncQuerySystemStatusComplete
*/ */
private final Object mAsyncQueryCompleteLock = new Object(); private final Object mAsyncQueryCompleteLock = new Object();
@ -163,7 +163,7 @@ public class RestApi {
synchronized (mAsyncQueryCompleteLock) { synchronized (mAsyncQueryCompleteLock) {
asyncQueryVersionComplete = false; asyncQueryVersionComplete = false;
asyncQueryConfigComplete = false; asyncQueryConfigComplete = false;
asyncQuerySystemInfoComplete = false; asyncQuerySystemStatusComplete = false;
} }
new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mApiKey, null, result -> { new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mApiKey, null, result -> {
JsonObject json = new JsonParser().parse(result).getAsJsonObject(); JsonObject json = new JsonParser().parse(result).getAsJsonObject();
@ -182,18 +182,18 @@ public class RestApi {
checkReadConfigFromRestApiCompleted(); checkReadConfigFromRestApiCompleted();
} }
}); });
getSystemInfo(info -> { getSystemStatus(info -> {
mLocalDeviceId = info.myID; mLocalDeviceId = info.myID;
mUrVersionMax = info.urVersionMax; mUrVersionMax = info.urVersionMax;
synchronized (mAsyncQueryCompleteLock) { synchronized (mAsyncQueryCompleteLock) {
asyncQuerySystemInfoComplete = true; asyncQuerySystemStatusComplete = true;
checkReadConfigFromRestApiCompleted(); checkReadConfigFromRestApiCompleted();
} }
}); });
} }
private void checkReadConfigFromRestApiCompleted() { private void checkReadConfigFromRestApiCompleted() {
if (asyncQueryVersionComplete && asyncQueryConfigComplete && asyncQuerySystemInfoComplete) { if (asyncQueryVersionComplete && asyncQueryConfigComplete && asyncQuerySystemStatusComplete) {
Log.v(TAG, "Reading config from REST completed."); Log.v(TAG, "Reading config from REST completed.");
mOnApiAvailableListener.onApiAvailable(); mOnApiAvailableListener.onApiAvailable();
} }
@ -502,9 +502,9 @@ public class RestApi {
/** /**
* Requests and parses information about current system status and resource usage. * Requests and parses information about current system status and resource usage.
*/ */
public void getSystemInfo(OnResultListener1<SystemInfo> listener) { public void getSystemStatus(OnResultListener1<SystemStatus> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM, mApiKey, null, result -> new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM_STATUS, mApiKey, null, result ->
listener.onResult(new Gson().fromJson(result, SystemInfo.class))); listener.onResult(new Gson().fromJson(result, SystemStatus.class)));
} }
public boolean isConfigLoaded() { public boolean isConfigLoaded() {
@ -558,7 +558,7 @@ public class RestApi {
* Returns status information about the folder with the given id. * Returns status information about the folder with the given id.
*/ */
public void getFolderStatus(final String folderId, final OnResultListener2<String, FolderStatus> listener) { public void getFolderStatus(final String folderId, final OnResultListener2<String, FolderStatus> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_STATUS, mApiKey, new GetRequest(mContext, mUrl, GetRequest.URI_DB_STATUS, mApiKey,
ImmutableMap.of("folder", folderId), result -> { ImmutableMap.of("folder", folderId), result -> {
FolderStatus m = new Gson().fromJson(result, FolderStatus.class); FolderStatus m = new Gson().fromJson(result, FolderStatus.class);
mCachedFolderStatuses.put(folderId, m); mCachedFolderStatuses.put(folderId, m);

View file

@ -158,6 +158,9 @@ Please report any problems you encounter via Github.</string>
<!-- Title for announce server status --> <!-- Title for announce server status -->
<string name="announce_server">Configured Announce Server</string> <string name="announce_server">Configured Announce Server</string>
<!-- Title for uptime status -->
<string name="uptime">Uptime</string>
<string name="restart">Restart</string> <string name="restart">Restart</string>
<string name="dialog_confirm_restart">Do you want to restart Syncthing?</string> <string name="dialog_confirm_restart">Do you want to restart Syncthing?</string>