WebView et HTML5 <video>

122

Je suis en train de créer une application cheapo qui, entre autres, "encadre" certains de nos sites Web ... Assez simple avec le WebViewClient. jusqu'à ce que je frappe la vidéo.

La vidéo est réalisée sous forme d' HTML5 éléments, et ceux-ci fonctionnent très bien sur Chrome, les iPhones, et maintenant que nous avons résolu les problèmes d'encodage, cela fonctionne très bien Androiddans le navigateur natif.

Maintenant, le hic: WebViewje n'aime pas ça. Du tout. Je peux cliquer sur l'image de l'affiche et rien ne se passe.

En googlant, j'ai trouvé cela qui est proche, mais qui semble être basé sur un «lien» (comme dans un href ...) au lieu d'un élément vidéo. (onDownloadListener ne semble pas être appelé sur les éléments vidéo ...)

Je vois également des références à la substitution de onShowCustomView, mais cela ne semble pas être appelé sur les éléments vidéo ... ni shouldOverrideUrlLoading ..

Je préférerais ne pas "extraire du xml du serveur, le reformater dans l'application" .. en gardant la mise en page de l'histoire sur le serveur, je peux contrôler un peu mieux le contenu sans forcer les gens à continuer à mettre à jour une application. Donc, si je peux convaincre WebView de gérer des balises comme le navigateur natif, ce serait mieux.

Il me manque clairement quelque chose d'évident ... mais je n'ai aucune idée de quoi.

Brian Moore
la source
Dans le même esprit, je recherche un lecteur HTML5 pour mon site Web. Que dois-je utiliser?
Wolfpack'08
1
Ma réponse ici: stackoverflow.com/a/16179544/423171
cprcrack
1
Rien n'a fonctionné alors j'ai regardé VideoEnabledWebViewici stackoverflow.com/questions/15768837/…
EpicPandaForce

Réponses:

92

Je réponds à ce sujet au cas où quelqu'un le lirait et serait intéressé par le résultat. Il est possible de visualiser un élément vidéo (tag video html5) dans une WebView, mais je dois dire que j'ai dû m'en occuper pendant quelques jours. Voici les étapes que j'ai dû suivre jusqu'à présent:

-Trouver une vidéo correctement encodée

-Lors de l'initialisation de WebView, définissez le JavaScript, les plug-ins WebViewClient et WebChromeClient.

url = nouvelle chaîne ("http://broken-links.com/tests/video/"); 
mWebView = (WebView) findViewById (R.id.webview);
mWebView.setWebChromeClient (chromeClient);
mWebView.setWebViewClient (wvClient);
mWebView.getSettings (). setJavaScriptEnabled (true);
mWebView.getSettings (). setPluginState (PluginState.ON);
mWebView.loadUrl (url);

-Gérer le onShowCustomView dans l'objet WebChromeClient.

@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
    super.onShowCustomView(view, callback);
    if (view instanceof FrameLayout){
        FrameLayout frame = (FrameLayout) view;
        if (frame.getFocusedChild() instanceof VideoView){
            VideoView video = (VideoView) frame.getFocusedChild();
            frame.removeView(video);
            a.setContentView(video);
            video.setOnCompletionListener(this);
            video.setOnErrorListener(this);
            video.start();
        }
    }
}

-Gérer les événements onCompletion et onError pour la vidéo, afin de revenir à la vue Web.

public void onCompletion(MediaPlayer mp) {
    Log.d(TAG, "Video completo");
    a.setContentView(R.layout.main);
    WebView wb = (WebView) a.findViewById(R.id.webview);
    a.initWebView();
}

