Вопрос

Я составляю приложение Sheako, которое среди прочего «кадры» некоторые наших сайтов ... Довольно просты с WebViewClient. Отказ пока я не ударю видео.

Видео сделано как HTML5 элементы, и эти работают нормально и денди на хрома, iPhone, а теперь, когда мы исправили проблемы кодирования, он отлично работает на Android в родном браузере.

Теперь RUB: WebView не нравится это. Вообще. Я могу нажать на изображение плаката, и ничего не происходит.

Googling, я нашел это Что близко, но, похоже, основано на «ссылке» (как в Href ...) вместо видеоэлемента. (OnDownloadListener, похоже, не привязан к видео элементам ...)

Я также вижу ссылки на переоценку onshowcustomview, но это, кажется, не вызывается видео элементами ... и не требует того, что поглощает

Я бы предпочел не попасть в «Потяните XML с сервера», переформатируйте его в приложении «.. Поддерживая раскладку истории на сервере, я могу контролировать контент немного лучше, не заставляя людей поддерживать обновление приложения. Так что, если я смогу убедить WebView для обработки тегов, таких как родной браузер, это было бы лучше.

Я явно пропускаю что-то очевидное .. Но я понятия не имею.

Это было полезно?

Решение

Я отвечаю на эту тему, на всякий случай, если кто-то прочитал его и заинтересован в результате. Можно просматривать видеоэлемент (видео HTML5) в WebView, но я должен сказать, что мне нужно было иметь дело с ним в течение нескольких дней. Это шаги, которые я должен был следовать до сих пор:

-Не правильно закодированное видео

-Когда инициализация веб-просмотра, установите JavaScript, плагины WebViewClient и WebchRomEclient.

URL = новая строка ("http://brones-links.com/tests/video/"); mwebview = (webview) findviewbyid (r.id.webview); mwebview.setwebchRomeClient (хромец); mwebview.setwebviewClient (WVClient); mwebview.getsettings (). setjavascriptenabled (true); mwebview.getsettings (). setpluginstate (pluginstate.on); mwebview.loadurl (URL);

-Нахайте в OnShowCustomView в объекте 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();
        }
    }
}

-Дулните о непосредственном состоянии и события OneRror для видео, чтобы вернуться к представлению веб-вида.

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

Но теперь я должен сказать, что есть еще важный вопрос. Я могу сыграть это только один раз. Второй раз я нажимаю на диспетчер видео (либо кнопку POSTER или какую-то воспроизведение), это ничего не делает.

Я также хотел бы, чтобы видео было воспроизведено внутри кадра WebView, вместо того, чтобы открыть окно медиаплеера, но это для меня вторичная проблема.

Я надеюсь, что это поможет кому-то, и я бы также благодарю какие-либо комментарии или предложения.

Салудос, Терриколас.

Другие советы

После долгих исследований я получил эту вещь, работаю. Смотрите следующий код:

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>

Mainest.xml.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>

Ожидание остальных вещей, которые вы можете понять.

Ответ Mdelolmo был невероятно услужливым, но, как сказал он, видео играет только один раз, и тогда вы не можете открыть его снова.

Я немного посмотрел на это, и вот то, что я нашел, на случай, если какой-то утомленные путешественники WebView, как сам наткнуться на этот пост в будущем.

Во-первых, я посмотрел на Videoview. а также Проигрыватель медиаДокументация и получила лучшее чувство, как эти работы. Я настоятельно рекомендую тем.

Тогда я посмотрел на Исходный код, чтобы увидеть, как браузер Android Имеет ли это. Найдите ли страница и посмотрите, как они обрабатываются onShowCustomView(). Отказ Они хранят ссылку на CustomViewCallbackи на заказ.

Со всем этим, и с ответом Mdelolmo в уме, когда вы закончите с видео, все, что вам нужно сделать, это две вещи. Во-первых, на VideoView что вы сохранили ссылку на, позвоните stopPlayback() это будет выпустить MediaPlayer использоваться позже в другом месте. Вы можете увидеть это в Videoview. исходный код. Во-вторых, на CustomViewCallback Вы сохранили ссылку на звонок CustomViewCallback.onCustomViewHidden().

После выполнения этих двух вещей вы можете нажать на одно и то же видео или любое другое видео, и он откроется раньше. Не нужно перезапустить весь веб-просмотр.

Надеюсь, это поможет.

На самом деле, кажется, достаточно просто прикрепить запас WebchRomeClient на вид клиента, ALA

