WebView i HTML5 <video>

123

Składam razem tanią aplikację, która między innymi „oprawia” niektóre z naszych stron internetowych ... Całkiem proste dzięki WebViewClient. dopóki nie włączę wideo.

Wideo jest zrobione jako HTML5 elementy, które działają dobrze i elegancko w Chrome, iPhone'ach, a teraz, gdy naprawiliśmy problemy z kodowaniem, działa świetnie Androidw natywnej przeglądarce.

Teraz rub: WebViewnie podoba. W ogóle. Mogę kliknąć obraz plakatu i nic się nie dzieje.

Szukając w Google, znalazłem to, które jest bliskie, ale wydaje się być oparte na „linku” (jak w href ...) zamiast na elemencie wideo. (onDownloadListener nie wydaje się być wywoływany dla elementów wideo ...)

Widzę również odniesienia do zastępowania onShowCustomView, ale wydaje się, że nie jest to wywoływane w elementach wideo ... ani nie powinnoOverrideUrlLoading ..

Wolałbym nie zajmować się „ściąganiem xml z serwera, przeformatowaniem go w aplikacji”… utrzymując układ fabuły na serwerze, mogę nieco lepiej kontrolować zawartość bez zmuszania ludzi do ciągłego aktualizowania aplikacji. Więc jeśli uda mi się przekonać WebView do obsługi tagów, takich jak natywna przeglądarka, byłoby najlepiej.

Wyraźnie brakuje mi czegoś oczywistego… ale nie mam pojęcia co.

Brian Moore
źródło
W tych samych kwestiach szukam odtwarzacza HTML5 do mojej witryny. Czego powinienem użyć?
Wolfpack'08,
1
Moja odpowiedź tutaj: stackoverflow.com/a/16179544/423171
cprcrack.
1
Nic nie działało, więc zajrzałem VideoEnabledWebViewtutaj stackoverflow.com/questions/15768837/ ...
EpicPandaForce

Odpowiedzi:

93

Odpowiadam na ten temat na wypadek, gdyby ktoś to przeczytał i jest zainteresowany wynikiem. Możliwe jest obejrzenie elementu wideo (tag video html5) w ramach WebView, ale muszę powiedzieć, że musiałem sobie z tym radzić przez kilka dni. Oto kroki, które musiałem wykonać do tej pory:

- Znajdź prawidłowo zakodowany film

-Podczas inicjowania WebView, ustaw JavaScript, wtyczki WebViewClient i 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);

-Obsługuj onShowCustomView w obiekcie 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();
        }
    }
}

-Obsługuj zdarzenia onCompletion i onError dla wideo, aby wrócić do widoku sieci 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();
}

Ale teraz powinienem powiedzieć, że nadal istnieje ważna kwestia. Mogę to zagrać tylko raz. Za drugim razem, gdy klikam dyspozytor wideo (albo plakat, albo jakiś przycisk odtwarzania), nic nie robi.

Chciałbym również, aby wideo było odtwarzane w ramce WebView, zamiast otwierać okno Media Player, ale jest to dla mnie kwestia drugorzędna.

Mam nadzieję, że komuś to pomoże, a także dziękuję za wszelkie komentarze lub sugestie.

Saludos, terrícolas.

