mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-11-22 20:31:16 +00:00
Improved polling for web gui (fixes #7).
This commit is contained in:
parent
a2a3f189b3
commit
7576e2a47d
2 changed files with 109 additions and 29 deletions
|
@ -8,7 +8,6 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
@ -30,7 +29,7 @@ import java.io.InputStream;
|
||||||
/**
|
/**
|
||||||
* Holds a WebView that shows the web ui of the local syncthing instance.
|
* Holds a WebView that shows the web ui of the local syncthing instance.
|
||||||
*/
|
*/
|
||||||
public class WebGuiActivity extends Activity {
|
public class WebGuiActivity extends Activity implements SyncthingService.OnWebGuiAvailableListener {
|
||||||
|
|
||||||
private static final String TAG = "WebGuiActivity";
|
private static final String TAG = "WebGuiActivity";
|
||||||
|
|
||||||
|
@ -54,6 +53,7 @@ public class WebGuiActivity extends Activity {
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
SyncthingServiceBinder binder = (SyncthingServiceBinder) service;
|
SyncthingServiceBinder binder = (SyncthingServiceBinder) service;
|
||||||
mSyncthingService = binder.getService();
|
mSyncthingService = binder.getService();
|
||||||
|
mSyncthingService.registerOnWebGuiAvailableListener(WebGuiActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName className) {
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
@ -62,32 +62,14 @@ public class WebGuiActivity extends Activity {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retries loading every second until the web UI becomes available.
|
* Hides the loading screen and shows the WebView once it is fully loaded.
|
||||||
*/
|
*/
|
||||||
private WebViewClient mWebViewClient = new WebViewClient() {
|
private WebViewClient mWebViewClient = new WebViewClient() {
|
||||||
|
|
||||||
private int mError = 0;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceivedError(WebView view, int errorCode, String description,
|
|
||||||
String failingUrl) {
|
|
||||||
mError = errorCode;
|
|
||||||
new Handler().postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mError = 0;
|
|
||||||
mWebView.loadUrl(SyncthingService.SYNCTHING_URL);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
if (mError == 0) {
|
mWebView.setVisibility(View.VISIBLE);
|
||||||
mWebView.setVisibility(View.VISIBLE);
|
mLoadingView.setVisibility(View.GONE);
|
||||||
mLoadingView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,11 +82,6 @@ public class WebGuiActivity extends Activity {
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
getApplicationContext().startService(
|
|
||||||
new Intent(this, SyncthingService.class));
|
|
||||||
getApplicationContext().bindService(
|
|
||||||
new Intent(this, SyncthingService.class),
|
|
||||||
mSyncthingServiceConnection, Context.BIND_AUTO_CREATE);
|
|
||||||
|
|
||||||
setContentView(R.layout.main);
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
|
@ -115,7 +92,6 @@ public class WebGuiActivity extends Activity {
|
||||||
mWebView = (WebView) findViewById(R.id.webview);
|
mWebView = (WebView) findViewById(R.id.webview);
|
||||||
mWebView.getSettings().setJavaScriptEnabled(true);
|
mWebView.getSettings().setJavaScriptEnabled(true);
|
||||||
mWebView.setWebViewClient(mWebViewClient);
|
mWebView.setWebViewClient(mWebViewClient);
|
||||||
mWebView.loadUrl(SyncthingService.SYNCTHING_URL);
|
|
||||||
|
|
||||||
// Handle first start.
|
// Handle first start.
|
||||||
File config = new File(getApplicationInfo().dataDir, CONFIG_FILE);
|
File config = new File(getApplicationInfo().dataDir, CONFIG_FILE);
|
||||||
|
@ -130,8 +106,23 @@ public class WebGuiActivity extends Activity {
|
||||||
.setNeutralButton(android.R.string.ok, null)
|
.setNeutralButton(android.R.string.ok, null)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getApplicationContext().startService(
|
||||||
|
new Intent(this, SyncthingService.class));
|
||||||
|
getApplicationContext().bindService(
|
||||||
|
new Intent(this, SyncthingService.class),
|
||||||
|
mSyncthingServiceConnection, Context.BIND_AUTO_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads and shows WebView, hides loading view.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onWebGuiAvailable() {
|
||||||
|
mWebView.loadUrl(SyncthingService.SYNCTHING_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -11,10 +12,21 @@ import android.util.Log;
|
||||||
import com.nutomic.syncthingandroid.R;
|
import com.nutomic.syncthingandroid.R;
|
||||||
import com.nutomic.syncthingandroid.WebGuiActivity;
|
import com.nutomic.syncthingandroid.WebGuiActivity;
|
||||||
|
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpHead;
|
||||||
|
import org.apache.http.conn.HttpHostConnectException;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the native syncthing instance and provides an API to access it.
|
* Holds the native syncthing instance and provides an API to access it.
|
||||||
|
@ -35,8 +47,26 @@ public class SyncthingService extends Service {
|
||||||
*/
|
*/
|
||||||
public static final String SYNCTHING_URL = "http://127.0.0.1:8080";
|
public static final String SYNCTHING_URL = "http://127.0.0.1:8080";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interval in ms, at which connections to the web gui are performed on first start
|
||||||
|
* to find out if it's online.
|
||||||
|
*/
|
||||||
|
private static final long WEB_GUI_POLL_INTERVAL = 100;
|
||||||
|
|
||||||
private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this);
|
private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when the Syncthing web interface becomes first available after service start.
|
||||||
|
*/
|
||||||
|
public interface OnWebGuiAvailableListener {
|
||||||
|
public void onWebGuiAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private LinkedList<OnWebGuiAvailableListener> mOnWebGuiAvailableListeners =
|
||||||
|
new LinkedList<OnWebGuiAvailableListener>();
|
||||||
|
|
||||||
|
private boolean mIsWebGuiAvailable = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
|
@ -100,6 +130,48 @@ public class SyncthingService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polls SYNCTHING_URL until it returns HTTP status OK, then calls all listeners
|
||||||
|
* in mOnWebGuiAvailableListeners and clears it.
|
||||||
|
*/
|
||||||
|
private class PollWebGuiAvailableTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... voids) {
|
||||||
|
int status = 0;
|
||||||
|
HttpClient httpclient = new DefaultHttpClient();
|
||||||
|
HttpHead head = new HttpHead(SYNCTHING_URL);
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
Thread.sleep(WEB_GUI_POLL_INTERVAL);
|
||||||
|
HttpResponse response = httpclient.execute(head);
|
||||||
|
// NOTE: status is not really needed, as HttpHostConnectException is thrown
|
||||||
|
// earlier.
|
||||||
|
status = response.getStatusLine().getStatusCode();
|
||||||
|
}
|
||||||
|
catch (HttpHostConnectException e) {
|
||||||
|
// We catch this in every call, as long as the service is not online,
|
||||||
|
// so we ignore and continue.
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Log.d(TAG, "Failed to poll for web interface", e);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {
|
||||||
|
Log.d(TAG, "Failed to poll for web interface", e);
|
||||||
|
}
|
||||||
|
} while(status != HttpStatus.SC_OK);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
mIsWebGuiAvailable = true;
|
||||||
|
for (OnWebGuiAvailableListener listener : mOnWebGuiAvailableListeners) {
|
||||||
|
listener.onWebGuiAvailable();
|
||||||
|
}
|
||||||
|
mOnWebGuiAvailableListeners.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates notification, starts native binary.
|
* Creates notification, starts native binary.
|
||||||
|
@ -118,6 +190,8 @@ public class SyncthingService extends Service {
|
||||||
startForeground(NOTIFICATION_ID, n);
|
startForeground(NOTIFICATION_ID, n);
|
||||||
|
|
||||||
new Thread(new NativeSyncthingRunnable()).start();
|
new Thread(new NativeSyncthingRunnable()).start();
|
||||||
|
|
||||||
|
new PollWebGuiAvailableTask().execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,4 +208,19 @@ public class SyncthingService extends Service {
|
||||||
new PostTask().execute(PostTask.URI_SHUTDOWN);
|
new PostTask().execute(PostTask.URI_SHUTDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a listener for the web gui becoming available..
|
||||||
|
*
|
||||||
|
* If the web gui is already available, listener will be called immediately.
|
||||||
|
* Listeners are unregistered automatically after being called.
|
||||||
|
*/
|
||||||
|
public void registerOnWebGuiAvailableListener(OnWebGuiAvailableListener listener) {
|
||||||
|
if (mIsWebGuiAvailable) {
|
||||||
|
listener.onWebGuiAvailable();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mOnWebGuiAvailableListeners.addLast(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue