I have created a basic Activity with a WebView. I have added a method in the WebView which loads an error.html page from the asset folder when the WebView receives a HTTP error. I wanted to hide the Share menu item when this error.html page was loaded and so, I moved this to a new Activity.
Now, what's happening is, when there's a connectivity error, the default connectivity error of Android loads first and then the Activity transition takes place. Thus, even though the transition is working fine, users can see the deault Android connectivity error page for a few milliseconds. Is there any way in which I can hide that error page completely as such the users can only see my custom error page.
Here's my MainActivity.java:
package com.ananya.brokenhearts;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
#SuppressWarnings("deprecation")
public class MainActivity extends AppCompatActivity
{
private WebView WebView;
private ProgressBar ProgressBar;
private LinearLayout LinearLayout;
private String currentURL;
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView = findViewById(R.id.webView);
ProgressBar = findViewById(R.id.progressBar);
LinearLayout = findViewById(R.id.layout);
ProgressBar.setMax(100);
WebView.loadUrl("https://www.brokenhearts.ml/index.html");
WebView.getSettings().setJavaScriptEnabled(true);
WebView.getSettings().setUserAgentString("Broken Hearts/1.0");
WebView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
{
LinearLayout.setVisibility(View.VISIBLE);
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url)
{
LinearLayout.setVisibility(View.GONE);
super.onPageFinished(view, url);
currentURL = url;
}
#Override
public void onReceivedError(WebView webview, int i, String s, String s1)
{
Intent intent = new Intent(MainActivity.this, ErrorActivity.class);
startActivity(intent);
finish();
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url2)
{
if (url2.contains("www.brokenhearts.ml"))
{
view.loadUrl(url2);
return false;
} else
{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url2));
startActivity(intent);
return true;
}
}
});
WebView.setWebChromeClient(new WebChromeClient()
{
#Override
public void onProgressChanged(WebView view, int newProgress)
{
super.onProgressChanged(view, newProgress);
ProgressBar.setProgress(newProgress);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.backward:
onBackPressed();
break;
case R.id.forward:
onForwardPressed();
break;
case R.id.refresh:
WebView.reload();
break;
case R.id.share:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT,currentURL);
shareIntent.putExtra(Intent.EXTRA_SUBJECT,"Copied URL");
startActivity(Intent.createChooser(shareIntent,"Share URL"));
break;
case R.id.update:
Intent intent = new Intent(MainActivity.this, UpdateActivity.class);
startActivity(intent);
finish();
break;
case R.id.exit:
new AlertDialog.Builder(this,R.style.AlertDialog)
.setIcon(R.drawable.ic_error_black_24dp)
.setTitle("Are you sure you want to exit?")
.setMessage("Tapping 'Yes' will close the app. Tap 'No' to continue using the app")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
finish();
}
})
.setNegativeButton("No", null)
.show();
break;
}
return super.onOptionsItemSelected(item);
}
private void onForwardPressed()
{
if (WebView.canGoForward())
{
WebView.goForward();
} else
{
Toast.makeText(this, "Can't go further", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBackPressed ()
{
if (WebView.canGoBack())
{
WebView.goBack();
} else
{
new AlertDialog.Builder(this,R.style.AlertDialog)
.setIcon(R.drawable.ic_error_black_24dp)
.setTitle("Are you sure you want to exit?")
.setMessage("Tapping 'Yes' will close the app. Tap 'No' to continue using the app")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
}
Prior to this, I was directly loading the error.html page in the MainActivity itself when there was an error and thus, the default error page wasn't visible. But, I wanted to hide the Share button when error.html page was loaded. I didn't know how to do and I didn't get any response to that question where I had posted it. Thus, I thought of creating a seperate Activity to load the error.html which can let me hide the Share menu icon.
Also, I've tried to add the WebView.loadUrl("file:///android_asset/error.html"); in the same method before that intent hoping that it'll load before the Activity transition, however, that didn't help. I can still see the default Android connectivity error page.
Just to clarify, this is the default error page that I'm talking about: https://i.stack.imgur.com/bMMHh.png
and there's a custom one that I've made that I'm displaying now in the ErrorActivity.java.
What can I do about this?
Hide the webview when an error occured.
#Override
public void onReceivedError(WebView webview, int i, String s, String s1)
{
WebView.setVisibility(View.GONE);**hide the webview when an error occured**
Intent intent = new Intent(MainActivity.this, ErrorActivity.class);
startActivity(intent);
finish();
}
Regarding hiding the share menu icon, you could always use onPrepareOptionsMenu() to hide your share menu if there is any error flag.
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.share).setVisible(!isPageError);
return true;
}
which would require you to have a isPageError boolean set to true in your
#Override
public void onReceivedError(WebView webview, int i, String s, String s1{
isPageError = true;
}
Related
Hello i have java code where progressBar Loads just for first time only.
second time when surfing inner pages it does not shows at all.
package ext.packagename.apk;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
WebView web;
ProgressBar progressBar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.activity_main);
OneSignal.startInit(this).init();
web = (WebView) findViewById(R.id.activity_main_webview);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
//open in webview
//web.setWebViewClient(new myWebClient());
web.getSettings().setJavaScriptEnabled(true);
web.loadUrl("http://example1.com");
// opening in browser instead of WebView
web.setWebViewClient(new MyAppWebViewClient());
}
public class MyAppWebViewClient extends WebViewClient
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(Uri.parse(url).getHost().endsWith("exmaple1.com") || Uri.parse(url).getHost().endsWith("example2.com") || Uri.parse(url).getHost().endsWith("example3.com") ) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
}
}
// To handle "Back" key press event for WebView to go back to previous screen.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
web.goBack();
return true;
} else {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Alert")
.setMessage("exit?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton("No", null)
.show();
}
return super.onKeyDown(keyCode, event);
}
}
Progressbar is loading very fine at first time when main page loads. after that it disappear.
Use
progressBar.setVisibility(View.VISIBLE);
in onPageStarted method
After searching on stackoverflow and testing all codes, my Return goBack(); doesn't work.
I do a WebView,
- URL work
- ZOOM work
But I need to reload last page so this is my code I added :
MainActivity.java
package org.sbynight.app;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.view.KeyEvent;
public class MainActivity extends Activity {
WebView view;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView view = (WebView) this.findViewById(R.id.webView1);
//URL du website - DO NOT CHANGE IT
String url = "http://www.mydomaine.com/";
//loads the WebView completely zoomed out
view.getSettings().setSupportZoom(true);
view.getSettings().setBuiltInZoomControls(true);
//loads WebView Client
view.getSettings().setLoadWithOverviewMode(true);
view.setWebViewClient(new WebViewClient());
view.setWebChromeClient(new WebChromeClient());
view.getSettings().setAppCacheEnabled(false);
//loads URL
view.loadUrl(url);
}
//loads RETURN URL on lastpage
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && this.view.canGoBack()) {
this.view.goBack();
return true;
} else {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Fermer SByNight")
.setMessage("Etes-vous sur de vouloir quittez SByNight?")
.setPositiveButton("Oui", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton("Non", null)
.show();
}
return true;
}
}
PS: I tested with goPressed(); doesn't work too!
SO you want to go back to the last page if there is one to go back to when the back key is pressed?
use the following:
#Override
public void onBackPressed() {
if(this.view.canGoBack())
{
this.view.goBack();
}
else {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Fermer SByNight")
.setMessage("Etes-vous sur de vouloir quittez SByNight?")
.setPositiveButton("Oui", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
finish();
}
})
.setNegativeButton("Non", null)
.show();
}
}
}
I haven't really checked the rest of your code. Just the invokable function.
I'm using a webview in my Android App.
I have 3 buttons 1 for a link to a website one to call a number and one email button.
At first calling my website button worked, http://www.somelink.com .
But my tel: link was not working. So I integrated some code that made my tel: button work.
The problem is that it has made my website or http: button not work?
The html button just does nothing when you click it.
package de.sonae.novolam;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
#SuppressLint("SetJavaScriptEnabled")
public class DFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mainView = (View) inflater.inflate(R.layout.dfragment, container, false);
WebView webView = (WebView) mainView.findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL,
Uri.parse(url));
startActivity(intent);
}
return true;
}
});
webView.loadUrl("file:///android_asset/contact.html");
return mainView;
}
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if( url.startsWith("http:") || url.startsWith("https:") ) {
webView.loadUrl(url);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent );
}
else if (url.startsWith("mailto:")) {
}
// Otherwise allow the OS to handle it
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent );
return true;
}
}
You have two shouldOverrideUrlLoading methods in your code. The only first one is actually called by a WebView. Move code from second shouldOverrideUrlLoading to the first and it will work.
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
return true;
} else if( url.startsWith("http:") || url.startsWith("https:") ) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
} else if (url.startsWith("mailto:")) {
// TODO : handle mail url
return true;
}
return false;
}
});
You need to tell the web view when you handled url loading by your self and when you want do delegate handling on it. Simply return true from shouldOverrideUrlLoading when you handled url loading by your own action. Return false otherwise:
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL,
Uri.parse(url));
startActivity(intent);
return true; // we handled the url loading
}
return false; // let WebView handle this event
}
});
The method shouldOverrideUrlLoading should return true if you want to override (i.e., prevent default handling) or false if you want things to work as normal.
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
return true;
}
return false;
}
I have a Android Application which is basically uses WebView for all interaction..
How can i access (read) Cookies which are created in WebView (if someone logs in) and than store them somewhere, maybe in SharedPreferences, so that later i can use them.
For example.. on quitting the application .. i can say "Thank Mr.XYZ,do u really want to quit"
Here is my code...
package com.example.hellowebview;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class HelloWebView extends Activity {
WebView webview;
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
CookieSyncManager.getInstance().sync();
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new HelloWebViewClient(
));
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl("http://www.mysite.com/mobile");
}
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Thank <<Name Cookie value from Webview >>>,do u really want to quit?")
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
To work with WebView cookies, you can use CookieManager which has some getter and setter methods for you.
http://developer.android.com/reference/android/webkit/CookieManager.html
I was reading over at the Android development website about using reflections. But I'm really not grasping how to use it. I need this Java file to run on a 1.5 (SDK3) device but just ignore the new code and it works fine on a 2.0 (SDK5) or later phone. I have this Activity (posted below) and it's a simple webview. However, I want to have geolocation enabled (even if it is only for 2.0 and later phones), since these APIs weren't introduced until SDK 5, and I would like the webview to be able to, at the very least, to load on a 1.5 phone rather than just crashing. How do I take my code and set it up using reflections?
package com.my.app;
import com.facebook.android.R;
//NEEDS TO BE IGNORED**********************************************************
import android.webkit.GeolocationPermissions;
import android.webkit.GeolocationPermissions.Callback;
//END**************************************************************************
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
//GeolocationPermissionsCallback NEEDS TO BE IGNORED**********************************************************
public class Places extends Activity implements GeolocationPermissions.Callback {
private ProgressDialog progressBar;
public WebView webview;
private static final String TAG = "Main";
String geoWebsiteURL = "http://google.com";
#Override
public void onStart()
{
super.onStart();
CookieSyncManager.getInstance().sync();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new testClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setPluginsEnabled(true);
webview.loadUrl("http://google.com");
progressBar = ProgressDialog.show(Places.this, "", "Loading Page...");
//START GROUP OF CODE THAT NEEDS TO BE IGNORED************************************************************
webview.getSettings().setGeolocationEnabled(true);
GeoClient geo = new GeoClient();
webview.setWebChromeClient(geo);
}
public void invoke(String origin, boolean allow, boolean remember) {
}
final class GeoClient extends WebChromeClient {
#Override
public void onGeolocationPermissionsShowPrompt(String origin,
Callback callback) {
super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false);
}
//END OF CODE THAT NEEDS TO BE IGNORED************************************************
}
private class testClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG, "Processing webview url click...");
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
Log.i(TAG, "Finished loading URL: " +url);
if (progressBar.isShowing()) {
progressBar.dismiss();
}
if (url.startsWith("mailto:") || url.startsWith("geo:") ||
url.startsWith("tel:")) {
Intent intent = new Intent
(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
}
}
//What's here????
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
webview.goBack();
return true;
}
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
Intent z = new Intent(this, Search.class);
startActivity(z);
}
return super.onKeyDown(keyCode, event);
}
public boolean onCreateOptionsMenu (Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected (MenuItem item) {
switch (item.getItemId()) {
case R.id.home:
Intent m = new Intent(this, Home.class);
startActivity(m);
return true;
case R.id.refresh:
webview.reload();
Toast.makeText(this, "Refreshing...", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
public void onStop()
{
super.onStop();
CookieSyncManager.getInstance().sync();
}
}
Step #1: Do not implement GeolocationPermissions.Callback on the activity. Use some other object for GeolocationPermissions.Callback, one implemented in a public Java class that you would not load if you are running on older versions of the OS.
Step #2: Read the answers and comments on the question you asked previously, which covers what you need to know for the rest. Notably, you would make GeoClient be a public Java class in its own file, so you can avoid loading it on older versions of the OS. Personally, I like the Stephen C answer, and I demonstrate its use here.