WebView และ HTML5 <video>


123

ฉันกำลังปะติดปะต่อแอป cheapo ที่มี "เฟรม" บางเว็บไซต์ของเรา ... WebViewClientค่อนข้างเรียบง่ายด้วย. จนกว่าฉันจะเข้าชมวิดีโอ

วิดีโอถูกสร้างขึ้นเป็นHTML5 องค์ประกอบและสิ่งเหล่านี้ทำงานได้ดีบน Chrome, iPhone และตอนนี้เราได้แก้ไขปัญหาการเข้ารหัสแล้วซึ่งใช้งานได้ดีAndroidในเบราว์เซอร์ดั้งเดิม

ตอนนี้ถู: WebViewไม่ชอบ เลย. ฉันสามารถคลิกที่ภาพโปสเตอร์และไม่มีอะไรเกิดขึ้น

Googling ฉันพบสิ่งนี้ซึ่งอยู่ใกล้ แต่ดูเหมือนว่าจะขึ้นอยู่กับ 'ลิงก์' (เช่นเดียวกับ href ... ) แทนที่จะเป็นองค์ประกอบวิดีโอ (onDownloadListener ดูเหมือนจะไม่ถูกเรียกใช้ในองค์ประกอบวิดีโอ ... )

ฉันยังเห็นการอ้างอิงถึงการแทนที่ onShowCustomView แต่ดูเหมือนว่าจะไม่ได้รับการเรียกใช้องค์ประกอบวิดีโอ ... หรือไม่ shouldOverrideUrlLoading ..

ฉันไม่อยากเข้าไป "ดึง xml จากเซิร์ฟเวอร์ฟอร์แมตใหม่ในแอป" .. ด้วยการรักษาเค้าโครงเรื่องราวบนเซิร์ฟเวอร์ฉันสามารถควบคุมเนื้อหาได้ดีขึ้นเล็กน้อยโดยไม่ต้องบังคับให้คนอัปเดตแอป ดังนั้นหากฉันสามารถโน้มน้าวให้ WebView จัดการแท็กเช่นเบราว์เซอร์ดั้งเดิมได้ก็น่าจะดีที่สุด

ฉันขาดอะไรไปอย่างชัดเจน .. แต่ฉันไม่รู้อะไรเลย



ตามบรรทัดเดียวกันนี้ฉันกำลังมองหาโปรแกรมเล่น HTML5 สำหรับเว็บไซต์ของฉัน ฉันควรใช้อะไร?
Wolfpack'08

1
คำตอบของฉันที่นี่: stackoverflow.com/a/16179544/423171
cprcrack

1
ไม่มีอะไรได้ผลฉันจึงดูVideoEnabledWebViewที่นี่stackoverflow.com/questions/15768837/…
EpicPandaForce

คำตอบ:


93

ฉันตอบหัวข้อนี้ในกรณีที่มีคนอ่านและสนใจผลลัพธ์ เป็นไปได้ที่จะดูองค์ประกอบวิดีโอ (แท็ก html5 ของวิดีโอ) ภายใน WebView แต่ฉันต้องบอกว่าฉันต้องจัดการกับมันเป็นเวลาสองสามวัน นี่คือขั้นตอนที่ฉันต้องปฏิบัติตาม:

- ค้นหาวิดีโอที่เข้ารหัสอย่างถูกต้อง

- เมื่อเริ่มต้น WebView ให้ตั้งค่า JavaScript, Plug-ins, WebViewClient และ WebChromeClient

url = สตริงใหม่ ("http://broken-links.com/tests/video/"); 
mWebView = (WebView) findViewById (R.id.webview);
mWebView.setWebChromeClient (chromeClient);
mWebView.setWebViewClient (wvClient);
mWebView.getSettings () setJavaScriptEnabled (จริง).
. 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();
        }
    }
}

- จัดการเหตุการณ์ 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();
}

