WebView 및 HTML5 <동영상>


122

저는 다른 것들 중에서 우리 웹 사이트의 일부를 "프레임"하는 저렴한 앱을 함께 연결하고 WebViewClient있습니다 .... 비디오를 볼 때까지.

비디오는 HTML5 요소 로 수행되며 Chrome, iPhone에서 훌륭하고 멋지게 작동하며 이제 Android기본 브라우저에서 잘 작동하는 인코딩 문제를 수정했습니다 .

이제 문지름 : WebView그것을 좋아하지 않습니다. 조금도. 포스터 이미지를 클릭해도 아무 일도 일어나지 않습니다.

인터넷 검색, 나는 이것이 가깝지만 비디오 요소 대신 '링크'(href ...에서와 같이)를 기반으로 한 것으로 보입니다. (onDownloadListener는 비디오 요소에서 호출되지 않는 것으로 보입니다 ...)

또한 onShowCustomView 재정의에 대한 참조도 볼 수 있지만 동영상 요소에서 호출되지 않는 것 같습니다. shouldOverrideUrlLoading도 마찬가지입니다.

나는 "서버에서 XML을 가져 와서 앱에서 다시 포맷"하는 것이 아니라 서버에 스토리 레이아웃을 유지함으로써 사람들이 앱을 계속 업데이트하도록 강요하지 않고도 콘텐츠를 조금 더 잘 제어 할 수 있습니다. 따라서 WebView가 기본 브라우저와 같은 태그를 처리하도록 설득 할 수 있다면 이것이 가장 좋습니다.

분명한 걸 놓치고 있는데 .. 뭔지 모르겠어요.



이 같은 라인을 따라 웹 사이트 용 HTML5 플레이어를 찾고 있습니다. 무엇을 사용해야합니까?
Wolfpack'08


1
내가 들여다 그래서 아무것도 일하지 VideoEnabledWebView여기 stackoverflow.com/questions/15768837/...
EpicPandaForce

답변:


92

누군가가 그것을 읽고 결과에 관심이있는 경우를 대비하여이 주제에 대답합니다. WebView 내에서 비디오 요소 (video html5 태그)를 볼 수 있지만 며칠 동안 처리해야한다고 말해야합니다. 지금까지 따라야 할 단계는 다음과 같습니다.

-적절하게 인코딩 된 비디오 찾기

-WebView를 초기화 할 때 JavaScript를 설정하고 WebViewClient 및 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);

-WebChromeClient 개체에서 onShowCustomView를 처리합니다.

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

-웹보기로 돌아가려면 동영상의 onCompletion 및 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();
}

그러나 지금은 여전히 ​​중요한 문제가 있다고 말해야합니다. 한 번만 재생할 수 있습니다. 두 번째로 비디오 디스패처 (포스터 또는 일부 재생 버튼)를 클릭하면 아무 작업도 수행되지 않습니다.

또한 Media Player 창을 여는 대신 WebView 프레임 내에서 비디오를 재생하고 싶지만 이것은 저에게 두 번째 문제입니다.

누군가에게 도움이되기를 바라며 어떤 의견이나 제안에도 감사드립니다.

Saludos, terrícolas.


결과를 실행하지 않고 화면이 검은 색입니다. 광고가 필요한지 알고 싶습니다. 내 코드가 너무 길어서 여기에 posy. 연락 방법을 주거나 다른 주제를 열 수 있습니까?
pengwang

인코딩 문제가 아닌지 완전히 확신하십니까? 내가 게시 한 URL을 사용해보십시오. 분명히 그것은 네이티브 브라우저와 함께 작동해야합니다
mdelolmo

46
"a"는 무엇입니까? 그 활동이 될까요?
Collin Price

1
@Collin Price a는 웹뷰를 호스팅하는 활동의 인스턴스입니다. @desgraci, 나는 그것을 제공 할 수 있지만 그 외에는 많지 않습니다. 클래스를 확장 WebChromeClient하고 필요한 해당 메서드를 재정의하십시오. 주장한다면 나중에 집에 돌아와 나머지 수업을 업로드 할 수 있습니다.
mdelolmo

