Stopping Android WebView from navigating

Currently, I am working with Android version 5.0 and the latest update of the WebView component. My goal is to embed a remote website into a WebView without making any modifications to the source code of this website.

Here is the code snippet that I have implemented:

webView.setWebViewClient(new WebViewClient() {
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(url.contains(URL_SERVLET)) {
            //Do nothing 
            Log.d("DEBUG", "load IMAGE");
            //view.stopLoading();
        } else {
            Log.d("DEBUG", "load URL into WebView");
            view.loadUrl(url);
        }
        return true;
    }
    // Called when all page resources loaded
    public void onPageFinished(WebView view, String url) {
        webView.setVisibility(View.VISIBLE);
        splashscreenLayout.setVisibility(View.GONE);
    }
});

The issue arises when I encounter a button on the website's side that triggers another URL to open in a popup using JavaScript. When I click on this button within the Android WebView, the new URL replaces the current one displayed in the WebView. However, my intention is to prevent any action when clicking on this button.

The current implementation successfully prevents loading the additional URL, but it leads to the WebView displaying a blank white screen.

I have attempted calling stopLoading() without success in resolving this problem. Additionally, reloading the WebView via webview.reload() isn't feasible since the remote website generates HTML pages dynamically upon requests.

Efforts to save and restore the state of the WebView have also proved ineffective.

Is there a method to block the transition to a new URL and maintain the WebView's display of the initial content without triggering a reload?

Answer №1

If you're looking for a workaround to prevent page navigation in your WebView, one option is to implement a javascript solution that blocks any attempts to navigate away from the current page.

You can achieve this by incorporating the code snippet provided in this link.

var location = window.document.location;

var preventNavigation = function () {
    var originalHashValue = location.hash;

    window.setTimeout(function () {
        location.hash = 'preventNavigation' + ~~ (9999 * Math.random());
        location.hash = originalHashValue;
    }, 0);
};

window.addEventListener('beforeunload', preventNavigation, false);
window.addEventListener('unload', preventNavigation, false);

Alternatively, rather than blocking navigation entirely, you could simply disable the specific button causing the navigation issue using javascript.

To integrate this script into your WebView, you can refer to the guidance shared in this source.

WebView myWebView = (WebView) findViewById(R.id.webView);
WebSettings webSettings = myWebView.getSettings();

