Pregunta

Estoy juntando un cheapo aplicación que, entre otras cosas, "marcos" algunos de nuestros sitios web...Bastante simple, con el WebViewClient.hasta que me golpeó el video.

El vídeo está hecho a medida HTML5 elementos, y estos funcionan bien y dandy en Chrome, iphone, y ahora que hemos solucionado los problemas de codificación funciona muy bien en Android en el navegador nativo.

Ahora el problema: WebView no le gustan.En todos los.Puede hacer clic en el cartel de la imagen, y no pasa nada.

Buscando en google, he encontrado este que está cerca, pero parece estar basada en un 'link' (como en a href...) en lugar de un elemento de vídeo.(onDownloadListener no parece que se invoca en los elementos de vídeo...)

También veo referencias a la sustitución de onShowCustomView, pero que parece que no se llama en el vídeo de los elementos...tampoco shouldOverrideUrlLoading..

Prefiero no entrar en "tirar de xml en el servidor, vuelva a formatear en la aplicación"..manteniendo la historia del diseño en el servidor, puedo controlar el contenido un poco mejor, sin forzar a la gente a mantener la actualización de una aplicación.Así que si puedo convencer a WebView para manejar las etiquetas como el navegador nativo, que sería lo mejor.

Claramente estoy perdiendo algo obvio..pero no tengo ni idea de qué.

¿Fue útil?

Solución

Me contesta este tema por si acaso alguien se la lea y está interesado en el resultado. Es posible visualizar un elemento de vídeo (etiqueta de vídeo HTML5) dentro de un WebView, pero tengo que decir que tuve que tratar con él durante unos días. Estos son los pasos que tenía que seguir hasta el momento:

-Buscar un video codificado adecuadamente

-Cuando inicialización de la vista Web, establezca el JavaScript, plugins del WebViewClient y la WebChromeClient.

url = new String("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);

-Mango la onShowCustomView en el objeto 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();
        }
    }
}

-Mango la onCompletion y los eventos ONERROR para el video, con el fin de volver a la vista 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();
}

Pero ahora debo decir todavía hay una cuestión importante. Puedo jugar sólo una vez. La segunda vez que haga clic en el despachador de vídeo (ya sea el botón de reproducción algún cartel o), no hace nada.

También me gustaría que el vídeo se reproduzca dentro del marco de vista Web, en lugar de abrir la ventana de Media Player, pero esto es para mí una cuestión secundaria.

espero que ayude a alguien, y yo también lo agradecería cualquier comentario o sugerencia.

Saludos, Terrícolas.

Otros consejos

Después de una investigación de largo, tengo esta cosa de trabajo. Ver el siguiente código:

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>

Esperando resto de cosas que usted puede entender.

La respuesta de mdelolmo era increíblemente útil, pero como dijo, el vídeo sólo se reproduce una vez y luego no puede abrirlo de nuevo.

Me veía en esto un poco y aquí es lo que he encontrado, en caso de que todos los viajeros cansados ??como yo WebView tropiezan en este blog en el futuro.

En primer lugar, me miró a la VideoView y MediaPlayer 's documentación "http://developer.android.com/reference/android/media/MediaPlayer.html" rel = "noreferrer" y tiene una mejor idea de cómo funcionan. Recomiendo los.

A continuación, me miró a la código fuente para ver cómo el navegador de Android lo hace. Hacer un hallazgo página y vaya vistazo a la forma en que manejan onShowCustomView(). Mantienen una referencia a la CustomViewCallbackand a la vista personalizada.

Con todo esto, y con la respuesta de mdelolmo en cuenta, cuando haya terminado con el vídeo, todo lo que necesita hacer es dos cosas. En primer lugar, en la VideoView que guardó una referencia a, stopPlayback() llamada que liberará el MediaPlayer a ser utilizado más adelante en otro lugar. Se puede ver en el VideoView código fuente. En segundo lugar, en el CustomViewCallback que guarda una referencia a CustomViewCallback.onCustomViewHidden() llamada.

Después de hacer esas dos cosas, puede hacer clic en el mismo video o cualquier otro vídeo y se abrirá como antes. No hay necesidad de reiniciar todo el WebView.

Espero que ayude.

En realidad, parece más que suficiente para adjuntar un archivo WebChromeClient a la vista del cliente, ala

mWebView.setWebChromeClient(new WebChromeClient());

y es necesario tener la aceleración de hardware activada!

Por lo menos, si no es necesario reproducir un vídeo en pantalla completa, no hay necesidad de tirar de la VideoView fuera de la vista Web y empujarlo a la vista de la actividad. Se podrá ver en rect asignado del elemento de vídeo.