mdelolmo
źródło
nie uruchamiam żadnego wyniku, mój ekran jest czarny. Chcę wiedzieć, czy to potrzebuje thead. mój kod jest zbyt długi, aby go tu umieścić. czy możesz podać mi sposób kontaktu lub otworzyć inny temat.
pengwang
Czy na pewno nie jest to problem z kodowaniem? Spróbuj użyć adresu URL, który opublikowałem. Oczywiście musi działać z natywną przeglądarką
mdelolmo
46
co to jest „a”? jak ta aktywność miałaby być?
Collin Price
1
@Collin Price a jest wystąpieniem działania obsługującego widok internetowy. @desgraci, mogę to zapewnić, ale poza tym niewiele jest. Rozszerz klasę WebChromeClienti nadpisz odpowiednie metody, których potrzebujesz. Jeśli nalegasz, mogę przesłać resztę zajęć później, gdy wrócę do domu.
mdelolmo,
6
Nie działa na ICS, ponieważ getFocusedChild () nie jest VideoView, ale HTML5VFullScreen $ SurfaceVideoView. Masz jakiś pomysł, jak to zrobić na ICS? (patrz stackoverflow.com/questions/13540654/ ...
Pascal
61

Po długich poszukiwaniach udało mi się to. Zobacz poniższy kod:

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>

Spodziewam się reszty rzeczy, które potrafisz zrozumieć.

surendra
źródło
7
Ta powinna być akceptowaną odpowiedzią. Surendra i Malenkiy, oboje ocaliliście moje zdrowie psychiczne. U mnie zadziałało świetnie.
George Baker
Zgadzam się z George'em. Dokładnie tak działa natywna przeglądarka Androida z VideoView. Wygląda na to, że jest to ten sam kod, co tutaj code.google.com/p/html5webview . Działa świetnie na wszystkich wersjach Androida (testowałem na Androidzie 2.2 i nowszych). Tylko jedna rzecz, na którą chciałem zwrócić uwagę, należy pamiętać, że jeśli zmienisz docelowy SDK na coś powyżej 13, twoja aktywność zostanie odtworzona przy zmianie orientacji. Aby tego uniknąć, dodaj screenSize do android: configChanges (ale w tym przypadku będziesz potrzebować min sdk <13) lub użyj starego docelowego SDK (wtedy możesz zachować android: configChanges)
Yuriy Ashaev
2
To daje mi biały pusty ekran na Nexusie 7 (Android 4.1). Jakiś pomysł jak to naprawić?
Sahil
Przycisk Backbutton nie zatrzymuje wideo, a dźwięk nadal jest słyszalny, masz jakiś pomysł, jak to naprawić?
CONvid19
To jest to, czego szukałem, dokładnie tak samo, jak w natywnej przeglądarce. Dzięki Ton Surendra i Malenkiy.
Abhilash
33

Odpowiedź mdelolmo była niezwykle pomocna, ale jak powiedział, wideo jest odtwarzane tylko raz i nie można go ponownie otworzyć.

Przyjrzałem się temu trochę i oto, co znalazłem, na wypadek gdyby jacyś znużeni podróżnicy WebView, tacy jak ja, natknęli się w przyszłości na ten post.

Po pierwsze, przejrzałem dokumentację VideoView i MediaPlayera i lepiej zrozumiałem, jak one działają. Gorąco je polecam.

Następnie spojrzałem na kod źródłowy, aby zobaczyć, jak robi to przeglądarka Android . Znajdź stronę i zobacz, jak sobie radzą onShowCustomView(). Zachowują odniesienie do CustomViewCallbacki do widoku niestandardowego.

Mając to wszystko na uwadze i mając na uwadze odpowiedź mdelolmo, kiedy skończysz z wideo, wszystko, co musisz zrobić, to dwie rzeczy. Po pierwsze, w miejscu VideoView, do którego zapisałeś odniesienie, wywołanie stopPlayback(), które zwolni element MediaPlayerdo wykorzystania później w innym miejscu. Możesz to zobaczyć w kodzie źródłowym VideoView . Po drugie, CustomViewCallbackzapisałeś odniesienie do połączenia CustomViewCallback.onCustomViewHidden().

Po wykonaniu tych dwóch czynności możesz kliknąć ten sam film lub inny film, a otworzy się jak poprzednio. Nie ma potrzeby ponownego uruchamiania całego WebView.

Mam nadzieję, że to pomoże.

cottonBallPaws
źródło
Właściwie też to rozwiązałem, po prostu nie pamiętałem, aby opublikować rozwiązanie (wstyd mi). Tak jak ty, musiałem zajrzeć do kodu przeglądarki Androida i cóż, niewiele do dodania, zamiast tego użyłem odbiornika onCompletion, aby zatrzymać odtwarzacz i musiałem kilka razy ustawić widoczność, ale kupiłbym twoje rozwiązanie. Pozdrowienia!
mdelolmo,
1
Google Code Search zostało wycofane, myślę, że ta wersja BrowserActivity.java (z Froyo) w przybliżeniu odpowiada tej opisanej tutaj: github.com/android/platform_packages_apps_browser/blob/ ...
michiakig
Połączony kod @ spacemanki nie zawiera żadnych wzmianek o VideoView w całym repozytorium. Wydaje mi się, że BrowserActivity robi to teraz inaczej. Wróciłem nawet do wydania Eclair. Nie mogę znaleźć żadnego zastosowania.
mxcl
Problem, który mam z tym wszystkim, polega na tym, że to, co otrzymuję z frame.getFocusedChild (); jest HTml5VideoView zamiast ViewView i dlatego nic z tego nie działa dla mnie i nie mogę przełączyć się na pełny ekran :( Jestem na Androidzie 4.1.2.
Gonan
1
W końcu dodałem: @Override public void onStop () {super.onStop (); mWebView.destroy (); } do działania ... webview.destroy () był kluczowy
MacD
8

W rzeczywistości wydaje się wystarczające, aby po prostu dołączyć zwykłego WebChromeClient do widoku klienta, ala

mWebView.setWebChromeClient(new WebChromeClient());

i musisz mieć włączone przyspieszenie sprzętowe!

Przynajmniej jeśli nie musisz odtwarzać wideo na pełnym ekranie, nie ma potrzeby wyciągania VideoView z WebView i wypychania go do widoku działania. Będzie odtwarzany w wyznaczonym prostokącie elementu wideo.

Jakieś pomysły, jak przechwycić przycisk rozwijania wideo?

Russ Schnapp
źródło
możesz go przechwycić za pomocą WebChromeClient i nadpisać onShowCustomView
Frank
Określ, która wersja Androida. Działa to inaczej dla różnych wersji.
Ethan_AI
7

Wiem, że ten wątek ma kilka miesięcy, ale znalazłem rozwiązanie do odtwarzania wideo wewnątrz WebView bez robienia tego na pełnym ekranie (ale nadal w odtwarzaczu multimedialnym ...). Jak dotąd nie znalazłem w internecie żadnej wskazówki na ten temat, więc może jest to również interesujące dla innych. Nadal zmagam się z niektórymi problemami (np. Umieszczam odtwarzacz multimedialny w odpowiedniej sekcji ekranu, nie wiem, dlaczego robię to źle, ale myślę, że jest to stosunkowo mały problem ...).

W Custom ChromeClient określ LayoutParams:

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

Moja metoda onShowCustomView wygląda następująco:

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

Mam więc nadzieję, że mógłbym pomóc ... Ja też musiałem bawić się kodowaniem wideo i widziałem różne rodzaje korzystania z WebView z wideo html5 - w końcu mój działający kod był dziką mieszanką różnych części kodu, które znalazłem w internet i kilka rzeczy, które musiałem sam wymyślić. To naprawdę było uciążliwe w a *.

JESTEM
źródło
W ICS getFocusedChild () nie zwraca VideoView. Masz jakiś pomysł, jak to działa w ICS?
Pascal
4

To podejście działa dobrze aż do wersji 2.3. A przez dodanie hardwareaccelerated = true działa nawet od 3.0 do ICS.Jeden problem, z którym się obecnie zmagam, polega na tym, że po drugim uruchomieniu aplikacji odtwarzacza multimediów dochodzi do awarii, ponieważ nie zatrzymałem odtwarzania i wypuściłem Media Player. Ponieważ obiekt VideoSurfaceView, który otrzymujemy w funkcji onShowCustomView z systemu operacyjnego 3.0, jest specyficzny dla przeglądarki, a nie jest obiektem VideoView, jak w systemie do wersji 2.3. Jak mogę uzyskać do niego dostęp i zatrzymać odtwarzanie i zwolnić zasoby?

Nova
źródło
3

AM jest podobne do tego, co robi BrowerActivity . dla FrameLayout.LayoutParams LayoutParameters = new FrameLayout.LayoutParams (768, 512);

Myślę, że możemy użyć

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

zamiast.

Innym problemem, z którym się spotkałem, jest to, czy wideo jest odtwarzane, a użytkownik kliknie przycisk Wstecz, następnym razem przejdziesz do tej czynności (singleTop) i nie możesz odtworzyć wideo. Aby to naprawić, zadzwoniłem do

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

w metodzie onBackPressed działania.

yincan
źródło
2

Wiem, że to bardzo stare pytanie, ale czy wypróbowałeś hardwareAccelerated="true"flagę manifestu dla swojej aplikacji lub działania?

Z tym zestawem wydaje się działać bez żadnej modyfikacji WebChromeClient (czego oczekiwałbym od elementu DOM).

Pieluszka
źródło
2
hardwareAcceleratedzaczyna się od Androida 3.0
vbence
2

Użyłem html5webview, aby rozwiązać ten problem, pobierz i umieść go w swoim projekcie, a następnie możesz kodować w ten sposób.

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

Aby wideo można było obracać, umieść na przykład kod android: configChanges = "orientacja" w swoim działaniu (Androidmanifest.xml)

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

i zastąp metodę onConfigurationChanged.

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
}
Methuz Kaewsai-kao
źródło
2

To pytanie ma już lata, ale może moja odpowiedź pomoże ludziom takim jak ja, którzy muszą obsługiwać starą wersję Androida. Wypróbowałem wiele różnych podejść, które działały na niektórych wersjach Androida, ale nie na wszystkich. Najlepszym rozwiązaniem, jakie znalazłem, jest użycie Crosswalk Webview, który jest zoptymalizowany pod kątem obsługi funkcji HTML5 i działa na Androidzie 4.1 i nowszych. Jest tak prosty w użyciu, jak domyślny Android WebView. Musisz tylko dołączyć bibliotekę. Tutaj znajdziesz prosty samouczek, jak go używać: https://diego.org/2015/01/07/embedding-crosswalk-in-android-studio/

Apfelsaft
źródło
Uwaga: przejście dla pieszych nie jest już utrzymywane .
slhck
1

Cóż, najwyraźniej nie jest to możliwe bez użycia JNI do zarejestrowania wtyczki w celu uzyskania zdarzenia wideo. (Osobiście unikam JNI, ponieważ naprawdę nie chcę zajmować się bałaganem, gdy w ciągu najbliższych kilku miesięcy pojawią się tablety z Androidem oparte na Atom, tracąc przenośność Javy).

Jedyną realną alternatywą wydaje się być utworzenie nowej strony internetowej tylko dla WebView i nagranie wideo w oldschoolowy sposób z linkiem A HREF, jak podano w adresie URL Codelark powyżej.

Icky.

Brian Moore
źródło
1

W przypadku stosowania plastra miodu hardwareaccelerated=truei pluginstate.on_demandwydaje się, że działa

user953501
źródło
1

Miałem podobny problem. W folderze zasobów mojej aplikacji znajdowały się pliki HTML i filmy.

Dlatego filmy znajdowały się w pliku APK. Ponieważ plik APK jest w rzeczywistości plikiem ZIP, WebView nie był w stanie odczytać plików wideo.

Kopiowanie wszystkich plików HTML i wideo na kartę SD zadziałało.

RhodanV5500
źródło