แต่ตอนนี้ฉันควรจะบอกว่ายังมีปัญหาสำคัญ ฉันสามารถเล่นได้เพียงครั้งเดียว ครั้งที่สองที่ฉันคลิกที่โปรแกรมเลือกจ่ายวิดีโอ (ไม่ว่าจะเป็นโปสเตอร์หรือปุ่มเล่น) ก็ไม่ได้ทำอะไรเลย

ฉันต้องการให้วิดีโอเล่นภายในเฟรม WebView แทนการเปิดหน้าต่าง Media Player แต่นี่เป็นปัญหารองสำหรับฉัน

ฉันหวังว่ามันจะช่วยใครสักคนและฉันก็จะขอบคุณความคิดเห็นหรือข้อเสนอแนะ

Saludos, terícolas


ฉันไม่เรียกใช้ผลลัพธ์ใด ๆ หน้าจอของฉันเป็นสีดำ ฉันต้องการทราบว่าสิ่งนี้ต้องการ thead หรือไม่ รหัสของฉันยาวเกินไปที่นี่คุณสามารถให้ช่องทางการติดต่อฉันหรือเปิดหัวข้ออื่นได้
pengwang

คุณแน่ใจหรือไม่ว่าไม่ใช่ปัญหาการเข้ารหัส ลองใช้ URL ที่ฉันโพสต์ เห็นได้ชัดว่ามันต้องทำงานร่วมกับเบราว์เซอร์ดั้งเดิม
mdelolmo

46
"a" คืออะไร? กิจกรรมแบบนั้นจะเป็นอย่างไร
ราคา Collin

1
@Collin Price a เป็นตัวอย่างของกิจกรรมที่โฮสต์ webview @desgraci ฉันสามารถให้ได้ แต่มีไม่มากนอกจากนั้น ทำให้คลาสขยายWebChromeClientและแทนที่วิธีการที่เกี่ยวข้องที่คุณต้องการ หากคุณยืนยันฉันสามารถอัปโหลดชั้นเรียนที่เหลือได้ในภายหลังเมื่อกลับถึงบ้าน
mdelolmo

6
ไม่ทำงานบน ICS เนื่องจาก getFocusedChild () ไม่ใช่ VideoView แต่เป็น HTML5VFullScreen $ SurfaceVideoView มีความคิดเกี่ยวกับวิธีการทำ 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

ฉันเห็นด้วยกับจอร์จ นี่คือวิธีที่เบราว์เซอร์เนทีฟของ Android ทำงานร่วมกับ VideoView ดูเหมือนว่านี้เป็นรหัสเดียวกับที่นี่code.google.com/p/html5webview ใช้งานได้ดีกับ Android ทุกเวอร์ชัน (ฉันทดสอบบน Android 2.2 ขึ้นไป) มีเพียงสิ่งเดียวที่ฉันต้องการแจ้งให้ทราบคุณควรจำไว้ว่าหากคุณเปลี่ยน SDK เป้าหมายในสิ่งที่สูงกว่า 13 กิจกรรมของคุณจะถูกสร้างขึ้นใหม่เมื่อเปลี่ยนการวางแนว เพื่อหลีกเลี่ยงสิ่งนี้ต่อท้าย screenSize เป็น android: configChanges (แต่ในกรณีนี้คุณจะต้องใช้ min sdk <13) หรือใช้ SDK เป้าหมายเก่า (จากนั้นคุณสามารถเก็บ android: configChanges)
Yuriy Ashaev

2
นี่ทำให้ฉันมีหน้าจอว่างเปล่าสีขาวบน Nexus 7 (Android 4.1) มีความคิดอย่างไรที่จะแก้ไขปัญหานี้
Sahil

ปุ่มย้อนกลับไม่หยุดวิดีโอและเสียงยังคงได้ยินมีความคิดอย่างไรที่จะแก้ไขปัญหานี้
CONvid19