Mais maintenant, je devrais dire qu'il reste un problème important. Je ne peux y jouer qu'une seule fois. La deuxième fois que je clique sur le répartiteur vidéo (soit l'affiche, soit un bouton de lecture), il ne fait rien.

Je voudrais également que la vidéo soit lue à l'intérieur du cadre WebView, au lieu d'ouvrir la fenêtre du lecteur multimédia, mais c'est pour moi un problème secondaire.

J'espère que cela aide quelqu'un, et je remercie également tout commentaire ou suggestion.

Saludos, terrícolas.

mdelolmo
la source
je ne lance aucun résultat, mon écran est noir. Je veux savoir si cela a besoin de la tête. mon code est trop long à poser ici, pouvez-vous me donner un moyen de contact ou ouvrir un autre sujet.
pengwang
Êtes-vous tout à fait sûr qu'il ne s'agit pas d'un problème d'encodage? Essayez avec l'URL que j'ai publiée. De toute évidence, il doit fonctionner avec le navigateur natif
mdelolmo
46
qu'est-ce que "a"? comme cette activité serait-ce?
Collin Price
1
@Collin Price a est une instance de l'activité hébergeant la webview. @desgraci, je peux le fournir, mais il n'y a pas grand-chose à part ça. Faites une classe étendre WebChromeClientet remplacer les méthodes correspondantes dont vous avez besoin. Si vous insistez, je pourrai télécharger le reste de la classe plus tard lorsque je rentrerai à la maison.
mdelolmo du
6
Ne fonctionne pas sur ICS car getFocusedChild () n'est pas un VideoView, mais un HTML5VFullScreen $ SurfaceVideoView. Une idée sur comment faire sur ICS? (voir stackoverflow.com/questions/13540654/…
Pascal
61

Après de longues recherches, j'ai fait fonctionner cette chose. Voir le code suivant:

Test.java

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;

public class Test extends Activity {

    HTML5WebView mWebView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mWebView = new HTML5WebView(this);

        if (savedInstanceState != null) {
            mWebView.restoreState(savedInstanceState);
        } else {    
            mWebView.loadUrl("http://192.168.1.18/xxxxxxxxxxxxxxxx/");
        }

        setContentView(mWebView.getLayout());
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mWebView.saveState(outState);
    }

    @Override
    public void onStop() {
        super.onStop();
        mWebView.stopLoading();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (mWebView.inCustomView()) {
                mWebView.hideCustomView();
            //  mWebView.goBack();
                //mWebView.goBack();
                return true;
            }

        }
        return super.onKeyDown(keyCode, event);
    }
}

HTML% VIDEO.java

package com.ivz.idemandtest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;

public class HTML5WebView extends WebView {

    private Context                             mContext;
    private MyWebChromeClient                   mWebChromeClient;
    private View                                mCustomView;
    private FrameLayout                         mCustomViewContainer;
    private WebChromeClient.CustomViewCallback  mCustomViewCallback;

    private FrameLayout                         mContentView;
    private FrameLayout                         mBrowserFrameLayout;
    private FrameLayout                         mLayout;

    static final String LOGTAG = "HTML5WebView";

    private void init(Context context) {
        mContext = context;     
        Activity a = (Activity) mContext;

        mLayout = new FrameLayout(context);

        mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(a).inflate(R.layout.custom_screen, null);
        mContentView = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.main_content);
        mCustomViewContainer = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.fullscreen_custom_content);

        mLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);

        // Configure the webview
        WebSettings s = getSettings();
        s.setBuiltInZoomControls(true);
        s.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        s.setUseWideViewPort(true);
        s.setLoadWithOverviewMode(true);
      //  s.setSavePassword(true);
        s.setSaveFormData(true);
        s.setJavaScriptEnabled(true);
        mWebChromeClient = new MyWebChromeClient();
        setWebChromeClient(mWebChromeClient);

        setWebViewClient(new WebViewClient());

setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        // enable navigator.geolocation 
       // s.setGeolocationEnabled(true);
       // s.setGeolocationDatabasePath("/data/data/org.itri.html5webview/databases/");

        // enable Web Storage: localStorage, sessionStorage
        s.setDomStorageEnabled(true);

        mContentView.addView(this);
    }

    public HTML5WebView(Context context) {
        super(context);
        init(context);
    }

    public HTML5WebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public HTML5WebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public FrameLayout getLayout() {
        return mLayout;
    }

    public boolean inCustomView() {
        return (mCustomView != null);
    }

    public void hideCustomView() {
        mWebChromeClient.onHideCustomView();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if ((mCustomView == null) && canGoBack()){
                goBack();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    private class MyWebChromeClient extends WebChromeClient {
        private Bitmap      mDefaultVideoPoster;
        private View        mVideoProgressView;

        @Override
        public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)
        {
            //Log.i(LOGTAG, "here in on ShowCustomView");
            HTML5WebView.this.setVisibility(View.GONE);

            // if a view already exists then immediately terminate the new one
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }

            mCustomViewContainer.addView(view);
            mCustomView = view;
            mCustomViewCallback = callback;
            mCustomViewContainer.setVisibility(View.VISIBLE);
        }

        @Override
        public void onHideCustomView() {
            System.out.println("customview hideeeeeeeeeeeeeeeeeeeeeeeeeee");
            if (mCustomView == null)
                return;        

            // Hide the custom view.
            mCustomView.setVisibility(View.GONE);

            // Remove the custom view from its container.
            mCustomViewContainer.removeView(mCustomView);
            mCustomView = null;
            mCustomViewContainer.setVisibility(View.GONE);
            mCustomViewCallback.onCustomViewHidden();

            HTML5WebView.this.setVisibility(View.VISIBLE);
            HTML5WebView.this.goBack();
            //Log.i(LOGTAG, "set it to webVew");
        }


        @Override
        public View getVideoLoadingProgressView() {
            //Log.i(LOGTAG, "here in on getVideoLoadingPregressView");

            if (mVideoProgressView == null) {
                LayoutInflater inflater = LayoutInflater.from(mContext);
                mVideoProgressView = inflater.inflate(R.layout.video_loading_progress, null);
            }
            return mVideoProgressView; 
        }

         @Override
         public void onReceivedTitle(WebView view, String title) {
            ((Activity) mContext).setTitle(title);
         }

         @Override
         public void onProgressChanged(WebView view, int newProgress) {
             ((Activity) mContext).getWindow().setFeatureInt(Window.FEATURE_PROGRESS, newProgress*100);
         }

         @Override
         public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
             callback.invoke(origin, true, false);
         }
    }


    static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
        new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}

custom_screen.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android">
    <FrameLayout android:id="@+id/fullscreen_custom_content"
        android:visibility="gone"
        android:background="@color/black"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />
    <LinearLayout android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout android:id="@+id/error_console"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />

        <FrameLayout android:id="@+id/main_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
        />
    </LinearLayout>
</FrameLayout>

video_loading_progress.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/progress_indicator"
         android:orientation="vertical"
         android:layout_centerInParent="true"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content">

       <ProgressBar android:id="@android:id/progress"
           style="?android:attr/progressBarStyleLarge"
           android:layout_gravity="center"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" />

       <TextView android:paddingTop="5dip"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center"
           android:text="@string/loading_video" android:textSize="14sp"
           android:textColor="?android:attr/textColorPrimary" />
 </LinearLayout>

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/assets/res/any/http_authentication_colors.xml
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/
-->
<!-- FIXME: Change the name of this file!  It is now being used generically
    for the browser -->
<resources>
    <color name="username_text">#ffffffff</color>
    <color name="username_edit">#ff000000</color>

    <color name="password_text">#ffffffff</color>
    <color name="password_edit">#ff000000</color>

    <color name="ssl_text_label">#ffffffff</color>
    <color name="ssl_text_value">#ffffffff</color>

    <color name="white">#ffffffff</color>
    <color name="black">#ff000000</color>



    <color name="geolocation_permissions_prompt_background">#ffdddddd</color>
</resources>

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Test"
                  android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
            android:configChanges="orientation|keyboardHidden|keyboard">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>  
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
</manifest>

Attendre le reste des choses que vous pouvez comprendre.

