Skip to content

Mobile support issues and some solutions #975

Closed
@sangatpedas

Description

Hi guys,

I've been focussing on mobile support for videojs on the most popular Android browsers and find the following issues and some solutions. Mainly this is about support for the videojs controls.

First, in Chrome on Android all seems to work as expected.

The most problems occur with the default Android browser on Jelly Bean, ICS seems to be ok. Basically in the current version the controls of the standard browser in Jelly Bean don't work at all. The reason for this is that Browser generates multiple clicks. So for instance when the play button is clicked it calls the process twice, resulting in a play request followed immediately by a pause request, resulting in nothing really happening. The same goes for all other buttons in the control bar.

I'm sure my solutions won't meet the required quality of the project but I give them anyway so they can be used as temporary work-around by others. This is done by editing the dev version.

First I've defined more booleans so I better know what browser I deal with:

vjs.IS_FIREFOX = (/Firefox/i).test(vjs.USER_AGENT);
vjs.IS_CHROME = (/Chrome/i).test(vjs.USER_AGENT);
vjs.IS_OPERA = ((/Opera/i).test(vjs.USER_AGENT) || (/OPR/i).test(vjs.USER_AGENT));
if (!vjs.IS_FIREFOX && !vjs.IS_CHROME && !vjs.IS_OPERA) //the safari string is also used in other browsers
vjs.IS_SAFARI = (/Safari/i).test(vjs.USER_AGENT);

Next, I define an execution time out based on browser/platform:

var execTimeout=0;
if (vjs.TOUCH_ENABLED && vjs.IS_ANDROID && (vjs.IS_SAFARI || vjs.IS_FIREFOX))
var execTimeout=500; //this is the time in ms that allows for a next execution
var isExecuted=false;

Now basically all onclick function are rewritten like this:

// OnClick - Toggle between play and pause
vjs.PlayToggle.prototype.onClick = function(event){
   if(isExecuted==false || isExecuted==null) {
    isExecuted=true;
    if (this.player_.paused())  {
        this.player_.play();
    } else {
        this.player_.pause();
    }
    setTimeout(function() {isExecuted=false; }, execTimeout);
  }
};

On the fullscreen toggle button more changes are required. Since Safari uses native controls in fullscreen mode, any request from the toggle button is always a request for fullscreen. And since returning from fullscreen with native controls doesn't change the values of the button or the var isFullScreen, no need to change them in the first place.

vjs.FullscreenToggle.prototype.onClick = function(){
  if(isExecuted==false || isExecuted==null) {
    isExecuted=true;
    if (this.player_.isFullScreen==null) this.player_.isFullScreen=false;
    if ((vjs.TOUCH_ENABLED && vjs.IS_ANDROID && vjs.IS_SAFARI) || !this.player_.isFullScreen) {
        this.player_.play();
        this.player_.requestFullScreen();
    }
    else if (!this.player_.isFullScreen) {
        this.player_.requestFullScreen();
        this.el_.children[0].children[0].innerHTML = 'Non-Fullscreen'; // change the button text to "Non-Fullscreen"        
    } else {
        this.player_.cancelFullScreen();
        this.el_.children[0].children[0].innerHTML = 'Fullscreen'; // change the button to "Fullscreen"
    }
    setTimeout(function() {isExecuted=false; }, execTimeout);
  }
};

vjs.MuteToggle.prototype.onClick = function(){
    var _this = this;
    if(isExecuted==false || isExecuted==null) {
        isExecuted=true;
        _this.player_.muted( _this.player_.muted() ? false : true ); 
    }
    setTimeout(function() {isExecuted=false; }, execTimeout);
};

As for the volume slider, I don't see much use for it unless one is a midget with extremely small fingers.

Then there's a problem (in my opinion) once a player is paused. Most mobile browser show a play button in the middle but since vjs.MediaTechController.prototype.onTap only triggers user activity. Since Chrome and Opera show a big native play button I made the following changes:

vjs.MediaTechController.prototype.onTap = function(){
  this.player().userActive(!this.player().userActive());
     if ((this.player().paused()) && (vjs.IS_CHROME || vjs.IS_OPERA))
      this.player().play() ;
};

After having done these changes the following issues remain for Android:

Firefox:
fullscreen doesn't work, remote debugging shows the fullscreen request is ignored due to too many iterations. This corresponds with a test I did with an external button that requests a full change, which works.

Returning from fullscreen changes zoom mode, player is slightly bigger as if double clicked.

Safari (so the official Safari release on Android)
Any fullscreen requests is ignored and stops the video entirely from playing

Opera
First play always switches to fullscreen
returning from fullscreen the native controls show again, even the boolean is set to false.

Thanks for all the work you guys put in and I hope this helps a bit and obviously I hope you guys can help with some of the remaining issues.

Remco

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions