I'm new in Android world (as user but also as developer) and my Android App crash when execute myWebView.loadUrl("https://www.google.com")
, but I don't understand why...
The goal is monitoring internet connection while the app is running: If the connection is lost -> loads the error html in the web view If the connection returns active -> reload the web view
Here's my app code:
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dedalos.amb">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".SplashScreen" android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity
public class MainActivity extends AppCompatActivity {
// WEB VIEW
WebView myWebView = null;
// NETWORK MONITORING
Boolean isInternetConnected = false;
ConnectivityManager.NetworkCallback networkCallback = null;
ConnectivityManager connectivityManager = null;
//////////////////// OVERRIDE ////////////////////
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hideSystemUI();
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
if (getToken().equals("")) {
String uniqueID = UUID.randomUUID().toString();
SharedPreferences.Editor editor = prefs.edit();
editor.putString("token", uniqueID);
editor.commit();
}
creaWebView();
configuraWebView();
initNetworkCallback();
}
@Override
public void onResume() {
super.onResume();
if (myWebView == null) {
creaWebView();
configuraWebView();
}
if (networkCallback == null || connectivityManager == null)
initNetworkCallback();
isInternetConnected = (new ConnectionDetector(this).isConnectingToInternet());
startNetworkMonitoring();
if (isInternetConnected) {
caricaWebView();
}
else {
MyWebViewClient.loadError(myWebView);
}
}
@Override
public void onPause() {
super.onPause();
stopNetworkMonitoring();
}
private void creaWebView() {
if (myWebView == null) {
myWebView = (WebView) findViewById(R.id.ambWebViewLayout);
}
}
private void configuraWebView() {
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.setWebViewClient(new MyWebViewClient());
}
private void caricaWebView() {
if (myWebView == null) {
creaWebView();
configuraWebView();
}
myWebView.loadUrl("https://www.google.com");
}
private void initNetworkCallback() {
networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
if (!isInternetConnected) {
isInternetConnected = true;
caricaWebView();
}
}
@Override
public void onLost(Network network) {
if (isInternetConnected) {
isInternetConnected = false;
MyWebViewClient.loadError(myWebView);
}
}
};
connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
}
private void startNetworkMonitoring() {
if (networkCallback == null)
initNetworkCallback();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectivityManager.registerDefaultNetworkCallback(networkCallback);
}
else {
NetworkRequest request = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
connectivityManager.registerNetworkCallback(request, networkCallback);
}
}
private void stopNetworkMonitoring() {
connectivityManager.unregisterNetworkCallback(networkCallback);
}
private String getToken() {
return getPreferences(MODE_PRIVATE).getString("token", "");
}
private void hideSystemUI() {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE
// Set the content to appear under the system bars so that the
// content doesn't resize when the system bars hide and show.
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
// Hide the nav bar and status bar
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
MyWebViewClient
public class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("https://www.google.com")) {
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
else {
return false;
}
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
if (error.getErrorCode() == -2) {
loadError(view);
}
else {
// TODO
}
}
public static void loadError(WebView view) {
String html = "<!DOCTYPE HTML>\n" +
"<html>\n" +
"<head>\n" +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" +
"<title>APP</title>\n" +
"</head>\n" +
"<body style=\"background:#e11020;font-family:Arial,Helvetica;\">\n" +
"<h1 style=\"color:rgba(255,255,255,0.9);text-align:center;padding:120px 20px 20px 20px;font-size:30px;\">No Internet connection</h1>\n" +
"</body>\n" +
"</html>";
view.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null);
}
}
ConnectionDetector
public class ConnectionDetector {
private Context mContext;
public ConnectionDetector(Context context) {
this.mContext = context;
}
/**
* Checking for all possible internet providers
* **/
public boolean isConnectingToInternet() {
ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Network[] networks = connectivityManager.getAllNetworks();
NetworkInfo networkInfo;
for (Network mNetwork : networks) {
networkInfo = connectivityManager.getNetworkInfo(mNetwork);
if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
return true;
}
}
}
else {
if (connectivityManager != null) {
//noinspection deprecation
NetworkInfo[] info = connectivityManager.getAllNetworkInfo();
if (info != null) {
for (NetworkInfo anInfo : info) {
if (anInfo.getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
}
return false;
}
}
Thanks in advance
According to this you need to call all view related methods on UI thread. Just load the url on UI thread like this:
myWebView.post(new Runnable() {
@Override
public void run() {
myWebView.loadUrl("https://www.google.com");
}
});
You also need to load your error html in the same way, like:
view.post(new Runnable() {
@Override
public void run() {
String html = "<!DOCTYPE HTML>\n" +
"<html>\n" +
"<head>\n" +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" +
"<title>APP</title>\n" +
"</head>\n" +
"<body style=\"background:#e11020;font-family:Arial,Helvetica;\">\n" +
"<h1 style=\"color:rgba(255,255,255,0.9);text-align:center;padding:120px 20px 20px 20px;font-size:30px;\">No Internet connection</h1>\n" +
"</body>\n" +
"</html>";
view.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null);
}
});