surendra
la source
7
Celui-ci devrait être la réponse acceptée. Surendra et Malenkiy, vous avez tous les deux sauvé ma raison. A très bien fonctionné pour moi.
George Baker
Je suis d'accord avec George. C'est exactement comment le navigateur natif Android fonctionne avec VideoView. Il semble que ce soit le même code qu'ici code.google.com/p/html5webview . Cela fonctionne très bien pour toutes les versions d'Android (j'ai testé sur Android 2.2 et supérieur). Une seule chose que je voulais remarquer, vous devez garder à l'esprit que si vous changez le SDK cible sur quelque chose au-dessus de 13, l'activité de votre sera recréée lors du changement d'orientation. Pour éviter cela, ajoutez screenSize à android: configChanges (mais dans ce cas, vous devrez utiliser min sdk <13) ou utiliser l'ancien SDK cible (alors vous pouvez garder android: configChanges)
Yuriy Ashaev
2
Cela me donne un écran blanc vide sur le Nexus 7 (Android 4.1). Une idée de comment résoudre ce problème?
Sahil
Le bouton arrière n'arrête pas la vidéo et l'audio est toujours audible, une idée de comment résoudre ce problème?
CONvid19
C'est ce que je recherchais exactement comme le flux du navigateur natif. Merci à Ton Surendra et Malenkiy.
Abhilash
33

La réponse de mdelolmo a été incroyablement utile, mais comme il l'a dit, la vidéo ne joue qu'une seule fois et vous ne pouvez pas l'ouvrir à nouveau.

J'ai examiné cela un peu et voici ce que j'ai trouvé, au cas où des voyageurs WebView fatigués comme moi tomberaient sur ce post à l'avenir.

Tout d' abord, je regardais le VideoView et MediaPlayer la documentation de et a obtenu un meilleur sens de la façon dont les travaux. Je les recommande fortement.

Ensuite, j'ai regardé le code source pour voir comment le navigateur Android le fait. Faites une recherche de page et regardez comment ils gèrent onShowCustomView(). Ils gardent une référence à la CustomViewCallbacket à la vue personnalisée.

Avec tout cela, et avec la réponse de mdelolmo à l'esprit, lorsque vous avez terminé avec la vidéo, tout ce que vous avez à faire est de deux choses. Tout d'abord, sur le VideoViewauquel vous avez enregistré une référence, appelez stopPlayback()qui libérera le MediaPlayerpour être utilisé plus tard ailleurs. Vous pouvez le voir dans le code source de VideoView . Deuxièmement, CustomViewCallbackvous avez enregistré une référence à appelerCustomViewCallback.onCustomViewHidden() .

Après avoir fait ces deux choses, vous pouvez cliquer sur la même vidéo ou sur n'importe quelle autre vidéo et elle s'ouvrira comme avant. Pas besoin de redémarrer l'intégralité de WebView.

J'espère que cela pourra aider.

cotonBallPaws
la source
En fait, je l'ai un peu résolu aussi, je ne me souvenais tout simplement pas de poster la solution (honte à moi). Tout comme vous, j'ai dû jeter un coup d'œil au code du navigateur Android, et bien, pas grand chose à ajouter, j'ai utilisé l'écouteur onCompletion pour arrêter le lecteur à la place et j'ai dû définir la visibilité plusieurs fois, mais j'achèterais votre solution. Cordialement!
mdelolmo
1
Google Code Search a été retiré, je pense que cette version de BrowserActivity.java (de Froyo) correspond à peu près à celle décrite ici: github.com/android/platform_packages_apps_browser/blob/…
michiakig
Le code lié de @ spacemanki ne contient aucune mention de VideoView dans l'ensemble du référentiel. Je suppose que BrowserActivity le fait différemment maintenant. Je suis même retourné à la version Eclair. Impossible de trouver une utilisation.
mxcl
Le problème que j'ai avec tout cela est que ce que je récupère de frame.getFocusedChild (); est un HTml5VideoView au lieu d'un ViewView et donc rien de tout cela ne fonctionne pour moi et ne peut pas passer en plein écran: (Je suis sous Android 4.1.2.
Gonan
1
Ce qui a finalement fait cela pour moi a été d'ajouter: @Override public void onStop () {super.onStop (); mWebView.destroy (); } à l'activité ... le webview.destroy () était crucial
MacD
8

En fait, il semble suffisant de simplement attacher un stock WebChromeClient à la vue client, ala

mWebView.setWebChromeClient(new WebChromeClient());

et vous devez activer l'accélération matérielle!

Au moins, si vous n'avez pas besoin de lire une vidéo en plein écran, il n'est pas nécessaire d'extraire le VideoView de WebView et de le pousser dans la vue de l'activité. Il sera lu dans le rectangle alloué de l'élément vidéo.

Des idées pour intercepter le bouton de développement de la vidéo?

Russ Schnapp
la source
vous pouvez l'intercepter en utilisant WebChromeClient et en remplaçant onShowCustomView
Frank
Veuillez spécifier quelle version d'Android. Cela fonctionne différemment pour différentes versions.
Ethan_AI
7

Je sais que ce fil a plusieurs mois, mais j'ai trouvé une solution pour lire la vidéo dans WebView sans le faire en plein écran (mais toujours dans le lecteur multimédia ...). Jusqu'à présent, je n'ai trouvé aucun indice à ce sujet sur Internet, alors peut-être que c'est aussi intéressant pour d'autres. J'ai encore du mal sur certains problèmes (c'est-à-dire placer le lecteur multimédia dans la bonne section de l'écran, je ne sais pas pourquoi je le fais mal mais c'est un problème relativement petit je pense ...).

Dans le ChromeClient personnalisé, spécifiez LayoutParams:

// 768x512 is the size of my video
FrameLayout.LayoutParams LayoutParameters = 
                                     new FrameLayout.LayoutParams (768, 512); 

Ma méthode onShowCustomView ressemble à ceci:

public void onShowCustomView(final View view, final CustomViewCallback callback) {
     // super.onShowCustomView(view, callback);
     if (view instanceof FrameLayout) {
         this.mCustomViewContainer = (FrameLayout) view;
         this.mCustomViewCallback = callback;
         this.mContentView = (WebView) this.kameha.findViewById(R.id.webview);
         if (this.mCustomViewContainer.getFocusedChild() instanceof VideoView) {
             this.mCustomVideoView = (VideoView) 
                                     this.mCustomViewContainer.getFocusedChild();
             this.mCustomViewContainer.setVisibility(View.VISIBLE);
             final int viewWidth = this.mContentView.getWidth();
             final int viewLeft = (viewWidth - 1024) / 2;
             // get the x-position for the video (I'm porting an iPad-Webapp to Xoom, 
             // so I can use those numbers... you have to find your own of course...
             this.LayoutParameters.leftMargin = viewLeft + 256; 
             this.LayoutParameters.topMargin = 128;
             // just add this view so the webview underneath will still be visible, 
             // but apply the LayoutParameters specified above
             this.kameha.addContentView(this.mCustomViewContainer, 
                                             this.LayoutParameters); 
             this.mCustomVideoView.setOnCompletionListener(this);
             this.mCustomVideoView.setOnErrorListener(this);
             // handle clicks on the screen (turning off the video) so you can still
             // navigate in your WebView without having the video lying over it
             this.mCustomVideoView.setOnFocusChangeListener(this); 
             this.mCustomVideoView.start();
         }
     }
 }

Donc, j'espère que je pourrais aider ... J'ai aussi dû jouer avec l'encodage vidéo et j'ai vu différents types d'utilisation de WebView avec une vidéo html5 - à la fin, mon code de travail était un mélange sauvage de différentes parties de code que j'ai trouvées dans Internet et certaines choses que je devais résoudre moi-même. C'était vraiment une douleur dans le a *.

UN M
la source
Sur ICS, getFocusedChild () ne renvoie pas de VideoView. Une idée sur la façon de faire fonctionner cela sur ICS?
Pascal
4

Cette approche fonctionne très bien jusqu'à 2.3 Et en ajoutant hardwareaccelerated = true, cela fonctionne même de 3.0 à ICS Un problème auquel je suis actuellement confronté est que le deuxième lancement de l'application de lecteur multimédia se bloque parce que je n'ai pas arrêté la lecture et publié le lecteur multimédia. En tant qu'objet VideoSurfaceView, que nous obtenons dans la fonction onShowCustomView à partir du système d'exploitation 3.0, sont spécifiques au navigateur et non à un objet VideoView comme dans, jusqu'à 2.3 OS Comment puis-je y accéder et arrêter la lecture et libérer des ressources?

Nova
la source
3

AM est similaire à ce que fait le BrowerActivity . pour FrameLayout.LayoutParams LayoutParameters = new FrameLayout.LayoutParams (768, 512);

Je pense que nous pouvons utiliser

FrameLayout.LayoutParams LayoutParameters = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,
            FrameLayout.LayoutParams.FILL_PARENT) 

au lieu.

Un autre problème que j'ai rencontré est si la vidéo est en cours de lecture et que l'utilisateur clique sur le bouton Retour, la prochaine fois, vous accédez à cette activité (singleTop one) et ne pouvez pas lire la vidéo. pour résoudre ce problème, j'ai appelé le

try { 
    mCustomVideoView.stopPlayback();  
    mCustomViewCallback.onCustomViewHidden();
} catch(Throwable e) { //ignore }

dans la méthode onBackPressed de l'activité.

yincan
la source
2

Je sais que c'est une question très ancienne, mais avez-vous essayé l' hardwareAccelerated="true"indicateur de manifeste pour votre application ou activité?

Avec cet ensemble, il semble fonctionner sans aucune modification de WebChromeClient (ce que j'attendrais d'un élément DOM.)

Couche
la source
2
hardwareAccelerateddémarre à partir d'Android 3.0
vbence
2

J'ai utilisé html5webview pour résoudre ce problème.Téléchargez-le et mettez-le dans votre projet, vous pouvez alors coder comme ça.

private HTML5WebView mWebView;
String url = "SOMEURL";
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mWebView = new HTML5WebView(this);
    if (savedInstanceState != null) {
            mWebView.restoreState(savedInstanceState);
    } else {
            mWebView.loadUrl(url);
    }
    setContentView(mWebView.getLayout());
}
@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mWebView.saveState(outState);
}

Pour rendre la vidéo rotative, placez le code android: configChanges = "orientation" dans votre activité par exemple (Androidmanifest.xml)

<activity android:name=".ui.HTML5Activity" android:configChanges="orientation"/>

et remplacez la méthode onConfigurationChanged.

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
}
Methuz Kaewsai-kao
la source
2