mWebView.setWebChromeClient(new WebChromeClient());

И вам нужно включить аппаратное ускорение!

По крайней мере, если вам не нужно играть в полноэкранное видео, нет необходимости вытащить видеовизмо из веб-просмотра и нажать в представление о деятельности. Он будет воспроизводиться в выделенном видео элементе.

Любые идеи, как перехватить кнопку «Развернуть видео»?

Я знаю, что эта нить несколько месяцев, но я нашел решение для воспроизведения видео внутри WebView, не делая его полноэкранного экрана (но все же в медиаплеере ...). Пока что я не нашел никакого намека на это в интернете, так что, возможно, это также интересно для других. Я все еще борюсь на некоторые проблемы (т.е. поместив медиаплеер в правильном разделе экрана, не знаю, почему я делаю это неправильно, но это относительно небольшая проблема, которую я думаю ...).

В пользовательском хромечлете укажите LayoutParams:

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

Мой метод onshowcustomview выглядит так:

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

Итак, я надеюсь, что смогу помочь ... Я тоже должен был играть с видео-кодировкой и видел разные виды использования WebView с видео HTML5 - в конце моего рабочего кода был диким смесью разных частей кода, которые я нашел в Интернет и некоторые вещи, которые я должен был понять сам. Это действительно боль в а *.

Этот подход работает хорошо, очень до 2.3, и, добавив HardWareCaCECELECELED = TRUE, даже работает с 3.0 до ICS Одна проблема, которую я сталкиваюсь в настоящее время, на втором запуск приложения медиаплеера - это разбито, потому что я не перестал воспроизведение и выпустить медиаплеер. Поскольку объект VideoRFaceView, который мы получаем в OnshowCustomView функции с 3,0 ОС, специфичны для браузера, а не объектом VideoView, как в, до 2.3 ОС, как я могу получить доступ к ней и остановках и выпустить ресурсы?

Я похож на то, что Брелок делает. для framelayout.layoutparams layoutparameters = новый framelayout.layoutparams (768, 512);

Я думаю, что мы можем использовать

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

вместо.

Другой вопрос, который я встречал, это если видео воспроизведение, и пользователь нажимает кнопку «Назад», в следующий раз вы идете к этой деятельности (Singletop One) и не можете играть в видео. исправить это, я позвонил

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

в методе деятельности в обращении.

Я знаю, что это очень старый вопрос, но вы пробовали hardwareAccelerated="true" Манифест Флаг для вашего приложения или деятельности?

С помощью этого набора, кажется, работает без какой-либо модификации WebchroMeClient (которую я ожидал от DOM-элемента.)

я использовал html5webview. Чтобы решить эту проблему. Остановить его в свой проект, вы можете поставить код точно так.

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

Чтобы сделать видео вращающееся, поставьте Android: configchanges = "ориентация", например, в вашу деятельность (AndroidManifest.xml)

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

и переопределить метод onconfigurationChanged.

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

Этот вопрос годы, но, возможно, мой ответ поможет таким, как я, кто должен поддерживать старую версию Android. Я попробовал много разных подходов, которые работали на некоторых версиях Android, однако не на всех. Лучшее решение, которое я нашел, это использовать Crosswalk WebView. который оптимизирован для поддержки функций HTML5 и работает на Android 4.1 и выше. Так же просто использовать в качестве веб-просмотра Android по умолчанию. Вы просто должны включить библиотеку. Здесь вы можете найти простой учебник о том, как его использовать: https://diego.org/2015/01/07/embedding-crosswalk-in-android-studio/

Ну, по-видимому, это просто невозможно без использования JNI, чтобы зарегистрировать плагин для получения видео события. (Лично я избегаю JNI, поскольку я действительно не хочу иметь дело с беспорядком, когда атомные планшеты Android выходили в ближайшие несколько месяцев, теряя переносимость Java.)

Единственная реальная альтернатива, по-видимому, для создания новой веб-страницы только для WebView и выполняет видео старого школьного способа с помощью ссылки Href, как указано в URL CodeLark выше.

Icky.

На сотовой пользу hardwareaccelerated=true а также pluginstate.on_demand кажется, работает

У меня была похожая проблема. У меня были HTML-файлы и видео в папке активов моего приложения.

Поэтому видео были расположены внутри APK. Поскольку APK действительно ZIP-файл, веб-просмотр не смог прочитать видео-файлы.

Копирование всех HTML-и видеофайлов на SD-карту сработало для меня.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top