6
getFocusedChild ()는 VideoView가 아니라 HTML5VFullScreen $ SurfaceVideoView이므로 ICS에서 작동하지 않습니다. ICS에서 수행하는 방법에 대한 아이디어가 있습니까? ( stackoverflow.com/questions/13540654/…
Pascal

61

오랜 연구 끝에이 일이 작동했습니다. 다음 코드를 참조하십시오.

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>

당신이 이해할 수있는 나머지 것들을 기대합니다.


7
이것은 받아 들여진 대답이어야합니다. Surendra와 Malenkiy 둘 다 내 정신을 구했습니다. 나를 위해 훌륭하게 일했습니다.
George Baker

나는 George와 동의합니다. 이것이 바로 Android 기본 브라우저가 VideoView와 작동하는 방식입니다. 이것은 여기 code.google.com/p/html5webview 와 동일한 코드 인 것 같습니다 . 모든 Android 버전에서 잘 작동합니다 (Android 2.2 이상에서 테스트했습니다). 내가 주목하고 싶은 한 가지만, 13 이상의 대상 SDK를 변경하면 방향 변경시 활동이 다시 생성된다는 점을 명심해야합니다. 이를 방지하려면 screenSize를 android : configChanges에 추가하거나 (이 경우에는 min sdk <13을 사용해야 함) 이전 대상 SDK를 사용합니다 (그런 다음 android : configChanges를 유지할 수 있음)
Yuriy Ashaev 2013 년

2
이것은 넥서스 7 (안드로이드 4.1)에서 흰색 빈 화면을 제공합니다. 이 문제를 해결하는 방법을 아십니까?
Sahil

뒤로 버튼은 비디오를 멈추지 않고 오디오는 여전히들을 수 있습니다.이 문제를 해결하는 방법은 무엇입니까?
CONvid19 2014

이것이 내가 기본 브라우저 흐름과 정확히 똑같은 것을 찾고 있던 것입니다. Ton Surendra와 Malenkiy에게 감사드립니다.
Abhilash

33

mdelolmo의 답변은 매우 도움이되었지만 그가 말했듯이 비디오는 한 번만 재생되고 다시 열 수 없습니다.

나는 이것을 조금 조사했고, 나처럼 지친 WebView 여행자가 미래 에이 게시물을 우연히 발견 한 경우를 대비하여 내가 찾은 것입니다.

먼저 VideoViewMediaPlayer 의 문서를 살펴보고 작동 방식을 더 잘 이해했습니다. 나는 그것들을 강력히 추천합니다.

그런 다음 Android 브라우저어떻게 작동하는지 확인하기 위해 소스 코드를 살펴 보았습니다 . 페이지 찾기를 수행하고 처리 방법을 살펴보십시오 onShowCustomView(). CustomViewCallback및 사용자 정의보기에 대한 참조를 유지합니다 .

그 모든 것과 mdelolmo의 대답을 염두에두고 비디오 작업을 마치면 두 가지 작업 만하면됩니다. 먼저 VideoView참조를 저장 한에서 나중에 다른 곳에서 사용할을 stopPlayback()해제하는 호출을 합니다 MediaPlayer. VideoView 소스 코드 에서 볼 수 있습니다 . 둘째,에 CustomViewCallback호출에 대한 참조를 저장했습니다 CustomViewCallback.onCustomViewHidden().

이 두 가지 작업을 수행 한 후 동일한 비디오 또는 다른 비디오를 클릭하면 이전과 같이 열립니다. 전체 WebView를 다시 시작할 필요가 없습니다.

도움이되기를 바랍니다.


사실 나도 문제를 해결했고 해결책을 게시하는 것을 기억하지 못했습니다 (부끄러움). 여러분과 마찬가지로 Android 브라우저의 코드를 살펴 봐야했고 추가 할 사항이 많지 않았습니다. 대신 onCompletion 리스너를 사용하여 Player를 중지하고 가시성을 몇 번 설정해야했지만 솔루션을 구입하겠습니다. 문안 인사!
mdelolmo 2011 년

1
Google 코드 검색이 중단
michiakig

@spacemanki의 연결된 코드에는 전체 저장소에서 VideoView에 대한 언급이 없습니다. 이제 BrowserActivity가 다르게 작동한다고 생각합니다. 나는 심지어 Eclair 릴리스로 돌아갔습니다. 사용법을 찾을 수 없습니다.
mxcl

내가 가진 문제는 내가 frame.getFocusedChild (); 은 ViewView 대신 HTml5VideoView이므로이 중 어느 것도 나를 위해 작동하지 않으며 전체 화면으로 전환 할 수 없습니다 :( 저는 Android 4.1.2에 있습니다.
Gonan

1
마지막으로 나를 위해 한 것은 다음을 추가하는 것입니다. @Override public void onStop () {super.onStop (); mWebView.destroy (); } 활동에 ... webview.destroy ()가 중요했습니다
MacD

8

사실, 단순히 스톡 WebChromeClient를 클라이언트 뷰에 첨부하는 것으로 충분 해 보입니다.

mWebView.setWebChromeClient(new WebChromeClient());

하드웨어 가속을 켜야합니다!

적어도 전체 화면 비디오를 재생할 필요가 없다면 WebView에서 VideoView를 끌어 내서 Activity의 뷰로 푸시 할 필요가 없습니다. 비디오 요소에 할당 된 사각형에서 재생됩니다.

동영상 확장 버튼을 가로채는 방법에 대한 아이디어가 있습니까?


WebChromeClient를 사용하여 가로 채고 onShowCustomView를 재정의 할 수 있습니다.
Frank

Android 버전을 지정하십시오. 이것은 버전에 따라 다르게 작동합니다.
Ethan_AI 2014

7

이 스레드가 몇 달 전이라는 것을 알고 있지만 전체 화면을 수행하지 않고 WebView 내에서 비디오를 재생하는 솔루션을 찾았습니다 (하지만 여전히 미디어 플레이어에서 ...). 지금까지 인터넷에서 이것에 대한 힌트를 찾지 못 했으므로 다른 사람들에게도 흥미로울 것입니다. 나는 여전히 몇 가지 문제로 어려움을 겪고 있습니다.

Custom ChromeClient에서 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();
         }
     }
 }

