Leveraging the power of Javascript within an Android WebView to initiate a function call

Background:-

I am attempting to trigger a method called @JavascriptInterface annotated as processVideo() from the loadUrl() function in a webview in order to receive a callback when a user clicks on any video within the webpage.

The solution I have implemented is functioning flawlessly.

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_download);

    webView = findViewById(R.id.web_view_facebook);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setPluginState(WebSettings.PluginState.ON);
    webView.getSettings().setBuiltInZoomControls(true);
    webView.getSettings().setDisplayZoomControls(true);
    webView.getSettings().setUseWideViewPort(true);
    webView.getSettings().setLoadWithOverviewMode(true);
    webView.addJavascriptInterface(this, "Downloader");

    webView.setWebViewClient(new WebViewClient() {

        @Override
        public void onLoadResource(WebView view, String url) {
            webView.loadUrl("javascript:(function prepareVideo() { "
                    + "var el = document.querySelectorAll('div[data-sigil]');"
                    + "for(var i=0;i<el.length; i++)"
                    + "{"
                    + "var sigil = el[i].dataset.sigil;"
                    + "if(sigil.indexOf('inlineVideo') > -1){"
                    + "delete el[i].dataset.sigil;"
                    + "console.log(i);"
                    + "var jsonData = JSON.parse(el[i].dataset.store);"
                    + "el[i].addEventListener('click',function(){Downloader.processVideo(jsonData['src'],jsonData['videoID']);});"
                    + "}" + "}" + "})()");
       }
    });

    webView.loadUrl("https://m.facebook.com");
}

@JavascriptInterface
public void processVideo(final String vidData, final String vidID) {

    try {
        Toast.makeText(this, "Download Started", Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        Toast.makeText(this, "Download Failed: " + e.toString(), Toast.LENGTH_LONG).show();
    }
}}

Now The Issue:-

When I load my custom JavaScript function in loadUrl(), I lose the ability to play videos on click. This is expected since I replaced the default behavior with my own code.

My goal is to allow the video to play when clicked, while still receiving the initial callback that was my primary objective.

What I Have Attempted So Far:-

To enable the video playback on click, I utilized:

addEventListener('click',function(){ 
var video = document.getElementById(jsonData['videoID']); 
video.play(); }

This successfully enables video playback.

However, when I combine this solution with my desired callback like so:

 addEventListener('click',function(){ 
    Downloader.processVideo(jsonData['src'],jsonData['videoID']);
    var video = document.getElementById(jsonData['videoID']); 
    video.play(); }

I encounter an issue where I do not receive the callback in my processVideo().

If I utilize them separately, both functionalities work perfectly within the addEventListener(), but they do not work simultaneously.

Answer №1

The following line of code:

var video = document.getElementById('jsonData['videoID']')
is causing an error due to the excessive use of single quotes within the argument.

You may want to consider replacing it with

var video = document.getElementById(jsonData['videoID'])
.

I trust this suggestion will resolve the issue for you.

Answer №2

I have successfully resolved the issue and below is the complete code snippet:

   webView.setWebViewClient(new WebViewClient()
    {

        @Override
        public void onPageFinished(WebView view, String url)
        {
            //query_string = "" + url;
            // view.loadUrl("javascript:(function() { document.getElementsByTagName('video')[0].play(); })()");
        }

        @Override
        public void onLoadResource(WebView view, String url)
        {
            //  query_string=""+url;

            webView.loadUrl("javascript:(function prepareVideo() " +
                    "{ "
                    + "var el = document.querySelectorAll('div[data-sigil]');"
                    +"var ID;"
                    +"var SRC;"
                    + "for(var i=0;i<el.length; i++)"
                    + "{"
                    + "var sigil = el[i].dataset.sigil;"
                    + "if(sigil.indexOf('inlineVideo') > -1)" +
                    "{"
                    + "delete el[i].dataset.sigil;"
                    + "console.log(i);"
                    + "var jsonData = JSON.parse(el[i].dataset.store);"
                    +"ID=jsonData['videoID'];"
                    +"SRC=jsonData['src'];"

                  //  +"document.getElementsByTagName(\"'+jsonData['videoID']+'\")[0].play();"
                 + "el[i].setAttribute('onClick','FBDownloader.processVideo(\"'+jsonData['src']+'\",\"'+jsonData['videoID']+'\");');"

                    + "}"
                    + "}"

                    + "})()");

        }
    });

JAVA ACTIVITY FUNCTION THAT IS INVOKED FROM JAVASCRIPT WEBVIEW

 public void processVideo(final String vidData, final String vidID)
{

    this.vidData=vidData;
    this.vidID=vidID;
    Get_Download_Permission();

    showtoast("video ID ="+this.vidID);
    webView.loadUrl("https://www.facebook.com/video/embed?video_id="+this.vidID);//193766537709747/");

}

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

Receiving an undefined value of x in AJAX and web API

In the Javascript code, I am attempting to display the listview of reviews when a user clicks on a movie. However, I am encountering errors in the console for the second and third movies - Batman and Avatar - stating that they are not defined. Additionally ...

Struggling to get image properly aligned using touch gestures

Currently, I am struggling with the task of centering my image based on the touch input that will drag it. For example, if the user touches the top right corner of the image, I want the image to automatically move so that its center aligns with that touch ...

Encountering a TypeError in Node Testing using Mocha and Chai: "app.address is not a function" error

I encountered the following error while attempting to test a basic GET Route in my Node application: TypeError: app.address is not a function Although I have checked my app code for any reference to the "address" error, I couldn't find anything that ...

Exploring the Contrast between Cursor and Stream in Node.js

When it comes to extracting large data from a database, there are options like using stream or cursor. I'm curious to find out which option is more efficient and also dive into how cursor and stream work internally in node js. ...

JavaScript - Fetch POST request is being terminated - Windows Error 10053

Seeking help for my JavaScript project course. The function is aborting during the fetch process. Chrome is the browser being used to test the project. It was intermittently "sending" before, but now it's not working at all. Had to run the app in Chro ...

Using jQuery to insert a div class with PHP referenced

My variable stores a color name. Here is an example: <?php $myvar = blueColour; ?> I want to apply this value to the body of an html page using jQuery: <script type="text/javascript"> jQuery(body).addClass("<?php echo $myvar; ?>"); < ...

Is there a way to enhance the sensitivity of the contenteditable area on my website for touch events specifically on stock browsers on Android devices?

It has come to my attention that focusing and editing a contenteditable area on Android stock browsers can be quite challenging. For instance, when visiting the following link http://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_global_contenteditabl ...

Unable to display programmatically created ImageView on Android

Currently, I am working on implementing an ImageView in my project using the following code snippet: RelativeLayout root = (RelativeLayout) ((Activity) GameGuessActivity.context).findViewById(R.id.layout); ImageView img = new ImageView(GameGuessActivity.c ...

Losing the attributes of an object is a common issue when utilizing axios in Vue.js

Recently, while working with axios, I've encountered a puzzling issue where some attributes of objects seem to disappear. Take a look at this snippet of code: <template> <div> <v-message-box :data="mBox" /> <v- ...

Looking for a JavaScript (Angular) event listener to trigger when closing pages and tabs

I am looking for an event that will only work when closing a page or tab, but should not be triggered when the page is refreshed. I am aware of the "beforeunload" event, but it also gets activated on page refresh. Below is the code snippet I am currently ...

using outlines for FontAwesome icons in React Native

I am struggling to use the fontAwesome + icon in the middle of a circle as one item. I have tried placing it inside a circle icon, but it doesn't seem to work properly. import IconFA from 'react-native-vector-icons/FontAwesome'; < ...

What is the best way to fetch a document from a MongoDB database using Mongoose in a Node.js environment

I have been trying to retrieve data from an existing MongoDB model, but all the resources I found demonstrate how to do it with new models. How can I achieve this? const mongoose = require("mongoose"); mongoose.connect("mongodb://localhost/a ...

Android Studio version 3.1.3.2 encountering a Gradle build issue

The search for gradle.jar (com.android.tools.build:gradle:3.1.3) has yielded no results so far. I have looked in various locations, including: Encountering this issue while trying to start a new project on Android Studio version 3.1.3. ...

What advantages come from destructuring in conjunction with require statements?

When utilizing require, is there a performance advantage or disadvantage to importing the entire module versus only importing selected functions? It's my understanding that when using require to import modules (as opposed to using import), compilers ...

What You See Is What You Get editor options

CKEditor is a fantastic HTML editor, but I've encountered an issue when pasting HTML structure and switching to WYSIWYG mode. The editor automatically reformats the HTML structure, causing unexpected changes to the original layout. I'm intereste ...

Sending various data to Toast notifications

I've been working on a small Android development project to enhance my skills in app building. I've implemented 4 radio buttons, each representing a different color. My dilemma lies in capturing the selected values from these radio buttons and di ...

Retrieving array items from PHP with JavaScript: How to access elements in an array

In the midst of a project that involves pulling data from the Google Maps API through a JQuery call, processing it in PHP, and ultimately displaying the results on a map. Progress has been made in fetching elements from the API call into an array and sendi ...

Using React to create a fadeout effect and decrease the length of the photo

Is there a way to create a fade-out effect for each photo card and then shorten the length of the photos following the fade out? I have tried implementing a solution, but it doesn't seem to work when I click on each photo. Any suggestions or insights ...

Various spacings between letters are used for various font styles

After carefully choosing a letter-spacing that enhances the readability of my webpage, I encountered an issue when Arial was used as a backup font for browsers that don't support embedded fonts. The letter-spacing got all messed up and caused overflow ...

Relocate the preview division below the button in the Kartik File Input Widget

There are two input file buttons that allow users to upload an image on each button. Upon selecting an image, a preview of the image will be displayed above the button. The current layout is shown here: https://i.sstatic.net/aLAbo.png When images of diff ...