1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-11-26 14:21:16 +00:00

Use Gson for connections

This commit is contained in:
Felix Ableitner 2016-11-17 20:01:51 +09:00
parent a201cd8789
commit dcdb6e1129
7 changed files with 78 additions and 102 deletions

View file

@ -1,10 +1,8 @@
package com.nutomic.syncthingandroid.test;
import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import com.nutomic.syncthingandroid.model.Connection;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.model.Folder;
import com.nutomic.syncthingandroid.model.Model;
@ -12,7 +10,6 @@ import com.nutomic.syncthingandroid.model.SystemInfo;
import com.nutomic.syncthingandroid.service.RestApi;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -54,7 +51,7 @@ public class MockRestApi extends RestApi {
}
@Override
public void getConnections(OnResultListener1<Map<String, Connection>> listener) {
public void getConnections(OnResultListener1<Map<String, Connections>> listener) {
throw new UnsupportedOperationException();
}

View file

@ -12,7 +12,9 @@ import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.*;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
@ -22,7 +24,7 @@ import com.google.gson.Gson;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.model.Connection;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.util.Compression;
@ -32,7 +34,6 @@ import com.nutomic.syncthingandroid.util.Util;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static android.text.TextUtils.isEmpty;
import static android.view.View.GONE;
@ -218,13 +219,13 @@ public class DeviceActivity extends SyncthingActivity implements View.OnClickLis
* NOTE: This is only called once on startup, should be called more often to properly display
* version/address changes.
*/
public void onReceiveConnections(Map<String, Connection> connections) {
public void onReceiveConnections(Connections connections) {
boolean viewsExist = mSyncthingVersionView != null && mCurrentAddressView != null;
if (viewsExist && connections.containsKey(mDevice.deviceID)) {
if (viewsExist && connections.connections.containsKey(mDevice.deviceID)) {
mCurrentAddressView.setVisibility(VISIBLE);
mSyncthingVersionView.setVisibility(VISIBLE);
mCurrentAddressView.setText(connections.get(mDevice.deviceID).address);
mSyncthingVersionView.setText(connections.get(mDevice.deviceID).clientVersion);
mCurrentAddressView.setText(connections.connections.get(mDevice.deviceID).address);
mSyncthingVersionView.setText(connections.connections.get(mDevice.deviceID).clientVersion);
}
}

View file

@ -15,7 +15,7 @@ import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.activities.MainActivity;
import com.nutomic.syncthingandroid.activities.SettingsActivity;
import com.nutomic.syncthingandroid.activities.WebGuiActivity;
import com.nutomic.syncthingandroid.model.Connection;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.SystemInfo;
import com.nutomic.syncthingandroid.model.SystemVersion;
import com.nutomic.syncthingandroid.service.RestApi;
@ -187,8 +187,8 @@ public class DrawerFragment extends Fragment implements View.OnClickListener {
/**
* Populates views with status received via {@link RestApi#getConnections}.
*/
private void onReceiveConnections(Map<String, Connection> connections) {
Connection c = connections.get(RestApi.TOTAL_STATS);
private void onReceiveConnections(Connections connections) {
Connections.Connection c = connections.total;
mDownload.setText(Util.readableTransferRate(mActivity, c.inBits));
mUpload.setText(Util.readableTransferRate(mActivity, c.outBits));
}

View file

@ -1,13 +0,0 @@
package com.nutomic.syncthingandroid.model;
public class Connection {
public String at;
public long inBytesTotal;
public long outBytesTotal;
public long inBits;
public long outBits;
public String address;
public String clientVersion;
public int completion;
public boolean connected;
}

View file

@ -0,0 +1,34 @@
package com.nutomic.syncthingandroid.model;
import java.util.Map;
public class Connections {
public Connection total;
public Map<String, Connection> connections;
public static class Connection {
public boolean paused;
public String clientVersion;
public String at;
public boolean connected;
public long inBytesTotal;
public long outBytesTotal;
public String type;
public String address;
// These fields are not sent from Syncthing, but are populated on the client side.
public int completion;
public long inBits;
public long outBits;
public void setTransferRate(Connection previous, long msElapsed) {
long secondsElapsed = msElapsed / 1000;
long inBytes = 8 * (inBytesTotal - previous.inBytesTotal) / secondsElapsed;
long outBytes = 8 * (outBytesTotal - previous.outBytesTotal) / secondsElapsed;
inBits = Math.max(0, inBytes);
outBits = Math.max(0, outBytes);
}
}
}

View file

@ -7,6 +7,7 @@ import android.content.Intent;
import android.util.Log;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
@ -21,7 +22,7 @@ import com.nutomic.syncthingandroid.http.GetTask;
import com.nutomic.syncthingandroid.http.PostConfigTask;
import com.nutomic.syncthingandroid.http.PostScanTask;
import com.nutomic.syncthingandroid.model.Config;
import com.nutomic.syncthingandroid.model.Connection;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.model.Event;
import com.nutomic.syncthingandroid.model.Folder;
@ -31,10 +32,6 @@ import com.nutomic.syncthingandroid.model.SystemInfo;
import com.nutomic.syncthingandroid.model.SystemVersion;
import com.nutomic.syncthingandroid.util.FolderObserver;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.HashMap;
@ -51,12 +48,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
private static final String TAG = "RestApi";
/**
* Key of the map element containing connection info for the local device, in the return
* value of {@link #getConnections}
*/
public static final String TOTAL_STATS = "total";
public interface OnConfigChangedListener {
void onConfigChanged();
}
@ -83,7 +74,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Stores the result of the last successful request to {@link GetTask#URI_CONNECTIONS},
* or an empty Map.
*/
private Map<String, Connection> mPreviousConnections = new HashMap<>();
private Optional<Connections> mPreviousConnections = Optional.absent();
/**
* Stores the timestamp of the last successful request to {@link GetTask#URI_CONNECTIONS}.
@ -342,62 +333,31 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
/**
* Returns connection info for the local device and all connected devices.
* <p/>
* Use the key {@link #TOTAL_STATS} to get connection info for the local device.
*
* The result is cached internally. Do not modify it or any of its contents.
*/
public void getConnections(final OnResultListener1<Map<String, Connection>> listener) {
public void getConnections(final OnResultListener1<Connections> listener) {
new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, null, result -> {
Long now = System.currentTimeMillis();
Long timeElapsed = (now - mPreviousConnectionTime) / 1000;
if (timeElapsed < 1) {
listener.onResult(mPreviousConnections);
Long msElapsed = now - mPreviousConnectionTime;
if (msElapsed < SyncthingService.GUI_UPDATE_INTERVAL) {
listener.onResult(deepCopy(mPreviousConnections.get(), Connections.class));
return;
}
try {
JSONObject json = new JSONObject(result);
Map<String, JSONObject> jsonConnections = new HashMap<>();
jsonConnections.put(TOTAL_STATS, json.getJSONObject(TOTAL_STATS));
JSONArray extConnections = json.getJSONObject("connections").names();
if (extConnections != null) {
for (int i = 0; i < extConnections.length(); i++) {
String deviceId = extConnections.get(i).toString();
jsonConnections.put(deviceId, json.getJSONObject("connections").getJSONObject(deviceId));
}
}
Map<String, Connection> connections = new HashMap<>();
for (Map.Entry<String, JSONObject> jsonConnection : jsonConnections.entrySet()) {
String deviceId = jsonConnection.getKey();
Connection c = new Connection();
JSONObject conn = jsonConnection.getValue();
c.address = deviceId;
c.at = conn.getString("at");
c.inBytesTotal = conn.getLong("inBytesTotal");
c.outBytesTotal = conn.getLong("outBytesTotal");
c.address = conn.getString("address");
c.clientVersion = conn.getString("clientVersion");
c.completion = getDeviceCompletion(deviceId);
c.connected = conn.getBoolean("connected");
mPreviousConnectionTime = now;
Connections connections = new Gson().fromJson(result, Connections.class);
for (Map.Entry<String, Connections.Connection> e : connections.connections.entrySet()) {
e.getValue().completion = getDeviceCompletion(e.getKey());
Connection prev = (mPreviousConnections.containsKey(deviceId))
? mPreviousConnections.get(deviceId)
: new Connection();
mPreviousConnectionTime = now;
c.inBits = Math.max(0, 8 *
(conn.getLong("inBytesTotal") - prev.inBytesTotal) / timeElapsed);
c.outBits = Math.max(0, 8 *
(conn.getLong("outBytesTotal") - prev.outBytesTotal) / timeElapsed);
connections.put(deviceId, c);
}
mPreviousConnections = connections;
listener.onResult(mPreviousConnections);
} catch (JSONException e) {
Log.w(TAG, "Failed to parse connections", e);
Connections.Connection prev = mPreviousConnections
.transform(c -> c.connections.get(e.getKey()))
.or(new Connections.Connection());
e.getValue().setTransferRate(prev, msElapsed);
}
Connections.Connection prev =
mPreviousConnections.transform(c -> c.total).or(new Connections.Connection());
connections.total.setTransferRate(prev, msElapsed);
mPreviousConnections = Optional.of(connections);
listener.onResult(deepCopy(connections, Connections.class));
}).execute();
}

View file

@ -10,22 +10,19 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.google.common.base.Optional;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.model.Connection;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.service.RestApi;
import com.nutomic.syncthingandroid.util.Util;
import java.util.HashMap;
import java.util.Map;
/**
* Generates item views for device items.
*/
public class DevicesAdapter extends ArrayAdapter<Device> {
private Map<String, Connection> mConnections =
new HashMap<>();
private Optional<Connections> mConnections = Optional.absent();
public DevicesAdapter(Context context) {
super(context, R.layout.item_device_list);
@ -46,21 +43,21 @@ public class DevicesAdapter extends ArrayAdapter<Device> {
TextView upload = (TextView) convertView.findViewById(R.id.upload);
String deviceId = getItem(position).deviceID;
Connection conn = mConnections.get(deviceId);
Optional<Connections.Connection> conn = mConnections.transform(a -> a.connections.get(deviceId));
name.setText(getItem(position).getDisplayName());
Resources r = getContext().getResources();
if (conn != null && conn.connected) {
if (conn.completion == 100) {
if (conn.isPresent() && conn.get().connected) {
if (conn.get().completion == 100) {
status.setText(r.getString(R.string.device_up_to_date));
status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_green));
}
else {
status.setText(r.getString(R.string.device_syncing, conn.completion));
status.setText(r.getString(R.string.device_syncing, conn.get().completion));
status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_blue));
}
download.setText(Util.readableTransferRate(getContext(), conn.inBits));
upload.setText(Util.readableTransferRate(getContext(), conn.outBits));
download.setText(Util.readableTransferRate(getContext(), conn.get().inBits));
upload.setText(Util.readableTransferRate(getContext(), conn.get().outBits));
}
else {
download.setText(Util.readableTransferRate(getContext(), 0));
@ -81,8 +78,8 @@ public class DevicesAdapter extends ArrayAdapter<Device> {
}
}
public void onReceiveConnections(Map<String, Connection> connections) {
mConnections = connections;
public void onReceiveConnections(Connections connections) {
mConnections = Optional.of(connections);
notifyDataSetChanged();
}
}