นี่คือสิ่งที่ฉันกำลังค้นหาเหมือนกับขั้นตอนของเบราว์เซอร์ดั้งเดิมทุกประการขอบคุณ Ton Surendra และ Malenkiy
Abhilash

33

คำตอบของ mdelolmo มีประโยชน์อย่างเหลือเชื่อ แต่อย่างที่เขาพูดวิดีโอจะเล่นเพียงครั้งเดียวจากนั้นคุณจะเปิดอีกครั้งไม่ได้

ฉันตรวจสอบสิ่งนี้เล็กน้อยและนี่คือสิ่งที่ฉันพบในกรณีที่นักเดินทาง WebView ที่เบื่อหน่ายเช่นตัวฉันเองสะดุดกับโพสต์นี้ในอนาคต

ก่อนอื่นฉันดูเอกสารของVideoViewและMediaPlayerและเข้าใจวิธีการทำงานที่ดีขึ้น ฉันขอแนะนำอย่างยิ่ง

จากนั้นฉันดูซอร์สโค้ดเพื่อดูว่าเบราว์เซอร์ Android ทำงานอย่างไร ค้นหาหน้าและไปดูว่าพวกเขาจัดการonShowCustomView()อย่างไร พวกเขาให้การอ้างอิงถึงCustomViewCallbackและไปยังมุมมองที่กำหนดเอง

ด้วยทั้งหมดนี้และด้วยคำตอบของ mdelolmo เมื่อคุณทำวิดีโอเสร็จแล้วสิ่งที่คุณต้องทำมีสองสิ่ง อันดับแรกVideoViewที่คุณบันทึกข้อมูลอ้างอิงไว้ให้โทรstopPlayback()ที่จะปล่อยMediaPlayerเพื่อใช้ในภายหลังที่อื่น คุณสามารถดูได้ในซอร์สโค้ดVideoView ประการที่สองในคุณบันทึกการอ้างอิงถึงการโทรCustomViewCallbackCustomViewCallback.onCustomViewHidden()

หลังจากทำสองสิ่งนั้นแล้วคุณสามารถคลิกที่วิดีโอเดียวกันหรือวิดีโออื่น ๆ และจะเปิดขึ้นเหมือนเดิม ไม่จำเป็นต้องรีสตาร์ท WebView ทั้งหมด

หวังว่าจะช่วยได้


อันที่จริงฉันก็แก้ไขได้เช่นกันฉันจำไม่ได้ว่าโพสต์วิธีการแก้ปัญหา เช่นเดียวกับคุณฉันต้องดูโค้ดของเบราว์เซอร์ Android และไม่ต้องเพิ่มอะไรมากฉันใช้ตัวฟัง onCompletion เพื่อหยุดโปรแกรมเล่นแทนและต้องตั้งค่าการเปิดเผยสองสามครั้ง แต่ฉันจะซื้อโซลูชันของคุณ ความนับถือ!
mdelolmo

1
Google Code Search เลิกใช้แล้วฉันคิดว่า BrowserActivity.java เวอร์ชันนี้ (จาก Froyo) สอดคล้องกับที่อธิบายไว้ที่นี่: github.com/android/platform_packages_apps_browser/blob/…
michiakig

โค้ดที่เชื่อมโยงของ @ spacemanki ไม่มีการกล่าวถึง VideoView ใน repo ทั้งหมด ฉันเดาว่า BrowserActivity แตกต่างออกไปในตอนนี้ ฉันยังกลับไปที่การเปิดตัวเอแคลร์ ไม่พบการใช้งานใด ๆ
mxcl