webSettings.setJavaScriptEnabled(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
myWebView.setWebViewClient(new WebViewClient() {
   @Override
   public boolean shouldOverrideUrlLoading(WebView view, String url) {
      return false;
   }

   @Override
   public void onPageFinished(WebView view, String url) {
      super.onPageFinished(view, url);

      injectScriptFile(view, "js/script.js"); // implementation below ...

      // check if the script was successfully loaded
      view.loadUrl("javascript:setTimeout(test(), 500)");
   }

   private void injectScriptFile(WevView view, String scriptFile) {
      InputStream input;
      try {
         input = getAssets().open(scriptFile);
         byte[] buffer = new byte[input.available()];
         input.read(buffer);
         input.close();

         // Encode script byte-array using BASE64 encoding
         String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
         view.loadUrl("javascript:(function() {" +
                      "var parent = document.getElementsByTagName('head').item(0);" +
                      "var script = document.createElement('script');" +
                      "script.type = 'text/javascript';" +
         // Ensure the browser decodes the string as script content
                      "script.innerHTML = window.atob('" + encoded + "');" +
                      "parent.appendChild(script)" +
                      "})()");
      } catch (IOException e) {
         // Handle exceptions
         e.printStackTrace();
      }
   }
});

myWebView.loadUrl("http://www.example.com");

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for saving collections of boolean values in Realm on Android?

Imagine having a dozen booleans to store for each entity, with the expectation of storing up to a few thousand records on any given Android device. For example, a Restaurant object may have booleans such as wifi, valetParking, sitDown, tippingEncouraged, l ...

In Android Studio, the RecyclerView is failing to refresh when onRefresh is triggered

When I try to refresh the items in the recylerview using onRefresh, it does not update the list as expected. Only after closing and reopening the app do I see the updated items list. The onRefresh method seems ineffective for updating the list; is there an ...

Utilize the composite primary key of an Entity within Typeorm for efficient data retrieval

I am working with the following database entities: @Entity() class Team { @PrimaryGeneratedColumn() id: string @PrimaryColumn() teamName: string @OneToMany(() => Player, player => player.team) players: Player[] } @Entity() class Player ...

What is the mechanism for invoking functions defined with the arrow syntax in Angular?

Referencing this code snippet from the tutorial at https://angular.io/tutorial/toh-pt4, specifically within the hero.component.ts file: getHeroes(): void { this.heroService.getHeroes() .subscribe(heroes => this.heroes = heroes); } After analyz ...

Cannot retrieve top 2 values from an object - Angular 6 bug fixing issue

I've been attempting to identify the top 2 values in an object within an array, but I'm encountering issues. Previously, I successfully achieved this with average values that were not within an array, however, when looping through some results an ...

using numerous if statements in ng-class

In my AngularJS application, I have a piece of code that I'm using in a table. I want to apply the 'rare' class only to rows with an index of 0, 1, or 2. In other words, I want to highlight the first three rows differently from the rest. Cu ...

Produce an additional page while remaining on the present one

I have a PHP-based invoice system that displays all customer invoices. I am interested in adding a feature that allows users to print an invoice directly from the list page without navigating away. While I am familiar with window.print() and media="print" ...

Unable to invoke .then when simulating axios call within componentDidMount

I'm currently working on unit testing the componentDidMount method while simulating an Axios call. // src/App.tsx import axios_with_baseUrl from './axios-instance-with-baseUrl'; ... public componentDidMount() { axios_with_baseUrl.get(& ...

node-fetch fails to catch HTTP errors

I am encountering issues with handling fetch exceptions in Node.js What I am anticipating to occur is: An HTTP error happening within my fetch call The CheckResponseStatus function running and throwing an error with the server error status and text This e ...

Force Layout - Labeling and anchoring the nodes

Currently I am creating my own force drag feature using d3js. I stumbled upon a fantastic example here which covers most of what I need: However, I have encountered a problem that I am struggling to solve due to my limited knowledge of d3js. I am attempt ...

In Android Java, the AlertDialog pops up before the thread's methods have completed their execution

At the inception of the app, there is a preliminary check to ensure that tables and data are properly loaded before moving on to the main activity. If they are not loaded correctly, the app resorts to connecting with the server using volley in order to fe ...

Troubleshooting: Why the TableTools basic usage example is not functioning as

After replicating the code from http://datatables.net/release-datatables/extensions/TableTools/examples/simple.html in my Visual Studio project, I organized the files by saving two css files as style1.css and style2.css, along with three js files named sc ...

There seems to be a contradiction in my code - I am returning a Promise but TypeScript is throwing an error saying that the

I currently have a function that retrieves a bot's inventory on the Frontend fetchBotInventory() { this.socket.emit('fetch bot inv'); this.socket.on('bot inv', (botInventory) => { return new Promise((resolve, re ...

Converting Java password encryption technique into a JavaScript version

I'm seeking assistance with converting the Java code for password hashing used in Blynk IoT software into a format suitable for an Express.js application. Any guidance or support would be greatly appreciated! Java code: import java.nio.charset.Stan ...

Issue with Vue mounting causing component to not receive updated values

Below is the Vue main file I'm working with: export default { name: 'app', components: { FormSelector, }, data () { return { headerInfo: { issue: '', mode ...

What is the right way to display accurate value with JSON.parse()?

I'm struggling to correctly parse some JSON code. Instead of just displaying messages, I am getting extra information such as Object and Array. How can I modify the code to only show the messages I need? var txt = ""; var json_string = JSON.stringify ...

Transferring Composite Data Structures from JavaScript to a WCF RESTful Service

Below are the code snippets: 1. The intricate object: [DataContract] public class NewUser { [DataMember(Name = "Email")] public string Email { get; set; } [DataMember(Name = "FirstName")] public string FirstName { get; set; } [DataMem ...

Executing the command causes an error when res.download() is called, resulting in a request

I am currently working on developing an archive that includes various .txt files and then I intend to download this archive. Take a look at the code snippet below: async function archiveAndDownload(res) { const bashCommand = ... const archive = ... ...

Element UI: Triggering an event when the sort caret is clicked

Is it possible to trigger an event when the sorting carets are clicked on a table with sortable columns, ideally with the same parameters as the header-click event? I am able to emit an event by clicking on the header of any sortable column (header-click) ...

What advantages can be gained by substituting a 'single-use' function with a property or object?

Put simply, consider the following code snippet: <script> window['object'] = function(arg) { var myvar = 1; this.object = {}; //add new properties and perform additional tasks this.object.x = arg?arg+1:myvar;//an example in contex ...