그래서 제가 도울 수 있기를 바랍니다 ... 저도 video-Encoding을 가지고 놀아야했고 html5 비디오와 함께 WebView를 사용하는 다양한 종류를 보았습니다. 결국 제 작업 코드는 제가 찾은 다양한 코드 부분의 거친 혼합이었습니다. 인터넷과 내가 스스로 알아 내야 할 몇 가지. 정말 a *의 고통이었습니다.


ICS에서 getFocusedChild ()는 VideoView를 반환하지 않습니다. ICS에서이 작업을 수행하는 방법에 대한 아이디어가 있습니까?
Pascal

4

이 접근 방식은 2.3까지 잘 작동하며 hardwareaccelerated = true를 추가하면 3.0에서 ICS까지도 작동합니다. 현재 직면하고있는 한 가지 문제는 재생을 중지하지 않고 미디어 플레이어를 출시하지 않았기 때문에 미디어 플레이어 응용 프로그램을 두 번째로 시작할 때 충돌이 발생한다는 것입니다. 3.0 OS의 onShowCustomView 함수에서 얻는 VideoSurfaceView 개체는 브라우저에 따라 다르며 2.3 OS까지는 VideoView 개체가 아닙니다. 어떻게 액세스하고 재생을 중지하고 리소스를 해제 할 수 있습니까?


3

AM은 BrowerActivity가하는 일과 유사합니다 . For FrameLayout.LayoutParams LayoutParameters = new 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 }

활동의 onBackPressed 메소드에서.


2

이것은 매우 오래된 질문이라는 것을 알고 있지만 hardwareAccelerated="true"응용 프로그램이나 활동에 대한 매니페스트 플래그를 사용해 보셨습니까?

이 세트를 사용하면 WebChromeClient 수정없이 작동하는 것 같습니다 (DOM-Element에서 기대할 수 있음).


2
hardwareAcceleratedAndroid 3.0에서 시작
vbence 2012 년

2

이 문제를 해결하기 위해 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 = "orientation"코드를 활동에 넣습니다 (예 : Androidmanifest.xml).

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

onConfigurationChanged 메소드를 재정의하십시오.

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

2

이 질문은 오래되었지만 제 대답은 이전 Android 버전을 지원해야하는 저와 같은 사람들에게 도움이 될 것입니다. 일부 Android 버전에서 작동하는 다양한 접근 방식을 시도했지만 전부는 아닙니다. 내가 찾은 최고의 솔루션 은 HTML5 기능 지원에 최적화되고 Android 4.1 이상에서 작동 하는 Crosswalk Webview 를 사용하는 것 입니다. 기본 Android WebView만큼 사용하기 쉽습니다. 라이브러리를 포함하기 만하면됩니다. 여기에서 사용법에 대한 간단한 튜토리얼을 찾을 수 있습니다 : https://diego.org/2015/01/07/embedding-crosswalk-in-android-studio/


참고 : 횡단 보도는 더 이상 유지 되지 않습니다.
slhck

1

글쎄, 분명히 이것은 비디오 이벤트를 얻기 위해 플러그인을 등록하기 위해 JNI를 사용하지 않고는 불가능합니다. (개인적으로 저는 JNI를 피하고 있습니다. 앞으로 몇 달 안에 Atom 기반 안드로이드 태블릿이 나올 때 자바의 이식성을 잃어 버릴 때 엉망진창을 처리하고 싶지 않기 때문입니다.)

유일한 대안은 WebView 전용 새 웹 페이지를 만들고 위의 Codelark url에 인용 된 A HREF 링크를 사용하여 구식 방식으로 비디오를 만드는 것입니다.

이키.


1

벌집 사용에 hardwareaccelerated=truepluginstate.on_demand작동하는 것 같다


1

비슷한 문제가있었습니다. 내 앱의 자산 폴더에 HTML 파일과 비디오가 있습니다.

따라서 비디오는 APK 내부에 있습니다. APK가 실제로 ZIP 파일이기 때문에 WebView는 비디오 파일을 읽을 수 없습니다.

모든 HTML 및 비디오 파일을 SD 카드에 복사하는 것이 저에게 효과적이었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.