Alguna idea de cómo interceptar el botón de vídeo expandirse?

Sé que este hilo es de varios meses de edad, pero he encontrado una solución para la reproducción del vídeo dentro de la vista Web sin hacerlo a pantalla completa (pero aún en el reproductor multimedia ...). Hasta ahora, no he encontrado ninguna pista sobre esto en internet así que tal vez esto también es interesante para los demás. Todavía estoy luchando en algunos temas (es decir, colocar el reproductor de medios en la sección derecha de la pantalla, no sé por qué estoy haciendo mal, pero es un tema relativamente pequeño creo ...).

En el ChromeClient personalizada especificar LayoutParams:

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

Mi método onShowCustomView es similar al siguiente:

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();
         }
     }
 }

Por lo tanto, espero poder ayudar ... yo también tenía que jugar un poco con la codificación de video y de sierra diferentes tipos de uso de la vista Web con vídeo HTML5 - al final mi código de trabajo era una mezcla salvaje de códigos distintas partes he encontrado en internet y algunas cosas que tenía que averiguar por mí mismo. Realmente era un dolor en el a *.

Este enfoque funciona bien muy hasta 2.3 Y mediante la adición de hardwareaccelerated = true incluso funciona de 3,0 a ICS Un problema que estoy enfrentando actualmente está sobre el segundo lanzamiento del reproductor multimedia se está estrelló porque no he dejado de reproducción y liberado del reproductor de medios. Como objeto VideoSurfaceView, que nos ponemos en función onShowCustomView de 3.0 OS, son específicos de navegador y no un objeto como en VideoView, hasta 2.3 OS ¿Cómo puedo acceder a ella y stopPlayback y liberación de recursos?

AM de lo que es similar a la BrowerActivity hace. para       FrameLayout.LayoutParams LayoutParameters = new FrameLayout.LayoutParams (768, 512);

Creo que podemos utilizar

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

en su lugar.

Otra cuestión es si me encontré con la reproducción del vídeo, y el usuario hace clic en el botón de retroceso, la próxima vez, que vaya a esta actividad (singleTop uno) y no puede reproducir el vídeo. para solucionar este problema, que se llama el

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

en el método onBackPressed de la actividad.

Sé que esto es una cuestión muy antigua, pero ¿ha intentado la bandera manifiesta hardwareAccelerated="true" para su aplicación o actividad?

Con este conjunto, parece que funciona sin ninguna modificación WebChromeClient (que yo esperaría de un DOM-Element.)

html5webview para resolver este problem.Download y ponerlo en su proyecto, entonces puede codificar como este.

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);
}

Para hacer el video giratorio, puesto androide: configChanges = código de "orientación" en su actividad por ejemplo (AndroidManifest.xml)

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

y reemplazar el método onConfigurationChanged.

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
}

Esta pregunta se hace años, pero tal vez mi respuesta será ayudar a personas como yo que tienen que soportar antigua versión de Android. He intentado un montón de diferentes enfoques que trabajaron en algunas versiones de Android, sin embargo no en todos. La mejor solución que he encontrado es utilizar la del paso de peatones Webview que está optimizado para el apoyo y la obra característica de HTML5 en Android 4.1 y mayor. Es tan fácil de usar como el Android WebView defecto. Sólo tienes que incluir la biblioteca. Aquí se puede encontrar una explicación sencilla sobre cómo usarlo: https://diego.org/2015/01/07/embedding-crosswalk-in-android-studio/

Bueno, aparentemente esto simplemente no es posible sin usar un JNI para registrar un complemento para obtener el evento de video.(Personalmente, estoy evitando los JNI porque realmente no quiero lidiar con un lío cuando las tabletas Android basadas en Atom salgan al mercado en los próximos meses, perdiendo la portabilidad de Java).

La única alternativa real parece ser crear una nueva página web solo para WebView y grabar videos a la antigua usanza con un enlace A HREF como se cita en la URL de Codelark anterior.

Asqueroso.

El uso de nido de abeja y hardwareaccelerated=true pluginstate.on_demand parece funcionar

He tenido un problema similar. Tenía archivos HTML y vídeos en la carpeta de los activos de mi aplicación.

Por lo tanto, los vídeos se encuentra en el interior de la APK. Debido a que el APK es realmente un archivo ZIP, la vista Web no era capaz de leer el vídeo-archivos.

Copiar todo en HTML y video-archivos en la tarjeta SD trabajó para mí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top