ปัญหาที่ฉันมีทั้งหมดนี้คือสิ่งที่ฉันได้รับกลับมาจาก frame.getFocusedChild (); เป็น HTml5VideoView แทนที่จะเป็น ViewView ดังนั้นสิ่งนี้จึงไม่เหมาะกับฉันและไม่สามารถเปลี่ยนเป็นแบบเต็มหน้าจอได้ :( ฉันใช้ Android 4.1.2
Gonan

1
สิ่งที่ทำให้ฉันในที่สุดก็คือการเพิ่ม: @Override public void onStop () {super.onStop (); mWebView.destroy (); } ถึงกิจกรรม ... webview.destroy () สำคัญมาก
MacD

8

ที่จริงดูเหมือนว่าเพียงพอแล้วที่จะแนบ WebChromeClient หุ้นเข้ากับมุมมองไคลเอนต์เท่านั้น

mWebView.setWebChromeClient(new WebChromeClient());

และคุณต้องเปิดการเร่งด้วยฮาร์ดแวร์!

อย่างน้อยถ้าคุณไม่จำเป็นต้องเล่นวิดีโอแบบเต็มหน้าจอก็ไม่จำเป็นต้องดึง VideoView ออกจาก WebView แล้วดันเข้าไปในมุมมองของกิจกรรม จะเล่นใน rect ที่กำหนดขององค์ประกอบวิดีโอ

มีความคิดอย่างไรในการสกัดกั้นปุ่มขยายวิดีโอ?


คุณสามารถสกัดกั้นได้โดยใช้ WebChromeClient และแทนที่ onShowCustomView
Frank

โปรดระบุว่า Android เวอร์ชันใด การทำงานนี้แตกต่างกันไปสำหรับเวอร์ชันต่างๆ
Ethan_AI

7

ฉันรู้ว่าเธรดนี้มีอายุหลายเดือนแล้ว แต่ฉันพบวิธีแก้ปัญหาสำหรับการเล่นวิดีโอใน WebView โดยไม่ต้องแสดงเต็มหน้าจอ (แต่ยังอยู่ในโปรแกรมเล่นสื่อ ... ) จนถึงตอนนี้ฉันไม่พบคำแนะนำใด ๆ เกี่ยวกับเรื่องนี้ในอินเทอร์เน็ตดังนั้นอาจเป็นเรื่องที่น่าสนใจสำหรับคนอื่น ๆ ฉันยังคงดิ้นรนในบางประเด็น (เช่นการวางโปรแกรมเล่นสื่อในส่วนที่ถูกต้องของหน้าจอไม่รู้ว่าทำไมฉันถึงทำผิด แต่ฉันคิดว่ามันค่อนข้างเล็ก ... )

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

ดังนั้นฉันหวังว่าฉันจะช่วยได้ ... ฉันก็ต้องเล่นกับการเข้ารหัสวิดีโอและเห็นประเภทต่างๆของการใช้ WebView กับวิดีโอ html5 - ในที่สุดโค้ดการทำงานของฉันก็เป็นการผสมผสานระหว่างส่วนโค้ดต่างๆที่ฉันพบใน อินเทอร์เน็ตและบางสิ่งที่ฉันต้องหาด้วยตัวเอง มันเป็นความเจ็บปวดใน a *


บน ICS getFocusedChild () ไม่ส่งคืน VideoView มีความคิดเกี่ยวกับวิธีการทำงานบน ICS หรือไม่?
Pascal

4

วิธีนี้ใช้งานได้ดีจนถึง 2.3 และด้วยการเพิ่ม hardwareaccelerated = true มันยังใช้งานได้ตั้งแต่ 3.0 ถึง ICS ปัญหาหนึ่งที่ฉันกำลังเผชิญอยู่ในขณะนี้คือการเปิดตัวแอปพลิเคชั่นเครื่องเล่นสื่อครั้งที่สองกำลังเกิดปัญหาเพราะฉันไม่ได้หยุดเล่นและปล่อย Media player ในฐานะที่เป็นวัตถุ VideoSurfaceView ซึ่งเราได้รับในฟังก์ชั่น onShowCustomView จาก 3.0 OS นั้นมีความเฉพาะเจาะจงสำหรับเบราว์เซอร์ไม่ใช่วัตถุ VideoView เช่นเดียวกับใน 2.3 OS ฉันจะเข้าถึงและหยุดการเล่นและปล่อยทรัพยากรได้อย่างไร


3

AM คล้ายกับสิ่งที่BrowerActivityทำ สำหรับ FrameLayout.LayoutParams LayoutParameters = ใหม่ FrameLayout.LayoutParams (768, 512);

ฉันคิดว่าเราสามารถใช้ได้

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

แทน.

ปัญหาอีกประการหนึ่งที่ฉันพบคือหากวิดีโอกำลังเล่นและผู้ใช้คลิกปุ่มย้อนกลับในครั้งต่อไปคุณไปที่กิจกรรมนี้ (ด้านบนเดียว) และไม่สามารถเล่นวิดีโอได้ เพื่อแก้ไขปัญหานี้ฉันเรียกว่า

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

ในวิธีการ onBackPressed ของกิจกรรม


2

ฉันรู้ว่านี่เป็นคำถามที่เก่ามาก แต่คุณได้ลองhardwareAccelerated="true"ตั้งค่าสถานะรายการสำหรับแอปพลิเคชันหรือกิจกรรมของคุณแล้วหรือยัง

ด้วยชุดนี้ดูเหมือนว่าจะใช้งานได้โดยไม่มีการปรับเปลี่ยน WebChromeClient (ซึ่งฉันคาดหวังจาก DOM-Element)


2
hardwareAcceleratedเริ่มตั้งแต่ Android 3.0
vbence

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 บางเวอร์ชัน แต่ก็ไม่ได้ใช้ทั้งหมด ทางออกที่ดีที่สุดที่ฉันพบคือใช้Crosswalk Webviewซึ่งได้รับการปรับให้เหมาะกับการรองรับฟีเจอร์ HTML5 และทำงานบน Android 4.1 ขึ้นไป ใช้งานง่ายเหมือนกับ Android WebView เริ่มต้น คุณต้องรวมไลบรารี คุณสามารถดูบทแนะนำง่ายๆเกี่ยวกับการใช้งานได้ที่นี่: https://diego.org/2015/01/07/embedding-crosswalk-in-android-studio/


หมายเหตุ: ทางม้าลายไม่ได้รับการดูแลอีกต่อไป
slhck

1

เห็นได้ชัดว่านี่เป็นไปไม่ได้เลยหากไม่ใช้ JNI เพื่อลงทะเบียนปลั๊กอินเพื่อรับวิดีโอเหตุการณ์ (โดยส่วนตัวแล้วฉันกำลังหลีกเลี่ยง JNI เนื่องจากฉันไม่ต้องการจัดการกับความยุ่งเหยิงเมื่อแท็บเล็ต Android ที่ใช้ Atom ออกมาในอีกไม่กี่เดือนข้างหน้าทำให้สูญเสียความสามารถในการพกพาของ Java ไป)

ทางเลือกเดียวที่แท้จริงคือการสร้างหน้าเว็บใหม่สำหรับ WebView และทำวิดีโอในแบบโรงเรียนเก่าด้วยลิงก์ A HREF ตามที่อ้างถึงใน URL ของ Codelark ด้านบน

เหนอะ


1

เกี่ยวกับการใช้รังผึ้งhardwareaccelerated=trueและpluginstate.on_demandดูเหมือนว่าจะได้ผล


1

ฉันมีปัญหาที่คล้ายกัน ฉันมีไฟล์และวิดีโอ HTML ในโฟลเดอร์ assets ของแอปของฉัน

ดังนั้นวิดีโอจึงอยู่ภายใน APK เนื่องจาก APK เป็นไฟล์ ZIP จริงๆ WebView จึงไม่สามารถอ่านไฟล์วิดีโอได้

การคัดลอกไฟล์ HTML และวิดีโอทั้งหมดลงใน SD-Card ได้ผลสำหรับฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.