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

Use lambdas for RestTask callbacks

This commit is contained in:
Felix Ableitner 2016-10-15 18:09:16 +09:00
parent 396370a71b
commit d222cd7a76
7 changed files with 182 additions and 224 deletions

View file

@ -10,6 +10,7 @@ import com.nutomic.syncthingandroid.syncthing.SyncthingRunnable;
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
import com.nutomic.syncthingandroid.test.MockContext;
import com.nutomic.syncthingandroid.util.ConfigXml;
import com.nutomic.syncthingandroid.util.Util;
import org.junit.After;
import org.junit.Assert;
@ -38,13 +39,10 @@ public class RestApiTest {
String httpsCertPath = context.getFilesDir() + "/" + SyncthingService.HTTPS_CERT_FILE;
final CountDownLatch latch = new CountDownLatch(2);
new PollWebGuiAvailableTask(config.getWebGuiUrl(), httpsCertPath, config.getApiKey()) {
@Override
protected void onPostExecute(Void aVoid) {
new PollWebGuiAvailableTask(config.getWebGuiUrl(), httpsCertPath, config.getApiKey(), result -> {
mApi.onWebGuiAvailable();
latch.countDown();
}
}.execute();
}).execute();
mApi = new RestApi(context, config.getWebGuiUrl(), config.getApiKey(),
new RestApi.OnApiAvailableListener() {
@Override
@ -97,8 +95,8 @@ public class RestApiTest {
public void testConvertNotCrashing() {
long[] values = new long[]{-1, 0, 1, 2, 4, 8, 16, 1024, 2^10, 2^15, 2^20, 2^25, 2^30};
for (long l : values) {
Assert.assertNotSame("", RestApi.readableFileSize(InstrumentationRegistry.getTargetContext(), l));
Assert.assertNotSame("", RestApi.readableTransferRate(InstrumentationRegistry.getTargetContext(), l));
Assert.assertNotSame("", Util.readableFileSize(InstrumentationRegistry.getTargetContext(), l));
Assert.assertNotSame("", Util.readableTransferRate(InstrumentationRegistry.getTargetContext(), l));
}
}

View file

@ -1,6 +1,7 @@
package com.nutomic.syncthingandroid.http;
import android.util.Log;
import android.util.Pair;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
@ -26,15 +27,16 @@ public class GetTask extends RestTask<String, Void, String> {
public static final String URI_REPORT = "/rest/svc/report";
public static final String URI_EVENTS = "/rest/events";
public GetTask(URL url, String path, String httpsCertPath, String apiKey) {
super(url, path, httpsCertPath, apiKey);
public GetTask(URL url, String path, String httpsCertPath, String apiKey,
OnSuccessListener<String> listener) {
super(url, path, httpsCertPath, apiKey, listener);
}
/**
* @param params Keys and values for the query string.
*/
@Override
protected String doInBackground(String... params) {
protected Pair<Boolean, String> doInBackground(String... params) {
try {
HttpsURLConnection connection = openConnection(params);
Log.v(TAG, "Calling Rest API at " + connection.getURL());
@ -47,10 +49,10 @@ public class GetTask extends RestTask<String, Void, String> {
}
br.close();
Log.v(TAG, "API call result: " + result);
return result;
return new Pair<>(true, result);
} catch (IOException e) {
Log.w(TAG, "Failed to call rest api", e);
return null;
return new Pair<>(false, null);
}
}

View file

@ -2,6 +2,7 @@ package com.nutomic.syncthingandroid.http;
import android.util.Log;
import android.util.Pair;
import javax.net.ssl.HttpsURLConnection;
import java.io.IOException;
@ -10,7 +11,7 @@ import java.net.URL;
/**
* Polls to load the web interface, until we receive http status 200.
*/
public abstract class PollWebGuiAvailableTask extends RestTask<Void, Void, Void> {
public class PollWebGuiAvailableTask extends RestTask<Void, Void, Void> {
private static final String TAG = "PollWebGuiAvailableTask";
@ -20,12 +21,13 @@ public abstract class PollWebGuiAvailableTask extends RestTask<Void, Void, Void>
*/
private static final long WEB_GUI_POLL_INTERVAL = 100;
public PollWebGuiAvailableTask(URL url, String httpsCertPath, String apiKey) {
super(url, "", httpsCertPath, apiKey);
public PollWebGuiAvailableTask(URL url, String httpsCertPath, String apiKey,
OnSuccessListener<Void> listener) {
super(url, "", httpsCertPath, apiKey, listener);
}
@Override
protected Void doInBackground(Void... aVoid) {
protected Pair<Boolean, Void> doInBackground(Void... aVoid) {
int status = 0;
do {
try {
@ -41,7 +43,7 @@ public abstract class PollWebGuiAvailableTask extends RestTask<Void, Void, Void>
}
}
} while (status != HttpsURLConnection.HTTP_OK);
return null;
return new Pair<>(true, null);
}
}

View file

@ -1,6 +1,7 @@
package com.nutomic.syncthingandroid.http;
import android.util.Log;
import android.util.Pair;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
@ -19,8 +20,9 @@ public class PostTask extends RestTask<String, Void, Boolean> {
public static final String URI_CONFIG = "/rest/system/config";
public static final String URI_SCAN = "/rest/db/scan";
public PostTask(URL url, String path, String httpsCertPath, String apiKey) {
super(url, path, httpsCertPath, apiKey);
public PostTask(URL url, String path, String httpsCertPath, String apiKey,
OnSuccessListener<Boolean> listener) {
super(url, path, httpsCertPath, apiKey, listener);
}
/**
@ -29,7 +31,7 @@ public class PostTask extends RestTask<String, Void, Boolean> {
* For {@link #URI_SCAN}, params[0] must contain the folder, and params[1] the subfolder.
*/
@Override
protected Boolean doInBackground(String... params) {
protected Pair<Boolean, Boolean> doInBackground(String... params) {
try {
HttpsURLConnection connection = (mPath.equals(URI_SCAN))
? openConnection("folder", params[0], "sub", params[1])
@ -50,10 +52,10 @@ public class PostTask extends RestTask<String, Void, Boolean> {
}
br.close();
Log.v(TAG, "API call result: " + result);
return true;
return new Pair<>(true, true);
} catch (IOException e) {
Log.w(TAG, "Failed to call rest api", e);
return false;
return new Pair<>(false, null);
}
}

View file

@ -5,6 +5,8 @@ import android.annotation.SuppressLint;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
import android.util.Pair;
import com.nutomic.syncthingandroid.syncthing.RestApi;
import javax.net.ssl.*;
@ -18,20 +20,28 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
public abstract class RestTask<A, B, C> extends AsyncTask<A, B, C> {
public abstract class RestTask<Params, Progress, Result> extends
AsyncTask<Params, Progress, Pair<Boolean, Result>> {
private static final String TAG = "RestTask";
public interface OnSuccessListener<Result> {
public void onSuccess(Result result);
}
private final URL mUrl;
protected final String mPath;
private final String mHttpsCertPath;
private final String mApiKey;
private final OnSuccessListener<Result> mListener;
public RestTask(URL url, String path, String httpsCertPath, String apiKey) {
public RestTask(URL url, String path, String httpsCertPath, String apiKey,
OnSuccessListener<Result> listener) {
mUrl = url;
mPath = path;
mHttpsCertPath = httpsCertPath;
mApiKey = apiKey;
mListener = listener;
}
protected HttpsURLConnection openConnection(String... params) throws IOException {
@ -50,6 +60,13 @@ public abstract class RestTask<A, B, C> extends AsyncTask<A, B, C> {
return connection;
}
protected void onPostExecute(Pair<Boolean, Result> result) {
if (mListener == null)
return;
mListener.onSuccess(result.second);
}
private SSLSocketFactory getSslSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");

View file

@ -152,29 +152,20 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
@Override
public void onWebGuiAvailable() {
mAvailableCount.set(0);
new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String s) {
if (s == null)
return;
JsonObject json = new JsonParser().parse(s).getAsJsonObject();
new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, result -> {
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
mVersion = json.get("version").getAsString();
Log.i(TAG, "Syncthing version is " + mVersion);
tryIsAvailable();
}
}.execute();
new GetTask(mUrl, GetTask.URI_CONFIG, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String config) {
}).execute();
new GetTask(mUrl, GetTask.URI_CONFIG, mHttpsCertPath, mApiKey, result -> {
try {
mConfig = new JSONObject(config);
mConfig = new JSONObject(result);
tryIsAvailable();
} catch (JSONException e) {
Log.w(TAG, "Failed to parse config", e);
}
}
}.execute();
}).execute();
getSystemInfo(info -> {
mLocalDeviceId = info.myID;
tryIsAvailable();
@ -277,7 +268,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
*/
public void requireRestart(Activity activity) {
if (mRestartPostponed) {
new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey).execute(mConfig.toString());
new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, null)
.execute(mConfig.toString());
} else {
activity.startActivity(new Intent(mContext, RestartActivity.class));
}
@ -290,13 +282,10 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* This executes a restart immediately, and does not show a dialog.
*/
public void updateConfig() {
new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(Boolean b) {
new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, result -> {
mContext.startService(new Intent(mContext, SyncthingService.class)
.setAction(SyncthingService.ACTION_RESTART));
}
}.execute(mConfig.toString());
}).execute(mConfig.toString());
}
@ -348,15 +337,9 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* @param listener Callback invoked when the result is received.
*/
public void getSystemInfo(final OnReceiveSystemInfoListener listener) {
new GetTask(mUrl, GetTask.URI_SYSTEM, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String s) {
if (s == null)
return;
listener.onReceiveSystemInfo(new Gson().fromJson(s, SystemInfo.class));
}
}.execute();
new GetTask(mUrl, GetTask.URI_SYSTEM, mHttpsCertPath, mApiKey, result -> {
listener.onReceiveSystemInfo(new Gson().fromJson(result, SystemInfo.class));
}).execute();
}
/**
@ -365,21 +348,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* @param listener Callback invoked when the result is received.
*/
public void getSystemVersion(final OnReceiveSystemVersionListener listener) {
new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String response) {
if (response == null) {
return;
}
new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, result -> {
try {
SystemVersion systemVersion = new Gson().fromJson(response, SystemVersion.class);
SystemVersion systemVersion = new Gson().fromJson(result, SystemVersion.class);
listener.onReceiveSystemVersion(systemVersion);
} catch (JsonSyntaxException e) {
Log.w(TAG, "Failed to read system info", e);
}
}
}.execute();
}).execute();
}
/**
@ -418,12 +394,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Use the key {@link #TOTAL_STATS} to get connection info for the local device.
*/
public void getConnections(final OnReceiveConnectionsListener listener) {
new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String s) {
if (s == null)
return;
new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, result -> {
Long now = System.currentTimeMillis();
Long timeElapsed = (now - mPreviousConnectionTime) / 1000;
if (timeElapsed < 1) {
@ -432,7 +403,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
}
try {
JSONObject json = new JSONObject(s);
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();
@ -473,8 +444,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
} catch (JSONException e) {
Log.w(TAG, "Failed to parse connections", e);
}
}
}.execute();
}).execute();
}
/**
@ -543,17 +513,11 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Returns status information about the folder with the given id.
*/
public void getModel(final String folderId, final OnReceiveModelListener listener) {
new GetTask(mUrl, GetTask.URI_MODEL, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String s) {
if (s == null)
return;
Model m = new Gson().fromJson(s, Model.class);
new GetTask(mUrl, GetTask.URI_MODEL, mHttpsCertPath, mApiKey, result -> {
Model m = new Gson().fromJson(result, Model.class);
mCachedModelInfo.put(folderId, m);
listener.onReceiveModel(folderId, m);
}
}.execute("folder", folderId);
}).execute("folder", folderId);
}
/**
@ -584,13 +548,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* The OnReceiveEventListeners onEvent method is called for each event.
*/
public final void getEvents(final long sinceId, final long limit, final OnReceiveEventListener listener) {
new GetTask(mUrl, GetTask.URI_EVENTS, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String s) {
if (s == null)
return;
JsonArray jsonEvents = new JsonParser().parse(s).getAsJsonArray();
new GetTask(mUrl, GetTask.URI_EVENTS, mHttpsCertPath, mApiKey, result -> {
JsonArray jsonEvents = new JsonParser().parse(result).getAsJsonArray();
long lastId = 0;
for (int i = 0; i < jsonEvents.size(); i++) {
@ -616,8 +575,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
}
listener.onDone(lastId);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
"since", String.valueOf(sinceId), "limit", String.valueOf(limit));
}
@ -800,22 +758,15 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Normalizes a given device ID.
*/
public void normalizeDeviceId(final String id, final OnDeviceIdNormalizedListener listener) {
new GetTask(mUrl, GetTask.URI_DEVICEID, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (s == null)
return;
JsonObject json = new JsonParser().parse(s).getAsJsonObject();
JsonElement id = json.get("id");
new GetTask(mUrl, GetTask.URI_DEVICEID, mHttpsCertPath, mApiKey, result -> {
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
JsonElement normalizedId = json.get("id");
JsonElement error = json.get("error");
if (id != null)
listener.onDeviceIdNormalized(id.getAsString(), null);
if (normalizedId != null)
listener.onDeviceIdNormalized(normalizedId.getAsString(), null);
if (error != null)
listener.onDeviceIdNormalized(null, error.getAsString());
}
}.execute("id", id);
}).execute("id", id);
}
/**
@ -823,7 +774,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
*/
@Override
public void onFolderFileChange(String folderId, String relativePath) {
new PostTask(mUrl, PostTask.URI_SCAN, mHttpsCertPath, mApiKey).execute(folderId, relativePath);
new PostTask(mUrl, PostTask.URI_SCAN, mHttpsCertPath, mApiKey, null)
.execute(folderId, relativePath);
}
/**
@ -882,19 +834,13 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Returns prettyfied usage report.
*/
public void getUsageReport(final OnReceiveUsageReportListener listener) {
new GetTask(mUrl, GetTask.URI_REPORT, mHttpsCertPath, mApiKey) {
@Override
protected void onPostExecute(String s) {
new GetTask(mUrl, GetTask.URI_REPORT, mHttpsCertPath, mApiKey, result -> {
try {
if (s == null)
return;
listener.onReceiveUsageReport(new JSONObject(s).toString(4));
listener.onReceiveUsageReport(new JSONObject(result).toString(4));
} catch (JSONException e) {
throw new RuntimeException("Failed to prettify usage report", e);
}
}
}.execute();
}).execute();
}
/**

View file

@ -20,6 +20,7 @@ import android.util.Log;
import android.util.Pair;
import android.widget.Toast;
import com.android.PRNGFixes;
import com.google.common.io.Files;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.activities.MainActivity;
@ -27,14 +28,10 @@ import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask;
import com.nutomic.syncthingandroid.model.Folder;
import com.nutomic.syncthingandroid.util.ConfigXml;
import com.nutomic.syncthingandroid.util.FolderObserver;
import com.android.PRNGFixes;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
@ -160,7 +157,7 @@ public class SyncthingService extends Service implements
/**
* True if a stop was requested while syncthing is starting, in that case, perform stop in
* {@link PollWebGuiAvailableTaskImpl}.
* {@link #pollWebGui}.
*/
private boolean mStopScheduled = false;
@ -230,8 +227,7 @@ public class SyncthingService extends Service implements
registerOnWebGuiAvailableListener(mApi);
if (mEventProcessor != null)
registerOnWebGuiAvailableListener(mEventProcessor);
new PollWebGuiAvailableTaskImpl(getWebGuiUrl(), getFilesDir() + "/" + HTTPS_CERT_FILE, mConfig.getApiKey())
.execute();
pollWebGui();
mRunnable = new SyncthingRunnable(this, SyncthingRunnable.Command.main);
new Thread(mRunnable).start();
updateNotification();
@ -480,12 +476,6 @@ public class SyncthingService extends Service implements
mOnApiChangeListeners.remove(listener);
}
private class PollWebGuiAvailableTaskImpl extends PollWebGuiAvailableTask {
public PollWebGuiAvailableTaskImpl(URL url, String httpsCertPath, String apiKey) {
super(url, httpsCertPath, apiKey);
}
/**
* Wait for the web-gui of the native syncthing binary to come online.
*
@ -493,8 +483,9 @@ public class SyncthingService extends Service implements
* to stop the binary in the time while waiting for the GUI to become active. See the comment
* for SyncthingService.onDestroy for details.
*/
@Override
protected void onPostExecute(Void aVoid) {
private void pollWebGui() {
new PollWebGuiAvailableTask(getWebGuiUrl(), getFilesDir() + "/" + HTTPS_CERT_FILE,
mConfig.getApiKey(), result -> {
synchronized (stateLock) {
if (mStopScheduled) {
mCurrentState = State.DISABLED;
@ -512,7 +503,7 @@ public class SyncthingService extends Service implements
listener.onWebGuiAvailable();
}
mOnWebGuiAvailableListeners.clear();
}
}).execute();
}
/**