Cette question a des années, mais ma réponse aidera peut-être des gens comme moi qui doivent prendre en charge l'ancienne version d'Android. J'ai essayé beaucoup d'approches différentes qui fonctionnaient sur certaines versions d'Android, mais pas sur toutes. La meilleure solution que j'ai trouvée est d'utiliser le Crosswalk Webview qui est optimisé pour la prise en charge des fonctionnalités HTML5 et fonctionne sur Android 4.1 et supérieur. Il est aussi simple à utiliser que le WebView Android par défaut. Il vous suffit d'inclure la bibliothèque. Vous trouverez ici un tutoriel simple sur son utilisation: https://diego.org/2015/01/07/embedding-crosswalk-in-android-studio/

Apfelsaft
la source
Remarque: le passage pour piétons n'est plus maintenu .
slhck
1

Eh bien, apparemment, ce n'est tout simplement pas possible sans utiliser un JNI pour enregistrer un plugin pour obtenir l'événement vidéo. (Personnellement, j'évite les JNI car je ne veux vraiment pas faire face à un désordre lorsque les tablettes Android basées sur Atom sortent dans les prochains mois, perdant la portabilité de Java.)

La seule vraie alternative semble être de créer une nouvelle page Web juste pour WebView et de faire de la vidéo à l'ancienne avec un lien A HREF comme cité dans l'url de Codelark ci-dessus.

Icky.

Brian Moore
la source
1

Sur l'utilisation en nid d'abeille hardwareaccelerated=trueet pluginstate.on_demandsemble fonctionner

user953501
la source
1

J'avais un problème similaire. J'avais des fichiers HTML et des vidéos dans le dossier assets de mon application.

Par conséquent, les vidéos étaient situées à l'intérieur de l'APK. Parce que l'APK est vraiment un fichier ZIP, le WebView n'a pas pu lire les fichiers vidéo.

Copier tous les fichiers HTML et vidéo sur la carte SD a fonctionné pour moi.

RhodanV5500
la source