mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-11-26 22:31:16 +00:00
Use volley for API requests (fixes #827)
This commit is contained in:
parent
71546fb160
commit
618945c5bf
11 changed files with 202 additions and 243 deletions
|
@ -27,6 +27,7 @@ dependencies {
|
||||||
compile 'org.mindrot:jbcrypt:0.3m'
|
compile 'org.mindrot:jbcrypt:0.3m'
|
||||||
compile 'com.google.guava:guava:20.0'
|
compile 'com.google.guava:guava:20.0'
|
||||||
compile 'com.annimon:stream:1.1.4'
|
compile 'com.annimon:stream:1.1.4'
|
||||||
|
compile 'com.android.volley:volley:1.0.0'
|
||||||
androidTestCompile 'com.android.support.test:rules:0.5'
|
androidTestCompile 'com.android.support.test:rules:0.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,19 @@ package com.nutomic.syncthingandroid.http;
|
||||||
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.android.volley.AuthFailureError;
|
||||||
import com.google.common.io.ByteSource;
|
import com.android.volley.RequestQueue;
|
||||||
|
import com.android.volley.VolleyError;
|
||||||
|
import com.android.volley.toolbox.HurlStack;
|
||||||
|
import com.android.volley.toolbox.StringRequest;
|
||||||
|
import com.android.volley.toolbox.Volley;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -27,16 +33,17 @@ import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
public abstract class RestTask extends
|
public abstract class ApiRequest {
|
||||||
AsyncTask<Void, Void, Pair<Boolean, String>> {
|
|
||||||
|
|
||||||
private static final String TAG = "RestTask";
|
private static final String TAG = "ApiRequest";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the HTTP header used for the syncthing API key.
|
* The name of the HTTP header used for the syncthing API key.
|
||||||
|
@ -47,74 +54,91 @@ public abstract class RestTask extends
|
||||||
public void onSuccess(String result);
|
public void onSuccess(String result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface OnErrorListener {
|
||||||
|
public void onError(VolleyError error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RequestQueue sVolleyQueue;
|
||||||
|
|
||||||
|
private RequestQueue getVolleyQueue() {
|
||||||
|
if (sVolleyQueue == null) {
|
||||||
|
Context context = mContext.getApplicationContext();
|
||||||
|
sVolleyQueue = Volley.newRequestQueue(context, new NetworkStack());
|
||||||
|
}
|
||||||
|
return sVolleyQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
private final URL mUrl;
|
private final URL mUrl;
|
||||||
protected final String mPath;
|
protected final String mPath;
|
||||||
private final String mHttpsCertPath;
|
private final String mHttpsCertPath;
|
||||||
private final String mApiKey;
|
private final String mApiKey;
|
||||||
private final OnSuccessListener mListener;
|
|
||||||
|
|
||||||
public RestTask(URL url, String path, String httpsCertPath, String apiKey,
|
public ApiRequest(Context context, URL url, String path, String httpsCertPath, String apiKey) {
|
||||||
OnSuccessListener listener) {
|
mContext = context;
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
mPath = path;
|
mPath = path;
|
||||||
mHttpsCertPath = httpsCertPath;
|
mHttpsCertPath = httpsCertPath;
|
||||||
mApiKey = apiKey;
|
mApiKey = apiKey;
|
||||||
mListener = listener;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HttpsURLConnection openConnection(Map<String, String> params) throws IOException {
|
protected Uri buildUri(Map<String, String> params) {
|
||||||
Uri.Builder uriBuilder = Uri.parse(mUrl.toString())
|
Uri.Builder uriBuilder = Uri.parse(mUrl.toString())
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.path(mPath);
|
.path(mPath);
|
||||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
uriBuilder.appendQueryParameter(entry.getKey(), entry.getValue());
|
uriBuilder.appendQueryParameter(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
URL url = new URL(uriBuilder.build().toString());
|
return uriBuilder.build();
|
||||||
Log.v(TAG, "Calling Rest API at " + url);
|
|
||||||
|
|
||||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
|
||||||
connection.setRequestProperty(HEADER_API_KEY, mApiKey);
|
|
||||||
connection.setHostnameVerifier((h, s) -> true);
|
|
||||||
connection.setSSLSocketFactory(getSslSocketFactory());
|
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the connection, then returns success status and response string.
|
* Opens the connection, then returns success status and response string.
|
||||||
*/
|
*/
|
||||||
protected Pair<Boolean, String> connect(HttpsURLConnection connection) throws IOException {
|
protected void connect(int requestMethod, Uri uri, @Nullable String requestBody,
|
||||||
connection.connect();
|
@Nullable OnSuccessListener listener, @Nullable OnErrorListener errorListener) {
|
||||||
Pair<Boolean, String> result;
|
StringRequest request = new StringRequest(requestMethod, uri.toString(), reply -> {
|
||||||
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
if (listener != null)
|
||||||
int responseCode = connection.getResponseCode();
|
listener.onSuccess(reply);
|
||||||
String responseMessage = connection.getResponseMessage();
|
}, error -> {
|
||||||
Log.i(TAG, "Request to " + connection.getURL() + " failed, code: " + responseCode +
|
if (errorListener != null)
|
||||||
", message: " + responseMessage);
|
errorListener.onError(error);
|
||||||
result = new Pair<>(false, streamToString(connection.getErrorStream()));
|
|
||||||
}
|
Log.w(TAG, "Request to " + uri + " failed: " + error.getMessage());
|
||||||
else {
|
}) {
|
||||||
result = new Pair<>(true, streamToString(connection.getInputStream()));
|
@Override
|
||||||
}
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
connection.disconnect();
|
return ImmutableMap.of(HEADER_API_KEY, mApiKey);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String streamToString(InputStream is) throws IOException {
|
|
||||||
ByteSource byteSource = new ByteSource() {
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream openStream() throws IOException {
|
public byte[] getBody() throws AuthFailureError {
|
||||||
return is;
|
return Optional.fromNullable(requestBody).transform(String::getBytes).orNull();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return byteSource.asCharSource(Charsets.UTF_8).read();
|
getVolleyQueue().add(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends {@link HurlStack}, uses {@link #getSslSocketFactory()} and disables hostname
|
||||||
|
* verification.
|
||||||
|
*/
|
||||||
|
private class NetworkStack extends HurlStack {
|
||||||
|
|
||||||
protected void onPostExecute(Pair<Boolean, String> result) {
|
public NetworkStack() {
|
||||||
if (mListener == null || !result.first)
|
super(null, getSslSocketFactory());
|
||||||
return;
|
}
|
||||||
|
@Override
|
||||||
mListener.onSuccess(result.second);
|
protected HttpURLConnection createConnection(URL url) throws IOException {
|
||||||
|
HttpsURLConnection connection = (HttpsURLConnection) super.createConnection(url);
|
||||||
|
connection.setHostnameVerifier(new HostnameVerifier() {
|
||||||
|
@Override
|
||||||
|
public boolean verify(String hostname, SSLSession session) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SSLSocketFactory getSslSocketFactory() {
|
private SSLSocketFactory getSslSocketFactory() {
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.nutomic.syncthingandroid.http;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.volley.Request;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a GET request to the Syncthing API
|
||||||
|
*/
|
||||||
|
public class GetRequest extends ApiRequest {
|
||||||
|
|
||||||
|
public static final String URI_CONFIG = "/rest/system/config";
|
||||||
|
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_MODEL = "/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 httpsCertPath, String apiKey,
|
||||||
|
@Nullable Map<String, String> params, OnSuccessListener listener) {
|
||||||
|
super(context, url, path, httpsCertPath, apiKey);
|
||||||
|
Map<String, String> safeParams = Optional.fromNullable(params).or(Collections.emptyMap());
|
||||||
|
Uri uri = buildUri(safeParams);
|
||||||
|
connect(Request.Method.GET, uri, null, listener, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,54 +0,0 @@
|
||||||
package com.nutomic.syncthingandroid.http;
|
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs a GET request to the Syncthing API
|
|
||||||
* Performs a GET request with no parameters to the URL in uri[0] with the path in uri[1] and
|
|
||||||
* returns the result as a String.
|
|
||||||
*/
|
|
||||||
public class GetTask extends RestTask {
|
|
||||||
|
|
||||||
private static final String TAG = "GetTask";
|
|
||||||
|
|
||||||
public static final String URI_CONFIG = "/rest/system/config";
|
|
||||||
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_MODEL = "/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";
|
|
||||||
|
|
||||||
private final Map<String, String> mParams;
|
|
||||||
|
|
||||||
public GetTask(URL url, String path, String httpsCertPath, String apiKey,
|
|
||||||
@Nullable Map<String, String> params, OnSuccessListener listener) {
|
|
||||||
super(url, path, httpsCertPath, apiKey, listener);
|
|
||||||
mParams = Optional.fromNullable(params).or(Collections.emptyMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Pair<Boolean, String> doInBackground(Void... aVoid) {
|
|
||||||
try {
|
|
||||||
HttpsURLConnection connection = openConnection(mParams);
|
|
||||||
Log.v(TAG, "Calling Rest API at " + connection.getURL());
|
|
||||||
return connect(connection);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, "Failed to call rest api", e);
|
|
||||||
return new Pair<>(false, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,21 +1,20 @@
|
||||||
package com.nutomic.syncthingandroid.http;
|
package com.nutomic.syncthingandroid.http;
|
||||||
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.content.Context;
|
||||||
import android.util.Pair;
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.android.volley.Request;
|
||||||
|
import com.android.volley.VolleyError;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Polls to load the web interface, until we receive http status 200.
|
* Polls to load the web interface, until it is available.
|
||||||
*/
|
*/
|
||||||
public class PollWebGuiAvailableTask extends RestTask {
|
public class PollWebGuiAvailableTask extends ApiRequest {
|
||||||
|
|
||||||
private static final String TAG = "PollWebGuiAvailableTask";
|
private static final String TAG = "PollWebGuiAvailableTask";
|
||||||
|
|
||||||
|
@ -25,29 +24,23 @@ public class PollWebGuiAvailableTask extends RestTask {
|
||||||
*/
|
*/
|
||||||
private static final long WEB_GUI_POLL_INTERVAL = 100;
|
private static final long WEB_GUI_POLL_INTERVAL = 100;
|
||||||
|
|
||||||
public PollWebGuiAvailableTask(URL url, String httpsCertPath, String apiKey,
|
private final OnSuccessListener mListener;
|
||||||
|
private final Handler mHandler = new Handler();
|
||||||
|
|
||||||
|
public PollWebGuiAvailableTask(Context context, URL url, String httpsCertPath, String apiKey,
|
||||||
OnSuccessListener listener) {
|
OnSuccessListener listener) {
|
||||||
super(url, "", httpsCertPath, apiKey, listener);
|
super(context, url, "", httpsCertPath, apiKey);
|
||||||
|
mListener = listener;
|
||||||
|
performRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void performRequest() {
|
||||||
protected Pair<Boolean, String> doInBackground(Void... aVoid) {
|
Uri uri = buildUri(Collections.emptyMap());
|
||||||
int status = 0;
|
connect(Request.Method.GET, uri, null, mListener, this::onError);
|
||||||
do {
|
|
||||||
try {
|
|
||||||
HttpsURLConnection connection = openConnection(Collections.emptyMap());
|
|
||||||
connection.connect();
|
|
||||||
status = connection.getResponseCode();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// We catch this in every call, as long as the service is not online, so we ignore and continue.
|
|
||||||
try {
|
|
||||||
Thread.sleep(WEB_GUI_POLL_INTERVAL);
|
|
||||||
} catch (InterruptedException e2) {
|
|
||||||
Log.w(TAG, "Failed to sleep", e2);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} while (status != HttpsURLConnection.HTTP_OK);
|
private void onError(VolleyError error) {
|
||||||
return new Pair<>(true, null);
|
mHandler.postDelayed(this::performRequest, WEB_GUI_POLL_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.nutomic.syncthingandroid.http;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.android.volley.Request;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class PostConfigRequest extends ApiRequest {
|
||||||
|
|
||||||
|
private static final String URI_CONFIG = "/rest/system/config";
|
||||||
|
|
||||||
|
public PostConfigRequest(Context context, URL url, String httpsCertPath, String apiKey, String config,
|
||||||
|
OnSuccessListener listener) {
|
||||||
|
super(context, url, URI_CONFIG, httpsCertPath, apiKey);
|
||||||
|
Uri uri = buildUri(Collections.emptyMap());
|
||||||
|
connect(Request.Method.POST, uri, config, listener, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
package com.nutomic.syncthingandroid.http;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
|
|
||||||
public class PostConfigTask extends RestTask {
|
|
||||||
|
|
||||||
private static final String TAG = "PostConfigTask";
|
|
||||||
|
|
||||||
private static final String URI_CONFIG = "/rest/system/config";
|
|
||||||
|
|
||||||
private final String mConfig;
|
|
||||||
|
|
||||||
public PostConfigTask(URL url, String httpsCertPath, String apiKey, String config,
|
|
||||||
OnSuccessListener listener) {
|
|
||||||
super(url, URI_CONFIG, httpsCertPath, apiKey, listener);
|
|
||||||
mConfig = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Pair<Boolean, String> doInBackground(Void... params) {
|
|
||||||
try {
|
|
||||||
HttpsURLConnection connection = openConnection(Collections.emptyMap());
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
Log.v(TAG, "Calling Rest API at " + connection.getURL());
|
|
||||||
|
|
||||||
OutputStream os = connection.getOutputStream();
|
|
||||||
os.write(mConfig.getBytes("UTF-8"));
|
|
||||||
return connect(connection);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, "Failed to call rest api", e);
|
|
||||||
return new Pair<>(false, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.nutomic.syncthingandroid.http;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.android.volley.Request;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class PostScanRequest extends ApiRequest {
|
||||||
|
|
||||||
|
private static final String URI_SCAN = "/rest/db/scan";
|
||||||
|
|
||||||
|
public PostScanRequest(Context context, URL url, String httpsCertPath, String apiKey,
|
||||||
|
String folder, String sub) {
|
||||||
|
super(context, url, URI_SCAN, httpsCertPath, apiKey);
|
||||||
|
Uri uri = buildUri(ImmutableMap.of("folder", folder, "sub", sub));
|
||||||
|
connect(Request.Method.POST, uri, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,40 +0,0 @@
|
||||||
package com.nutomic.syncthingandroid.http;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
|
|
||||||
public class PostScanTask extends RestTask {
|
|
||||||
|
|
||||||
private static final String TAG = "PostScanTask";
|
|
||||||
|
|
||||||
private static final String URI_SCAN = "/rest/db/scan";
|
|
||||||
|
|
||||||
private final String mFolder;
|
|
||||||
private final String mSub;
|
|
||||||
|
|
||||||
public PostScanTask(URL url, String httpsCertPath, String apiKey, String folder, String sub) {
|
|
||||||
super(url, URI_SCAN, httpsCertPath, apiKey, null);
|
|
||||||
mFolder = folder;
|
|
||||||
mSub = sub;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Pair<Boolean, String> doInBackground(Void... params) {
|
|
||||||
try {
|
|
||||||
HttpsURLConnection connection = openConnection(ImmutableMap.of("folder", mFolder, "sub", mSub));
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
return connect(connection);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, "Failed to call rest api", e);
|
|
||||||
return new Pair<>(false, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,9 +18,9 @@ import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.nutomic.syncthingandroid.BuildConfig;
|
import com.nutomic.syncthingandroid.BuildConfig;
|
||||||
import com.nutomic.syncthingandroid.activities.RestartActivity;
|
import com.nutomic.syncthingandroid.activities.RestartActivity;
|
||||||
import com.nutomic.syncthingandroid.http.GetTask;
|
import com.nutomic.syncthingandroid.http.GetRequest;
|
||||||
import com.nutomic.syncthingandroid.http.PostConfigTask;
|
import com.nutomic.syncthingandroid.http.PostConfigRequest;
|
||||||
import com.nutomic.syncthingandroid.http.PostScanTask;
|
import com.nutomic.syncthingandroid.http.PostScanRequest;
|
||||||
import com.nutomic.syncthingandroid.model.Config;
|
import com.nutomic.syncthingandroid.model.Config;
|
||||||
import com.nutomic.syncthingandroid.model.Connections;
|
import com.nutomic.syncthingandroid.model.Connections;
|
||||||
import com.nutomic.syncthingandroid.model.Device;
|
import com.nutomic.syncthingandroid.model.Device;
|
||||||
|
@ -71,13 +71,13 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
private boolean mRestartPostponed = false;
|
private boolean mRestartPostponed = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the result of the last successful request to {@link GetTask#URI_CONNECTIONS},
|
* Stores the result of the last successful request to {@link GetRequest#URI_CONNECTIONS},
|
||||||
* or an empty Map.
|
* or an empty Map.
|
||||||
*/
|
*/
|
||||||
private Optional<Connections> mPreviousConnections = Optional.absent();
|
private Optional<Connections> mPreviousConnections = Optional.absent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the timestamp of the last successful request to {@link GetTask#URI_CONNECTIONS}.
|
* Stores the timestamp of the last successful request to {@link GetRequest#URI_CONNECTIONS}.
|
||||||
*/
|
*/
|
||||||
private long mPreviousConnectionTime = 0;
|
private long mPreviousConnectionTime = 0;
|
||||||
|
|
||||||
|
@ -121,16 +121,16 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
@Override
|
@Override
|
||||||
public void onWebGuiAvailable() {
|
public void onWebGuiAvailable() {
|
||||||
mAvailableCount.set(0);
|
mAvailableCount.set(0);
|
||||||
new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> {
|
new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> {
|
||||||
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
|
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
|
||||||
mVersion = json.get("version").getAsString();
|
mVersion = json.get("version").getAsString();
|
||||||
Log.i(TAG, "Syncthing version is " + mVersion);
|
Log.i(TAG, "Syncthing version is " + mVersion);
|
||||||
tryIsAvailable();
|
tryIsAvailable();
|
||||||
}).execute();
|
});
|
||||||
new GetTask(mUrl, GetTask.URI_CONFIG, mHttpsCertPath, mApiKey, null, result -> {
|
new GetRequest(mContext, mUrl, GetRequest.URI_CONFIG, mHttpsCertPath, mApiKey, null, result -> {
|
||||||
mConfig = new Gson().fromJson(result, Config.class);
|
mConfig = new Gson().fromJson(result, Config.class);
|
||||||
tryIsAvailable();
|
tryIsAvailable();
|
||||||
}).execute();
|
});
|
||||||
getSystemInfo(info -> {
|
getSystemInfo(info -> {
|
||||||
mLocalDeviceId = info.myID;
|
mLocalDeviceId = info.myID;
|
||||||
tryIsAvailable();
|
tryIsAvailable();
|
||||||
|
@ -168,19 +168,18 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
* Sends current config to Syncthing.
|
* Sends current config to Syncthing.
|
||||||
*/
|
*/
|
||||||
private void sendConfig() {
|
private void sendConfig() {
|
||||||
new PostConfigTask(mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), null)
|
new PostConfigRequest(mContext, mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), null);
|
||||||
.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends current config and restarts Syncthing.
|
* Sends current config and restarts Syncthing.
|
||||||
*/
|
*/
|
||||||
public void restart() {
|
public void restart() {
|
||||||
new PostConfigTask(mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), result -> {
|
new PostConfigRequest(mContext, mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), result -> {
|
||||||
Intent intent = new Intent(mContext, SyncthingService.class)
|
Intent intent = new Intent(mContext, SyncthingService.class)
|
||||||
.setAction(SyncthingService.ACTION_RESTART);
|
.setAction(SyncthingService.ACTION_RESTART);
|
||||||
mContext.startService(intent);
|
mContext.startService(intent);
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -312,9 +311,9 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
* 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 getSystemInfo(OnResultListener1<SystemInfo> listener) {
|
||||||
new GetTask(mUrl, GetTask.URI_SYSTEM, mHttpsCertPath, mApiKey, null, result -> {
|
new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM, mHttpsCertPath, mApiKey, null, result -> {
|
||||||
listener.onResult(new Gson().fromJson(result, SystemInfo.class));
|
listener.onResult(new Gson().fromJson(result, SystemInfo.class));
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConfigLoaded() {
|
public boolean isConfigLoaded() {
|
||||||
|
@ -325,17 +324,17 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
* Requests and parses system version information.
|
* Requests and parses system version information.
|
||||||
*/
|
*/
|
||||||
public void getSystemVersion(OnResultListener1<SystemVersion> listener) {
|
public void getSystemVersion(OnResultListener1<SystemVersion> listener) {
|
||||||
new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> {
|
new GetRequest(mContext, mUrl, GetRequest.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> {
|
||||||
SystemVersion systemVersion = new Gson().fromJson(result, SystemVersion.class);
|
SystemVersion systemVersion = new Gson().fromJson(result, SystemVersion.class);
|
||||||
listener.onResult(systemVersion);
|
listener.onResult(systemVersion);
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns connection info for the local device and all connected devices.
|
* Returns connection info for the local device and all connected devices.
|
||||||
*/
|
*/
|
||||||
public void getConnections(final OnResultListener1<Connections> listener) {
|
public void getConnections(final OnResultListener1<Connections> listener) {
|
||||||
new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, null, result -> {
|
new GetRequest(mContext, mUrl, GetRequest.URI_CONNECTIONS, mHttpsCertPath, mApiKey, null, result -> {
|
||||||
Long now = System.currentTimeMillis();
|
Long now = System.currentTimeMillis();
|
||||||
Long msElapsed = now - mPreviousConnectionTime;
|
Long msElapsed = now - mPreviousConnectionTime;
|
||||||
if (msElapsed < SyncthingService.GUI_UPDATE_INTERVAL) {
|
if (msElapsed < SyncthingService.GUI_UPDATE_INTERVAL) {
|
||||||
|
@ -359,7 +358,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
connections.total.setTransferRate(prev, msElapsed);
|
connections.total.setTransferRate(prev, msElapsed);
|
||||||
mPreviousConnections = Optional.of(connections);
|
mPreviousConnections = Optional.of(connections);
|
||||||
listener.onResult(deepCopy(connections, Connections.class));
|
listener.onResult(deepCopy(connections, Connections.class));
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -398,12 +397,12 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
* Returns status information about the folder with the given id.
|
* Returns status information about the folder with the given id.
|
||||||
*/
|
*/
|
||||||
public void getModel(final String folderId, final OnResultListener2<String, Model> listener) {
|
public void getModel(final String folderId, final OnResultListener2<String, Model> listener) {
|
||||||
new GetTask(mUrl, GetTask.URI_MODEL, mHttpsCertPath, mApiKey,
|
new GetRequest(mContext, mUrl, GetRequest.URI_MODEL, mHttpsCertPath, mApiKey,
|
||||||
ImmutableMap.of("folder", folderId), result -> {
|
ImmutableMap.of("folder", folderId), result -> {
|
||||||
Model m = new Gson().fromJson(result, Model.class);
|
Model m = new Gson().fromJson(result, Model.class);
|
||||||
mCachedModelInfo.put(folderId, m);
|
mCachedModelInfo.put(folderId, m);
|
||||||
listener.onResult(folderId, m);
|
listener.onResult(folderId, m);
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -431,7 +430,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
public final void getEvents(final long sinceId, final long limit, final OnReceiveEventListener listener) {
|
public final void getEvents(final long sinceId, final long limit, final OnReceiveEventListener listener) {
|
||||||
Map<String, String> params =
|
Map<String, String> params =
|
||||||
ImmutableMap.of("since", String.valueOf(sinceId), "limit", String.valueOf(limit));
|
ImmutableMap.of("since", String.valueOf(sinceId), "limit", String.valueOf(limit));
|
||||||
new GetTask(mUrl, GetTask.URI_EVENTS, mHttpsCertPath, mApiKey, params, result -> {
|
new GetRequest(mContext, mUrl, GetRequest.URI_EVENTS, mHttpsCertPath, mApiKey, params, result -> {
|
||||||
JsonArray jsonEvents = new JsonParser().parse(result).getAsJsonArray();
|
JsonArray jsonEvents = new JsonParser().parse(result).getAsJsonArray();
|
||||||
long lastId = 0;
|
long lastId = 0;
|
||||||
|
|
||||||
|
@ -446,7 +445,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.onDone(lastId);
|
listener.onDone(lastId);
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -454,8 +453,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
*/
|
*/
|
||||||
public void normalizeDeviceId(String id, OnResultListener1<String> listener,
|
public void normalizeDeviceId(String id, OnResultListener1<String> listener,
|
||||||
OnResultListener1<String> errorListener) {
|
OnResultListener1<String> errorListener) {
|
||||||
new GetTask(mUrl, GetTask.URI_DEVICEID, mHttpsCertPath, mApiKey, ImmutableMap.of("id", id),
|
new GetRequest(mContext, mUrl, GetRequest.URI_DEVICEID, mHttpsCertPath, mApiKey,
|
||||||
result -> {
|
ImmutableMap.of("id", id), result -> {
|
||||||
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
|
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
|
||||||
JsonElement normalizedId = json.get("id");
|
JsonElement normalizedId = json.get("id");
|
||||||
JsonElement error = json.get("error");
|
JsonElement error = json.get("error");
|
||||||
|
@ -463,7 +462,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
listener.onResult(normalizedId.getAsString());
|
listener.onResult(normalizedId.getAsString());
|
||||||
if (error != null)
|
if (error != null)
|
||||||
errorListener.onResult(error.getAsString());
|
errorListener.onResult(error.getAsString());
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -471,19 +470,18 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onFolderFileChange(String folderId, String relativePath) {
|
public void onFolderFileChange(String folderId, String relativePath) {
|
||||||
new PostScanTask(mUrl, mHttpsCertPath, mApiKey, folderId, relativePath)
|
new PostScanRequest(mContext, mUrl, mHttpsCertPath, mApiKey, folderId, relativePath);
|
||||||
.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns prettyfied usage report.
|
* Returns prettyfied usage report.
|
||||||
*/
|
*/
|
||||||
public void getUsageReport(final OnResultListener1<String> listener) {
|
public void getUsageReport(final OnResultListener1<String> listener) {
|
||||||
new GetTask(mUrl, GetTask.URI_REPORT, mHttpsCertPath, mApiKey, null, result -> {
|
new GetRequest(mContext, mUrl, GetRequest.URI_REPORT, mHttpsCertPath, mApiKey, null, result -> {
|
||||||
JsonElement json = new JsonParser().parse(result);
|
JsonElement json = new JsonParser().parse(result);
|
||||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
listener.onResult(gson.toJson(json));
|
listener.onResult(gson.toJson(json));
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRestartPostponed() {
|
public void setRestartPostponed() {
|
||||||
|
|
|
@ -491,7 +491,7 @@ public class SyncthingService extends Service implements
|
||||||
* for SyncthingService.onDestroy for details.
|
* for SyncthingService.onDestroy for details.
|
||||||
*/
|
*/
|
||||||
private void pollWebGui() {
|
private void pollWebGui() {
|
||||||
new PollWebGuiAvailableTask(getWebGuiUrl(), getFilesDir() + "/" + HTTPS_CERT_FILE,
|
new PollWebGuiAvailableTask(this, getWebGuiUrl(), getFilesDir() + "/" + HTTPS_CERT_FILE,
|
||||||
mConfig.getApiKey(), result -> {
|
mConfig.getApiKey(), result -> {
|
||||||
synchronized (stateLock) {
|
synchronized (stateLock) {
|
||||||
if (mStopScheduled) {
|
if (mStopScheduled) {
|
||||||
|
@ -510,7 +510,7 @@ public class SyncthingService extends Service implements
|
||||||
listener.onWebGuiAvailable();
|
listener.onWebGuiAvailable();
|
||||||
}
|
}
|
||||||
mOnWebGuiAvailableListeners.clear();
|
mOnWebGuiAvailableListeners.clear();
|
||||||
}).execute();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue