A.Sharma
A.Sharma

Reputation: 2799

Gluon Mobile and JW Video Player

What is the best way to integrate Gluon Mobile with JW Video Player? It's a pretty popular plugin. I know Xamarin provides ways to integrate it, but I was wondering how I could do so with Gluon Mobile?

I have spent the last couple of hours trying to import using Maven:

https://developer.jwplayer.com/sdk/android/docs/developer-guide/getting-started/library-project-setup/

This leads to the following files present in dependencies:

Compile (Main): Shows .aar file

Compile (Android): Shows .aar file AND .jar file

I cannot import the JW Video Package however even though the dependencies are there. This is my gradle file:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.2.0'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases' 
    }
    maven {
            url 'https://mvn.jwplayer.com/content/repositories/releases/'
    }
}

mainClassName = 'com.konfamde.Konfamde'

dependencies {
    compile 'com.gluonhq:charm:4.3.0' 
    androidRuntime 'com.gluonhq:charm-down-core-android:3.1.0'
    iosRuntime 'com.gluonhq:charm-down-core-ios:3.1.0'
    desktopRuntime 'com.gluonhq:charm-down-plugin-display-desktop:3.1.0'
    androidCompile 'com.longtailvideo.jwplayer:jwplayer-core:+'
    desktopCompile 'com.longtailvideo.jwplayer:jwplayer-core:+'
    compile 'com.longtailvideo.jwplayer:jwplayer-core:+'
}

jfxmobile {
    downConfig {
        version = '3.2.0'
        // Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
        plugins 'barcode-scan', 'connectivity', 'display', 'lifecycle', 'position', 'statusbar', 'storage'
    }
    android {
        androidSdk = 'C:/Users/wjlax/AppData/Local/Android/sdk'
        compileSdkVersion = '23'
        manifest = 'src/android/AndroidManifest.xml'
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = [
                'com.konfamde.**.*',
                'com.gluonhq.**.*',
                'javax.annotations.**.*',
                'javax.inject.**.*',
                'javax.json.**.*',
                'org.glassfish.json.**.*'
        ]
    }
}

Somewhat of a Solution

I don't know if this will really work for mobile, but I created a WebView and passed an iframe URL to it. The video is showing on my desktop successfully as I test. Does porting WebView objects to iOS and Android work with Gluon Mobile?

Here is my code for the webengine:

WebView web = (WebView)view.lookup("#webber");
WebEngine engine = web.getEngine();
engine.load("https://content.jwplatform.com/players/VIDEOLINKHIDDEN.HTML");

Would this port effectively to iOS and Android? Also note that I need to figure out a way for the Gluon mobile application to detect when the video is done playing. I know that the WebEngine can call Java code from Javascript, and I have the following ideas to make it work, but I am not sure:

  1. Get the length of the video in Javascript and create a timer with another Thread in Java.
  2. Somehow get the on complete callback from the JW Player API to link to a JSObject in Java.
  3. Create my own REST calls to a webpage on the server running PHP, and handle the backend code there. Thus, handle the video entirely with Javascript (including AJAX calls to a separate URL) and just use the WebEngine to show what is happening.

Upvotes: 1

Views: 214

Answers (1)

A.Sharma
A.Sharma

Reputation: 2799

OK so I found a workaround, but I am unsure if this will resolve it as I have yet to try to port the app to mobile yet. I utilized a WebView/WebEngine with a callback for the end of the video.

I am unsure how well supported JS callbacks are in Gluon Mobile so I hope this works for mobile. It works for my desktop now though:

Note that the URL passed into the getHTML method is the URL of the video on the JWPlayer website

public WebView getWebEngine() {
    WebView web = new WebView();
    engine = web.getEngine();
    engine.loadContent(this.getHTML(this.video.getVideo()));
    return web;
}

public String getHTML(String videoUrl) {
    String videoElement = "<video width='320' height='240' id='myVideo' autoplay='true'>"
            + "<source src='" + videoUrl + "'/>"
            + "Your browser does not support the video tag."
            + "</video>";
    return "<html><body style='font-family:sans-serif';>" + videoElement + "</body></html>";
}

private void addEndingListener() {

    Document doc = engine.getDocument();

    Element el = (Element) doc.getElementsByTagName("video").item(0);

    EventListener listener = (Event evt) -> {
        this.reviewPane.setVisible(true);
    };

    if (el != null) {
        ((EventTarget) el).addEventListener("ended", listener, false);
    }

}

public void loadEngine(VBox container) {
    runLoop();
    this.reviewPane = getReviewPaneInstance();
    this.reviewPane.setVisible(false);
    container.getChildren().add(this.reviewPane);

    this.engine.reload();
    this.engine.getLoadWorker().stateProperty().addListener(
            new ChangeListener<State>() {
        @Override
        public void changed(ObservableValue ov, State oldState, State newState) {
            if (newState == Worker.State.SUCCEEDED) {
                addEndingListener();
            }
        }
    });
}

Update

So Javascript to Java will not work. However, I was able to solve this by adding Javascript directly into the web engine to handle everything that I need. The "onended" and "onseeking" inline event listeners seem to work (even when ported to the mobile devices):

public String getHTML(String videoUrl) {
        String onSeek = "document.getElementById(\"container\").innerHTML = \"No fast forwarding allowed! Try again.\"";
        String onEnd = "document.getElementById(\"container\").innerHTML =" + this.codeGen;

        String videoElement = "<div id='container'><video id='video' width='320' height='240' id='myVideo' controls onseeking='" + onSeek + "' onended='" + onEnd + "'>"
                + "<source src='" + videoUrl + "'/>"
                + "Your browser does not support the video tag."
                + "</video></div>";
        return "<html><body style='font-family:sans-serif;'>" + videoElement + "</body></html>";
    }

With this, I have been able to output a token on video completion that the user has to enter to state that the video has been watched. I have also prevented the user from seeking as it completely removes the video element and outputs a message on seeking.

Upvotes: 0

Related Questions