summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2020-11-20 21:17:52 +0300
committerAndrew Dolgov <[email protected]>2020-11-20 21:17:52 +0300
commit6d1331d54c4bd791806b547e975e794c3e366214 (patch)
tree7158c251a1ed6103312d3482f9e7502bd1630ab6
parentf3947248ab035fc433844a3125d2e441780bb559 (diff)
remove webview-based online/offline detection, use native android way instead (and pass it to webview)
-rw-r--r--org.fox.epube/src/main/java/org/fox/epube/MainActivity.java82
-rw-r--r--org.fox.epube/src/main/java/org/fox/epube/NetworkStateReceiver.java118
2 files changed, 191 insertions, 9 deletions
diff --git a/org.fox.epube/src/main/java/org/fox/epube/MainActivity.java b/org.fox.epube/src/main/java/org/fox/epube/MainActivity.java
index c2e7ac8..78a8090 100644
--- a/org.fox.epube/src/main/java/org/fox/epube/MainActivity.java
+++ b/org.fox.epube/src/main/java/org/fox/epube/MainActivity.java
@@ -2,9 +2,12 @@ package org.fox.epube;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -28,7 +31,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import icepick.State;
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends AppCompatActivity implements NetworkStateReceiver.NetworkStateReceiverListener {
private final String TAG = this.getClass().getSimpleName();
private final String BASE_URL = "https://fakecake.org/books";
@@ -38,6 +41,7 @@ public class MainActivity extends AppCompatActivity {
private ProgressBar m_loadingBar;
private WebView m_web;
private Menu m_menu;
+ private NetworkStateReceiver m_networkStateReceiver;
@State protected boolean m_offlineMode;
@State protected AppPage m_currentPage = AppPage.PAGE_UNKNOWN;
@@ -46,6 +50,9 @@ public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ startNetworkBroadcastReceiver(this);
+
setContentView(R.layout.activity_main);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
@@ -143,6 +150,10 @@ public class MainActivity extends AppCompatActivity {
m_currentPage = page;
+ // not initialized yet
+ if (m_menu == null)
+ return;
+
m_menu.setGroupVisible(R.id.menu_group_pages, false);
m_menu.setGroupVisible(R.id.menu_group_pages_offline, false);
m_menu.setGroupVisible(R.id.menu_group_library, false);
@@ -183,10 +194,18 @@ public class MainActivity extends AppCompatActivity {
}
@Override
+ protected void onPause() {
+ unregisterNetworkBroadcastReceiver(this);
+ super.onPause();
+ }
+
+ @Override
public void onResume() {
- super.onResume();
+ registerNetworkBroadcastReceiver(this);
+
+ onOfflineModeChanged(!isNetworkAvailable());
- m_web.evaluateJavascript("App.appCheckOffline()", null);
+ super.onResume();
}
public void toast(String msg) {
@@ -280,6 +299,17 @@ public class MainActivity extends AppCompatActivity {
m_offlineMode = offline;
onPageSwitched(m_currentPage);
+
+ // this would probably be annoying if network access status changes a lot
+ // never reload if reading a book
+ /* if (m_web != null && m_currentPage != AppPage.PAGE_READER)
+ m_web.evaluateJavascript("window.location.reload();", null); */
+
+ // let's delegate this to webview
+
+ if (m_web != null) {
+ m_web.evaluateJavascript("Reader.onOfflineModeChanged("+ offline +");", null);
+ }
}
class WebAppInterface {
@@ -358,13 +388,14 @@ public class MainActivity extends AppCompatActivity {
}
@JavascriptInterface
+ @Deprecated
public void setOffline(final boolean offline) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- MainActivity.this.onOfflineModeChanged(offline);
- }
- });
+ // No longer used, we don't rely on webview for offline/online switching anymore.
+ }
+
+ @JavascriptInterface
+ public boolean isOnline() {
+ return isNetworkAvailable();
}
@JavascriptInterface
@@ -397,6 +428,14 @@ public class MainActivity extends AppCompatActivity {
}
+ private boolean isNetworkAvailable() {
+ ConnectivityManager manager =
+ (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo networkInfo = manager.getActiveNetworkInfo();
+
+ return networkInfo != null && networkInfo.isConnected();
+ }
+
@Override
public void onSaveInstanceState(Bundle out) {
super.onSaveInstanceState(out);
@@ -413,4 +452,29 @@ public class MainActivity extends AppCompatActivity {
else
super.onBackPressed();
}
+
+ @Override
+ public void networkAvailable() {
+ onOfflineModeChanged(false);
+ }
+
+ @Override
+ public void networkUnavailable() {
+ onOfflineModeChanged(true);
+ }
+
+ public void startNetworkBroadcastReceiver(Context context) {
+ m_networkStateReceiver = new NetworkStateReceiver();
+ m_networkStateReceiver.addListener((NetworkStateReceiver.NetworkStateReceiverListener) context);
+ registerNetworkBroadcastReceiver(context);
+ }
+
+ public void registerNetworkBroadcastReceiver(Context context) {
+ context.registerReceiver(m_networkStateReceiver, new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));
+ }
+
+ public void unregisterNetworkBroadcastReceiver(Context context) {
+ context.unregisterReceiver(m_networkStateReceiver);
+ }
+
} \ No newline at end of file
diff --git a/org.fox.epube/src/main/java/org/fox/epube/NetworkStateReceiver.java b/org.fox.epube/src/main/java/org/fox/epube/NetworkStateReceiver.java
new file mode 100644
index 0000000..4afb7d9
--- /dev/null
+++ b/org.fox.epube/src/main/java/org/fox/epube/NetworkStateReceiver.java
@@ -0,0 +1,118 @@
+package org.fox.epube;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NetworkStateReceiver defines a BroadcastReceiver which allows us to register for system (i.e. network status) or application events.
+ * All registered receivers for an event are notified by the Android runtime once this event happens.
+ * Source: http://stackoverflow.com/questions/6169059/android-event-for-internet-connectivity-state-change
+ */
+public class NetworkStateReceiver extends BroadcastReceiver {
+
+ protected List<NetworkStateReceiverListener> listeners;
+ protected Boolean connected;
+ private String TAG = "NetworkStateReceiver";
+
+ public NetworkStateReceiver() {
+ listeners = new ArrayList<>();
+ connected = null;
+ }
+
+ /**
+ * Called when the BroadcastReceiver is receiving an Intent broadcast (event for which the broadcast receiver has registered occurs).
+ * During this time you can use the other methods on BroadcastReceiver to view/modify the current result values.
+ * NOTE: When it runs on the main thread you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed).
+ * NOTE: You cannot launch a popup dialog in your implementation of onReceive().
+ * @param context Object to access additional information or to start services or activities
+ * @param intent Object with action used to register your receiver. This object contains additional information (e.g. extras)
+ */
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Intent broadcast received");
+ if(intent == null || intent.getExtras() == null)
+ return;
+
+ // Retrieve a ConnectivityManager for handling management of network connections
+ ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ // Details about the currently active default data network. When connected, this network is the default route for outgoing connections
+ NetworkInfo networkInfo = manager.getActiveNetworkInfo();
+
+ /**
+ * NOTE: getActiveNetworkInfo() may return null when there is no default network e.g. Airplane Mode
+ */
+ if(networkInfo != null && networkInfo.getState() == NetworkInfo.State.CONNECTED) {
+ connected = true;
+ } else if(intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) { //Boolean that indicates whether there is a complete lack of connectivity
+ connected = false;
+ }
+
+ notifyStateToAll();
+ } //After the onReceive() of the receiver class has finished, the Android system is allowed to recycle the receiver
+
+ /**
+ * Notify the state to all needed methods
+ */
+ private void notifyStateToAll() {
+ Log.i(TAG, "Notifying state to " + listeners.size() + " listener(s)");
+ for(NetworkStateReceiverListener eachNetworkStateReceiverListener : listeners)
+ notifyState(eachNetworkStateReceiverListener);
+ }
+
+ /**
+ * Notify the network state, triggering interface functions based on the current state
+ * @param networkStateReceiverListener Object which implements the NetworkStateReceiverListener interface
+ */
+ private void notifyState(NetworkStateReceiverListener networkStateReceiverListener) {
+ if(connected == null || networkStateReceiverListener == null)
+ return;
+
+ if(connected == true) {
+ // Triggering function on the interface towards network availability
+ networkStateReceiverListener.networkAvailable();
+ } else {
+ // Triggering function on the interface towards network being unavailable
+ networkStateReceiverListener.networkUnavailable();
+ }
+ }
+
+ /**
+ * Adds a listener to the list so that it will receive connection state change updates
+ * @param networkStateReceiverListener Object which implements the NetworkStateReceiverListener interface
+ */
+ public void addListener(NetworkStateReceiverListener networkStateReceiverListener) {
+ Log.i(TAG, "addListener() - listeners.add(networkStateReceiverListener) + notifyState(networkStateReceiverListener);");
+ listeners.add(networkStateReceiverListener);
+ notifyState(networkStateReceiverListener);
+ }
+
+ /**
+ * Removes listener (when no longer necessary) from the list so that it will no longer receive connection state change updates
+ * @param networkStateReceiverListener Object which implements the NetworkStateReceiverListener interface
+ */
+ public void removeListener(NetworkStateReceiverListener networkStateReceiverListener) {
+ listeners.remove(networkStateReceiverListener);
+ }
+
+ /**
+ * Inner Interface (i.e. to encapsulate behavior in a generic and re-usable way) which handles connection state changes for classes which registered this receiver (Outer class NetworkStateReceiver)
+ * This interface implements the 'Strategy Pattern', where an execution strategy is evaluated and applied internally at runtime
+ */
+ public interface NetworkStateReceiverListener {
+ /**
+ * When the connection state is changed and there is a connection, this method is called
+ */
+ void networkAvailable();
+
+ /**
+ * Connection state is changed and there is not a connection, this method is called
+ */
+ void networkUnavailable();
+ }
+} \ No newline at end of file