在 Android 的视频闪屏期间预加载 WebView
Posted
技术标签:
【中文标题】在 Android 的视频闪屏期间预加载 WebView【英文标题】:Pre-load WebView during the Video Splash Screen in Android 【发布时间】:2017-03-16 11:25:35 【问题描述】:我正在使用 android 应用程序,我想在 webView 加载网页时预加载启动画面但是我有一个本地 .mp4 视频而不是图片。
因此,一旦用户点击应用,.mp4 文件就会开始播放(4 秒)。在这 4 秒内,webView 应该 pre-load 网页 SO 当视频完成时显示我的网页(如果网页已经加载),否则在启动画面,直到网页准备就绪,然后加载它。
这是我的 MainActivity:
public class MainActivity extends AppCompatActivity
private WebView webView;
public static final Object SPLASH_LOCK = new Object();
@Override
protected void onCreate(Bundle savedInstanceState)
String myURL = "https://www.testpage.com";
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setAllowContentAccess(true);
/** tell the webView to enable javascript execution */
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webSettings.getAllowFileAccessFromFileURLs();
webSettings.getAllowUniversalAccessFromFileURLs();
/** Load the html page */
webView.loadUrl(myURL);
/** Call the JavaScriptInterface within the WebView */
webView.addJavascriptInterface(this, "jsinterface");
startActivity(new Intent(this, AnimationScreenActivity.class));
/** Enable Javascript in WebView
/ callback for browser events */
webView.setWebViewClient(new WebViewClient()
@Override
public void onPageFinished (WebView webView, String url)
synchronized (SPLASH_LOCK)
SPLASH_LOCK.notifyAll();
);
这里是 AnimationScreenActivity:
public class AnimationScreenActivity extends AppCompatActivity
private static String TAG = AnimationScreenActivity.class.getName();
private static long MAX_SPLASH_TIME = 10000;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.animation_screen);
try
VideoView videoHolder = (VideoView) findViewById(R.id.videoView1);
Uri video = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.myvideo);
videoHolder.setVideoURI(video);
videoHolder.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
public void onCompletion(MediaPlayer mp)
jump();
);
videoHolder.start();
catch (Exception ex) jump();
private void jump()
new Thread()
@Override
public void run()
synchronized (MainActivity.SPLASH_LOCK)
// wait for notify or time-out
try
MainActivity.SPLASH_LOCK.wait(MAX_SPLASH_TIME);
catch (InterruptedException ignored)
finish();
.start();
这里是activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_
android:layout_
tools:context="test.test_android.MainActivity">
<WebView
android:id="@+id/webView"
android:layout_
android:layout_ />
</RelativeLayout>
这里是animation_screen_activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/animation_screen"
android:layout_
android:layout_
tools:context="test.test.AnimationScreenActivity">
<VideoView
android:id="@+id/videoView1"
android:layout_
android:layout_
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:layout_alignParentRight="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
最后是我将 MainActivity 设置为 LAUNCHER 的 Manifest.xml:
<activity android:name=".MainActivity"
android:theme="@style/FullScreenTheme"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".AnimationScreenActivity"
android:theme="@style/FullScreenTheme"
android:screenOrientation="portrait"/>
所以到目前为止我所拥有的是,一旦用户启动应用程序,.mp4 就会启动,当 .mp4 完成时 THEN 它会在 AnimationScreenActivity 中等待 10 秒,然后 THEN 加载网页。
任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:您可以拥有一个拥有 2 个 Activity 的单一 Activity,方法是让 ViewSwitcher(或 ViewAnimator)在布局之间切换。 这也将消除对 SPLASH_LOCK 对象的需要。
加载时,将ViewSwitcher(或ViewAnimator)切换到视频的布局,加载完页面后,切换到WebView的布局。
我编写了一个简单的代码,以便更轻松地在视图之间切换。如果你愿意,你可以使用它:
public static void setViewToSwitchTo(@NonNull final ViewAnimator viewAnimator, @NonNull final View viewToSwitchTo)
if (viewAnimator == null)
return;
if (viewAnimator.getCurrentView() == viewToSwitchTo)
return;
for (int i = 0; i < viewAnimator.getChildCount(); ++i)
if (viewAnimator.getChildAt(i) == viewToSwitchTo)
viewAnimator.setDisplayedChild(i);
break;
public static void setViewToSwitchTo(@NonNull final ViewAnimator viewAnimator, @IdRes final int viewIdToSwitchTo)
if (viewAnimator == null)
return;
if (viewAnimator.getCurrentView().getId() == viewIdToSwitchTo)
return;
for (int i = 0; i < viewAnimator.getChildCount(); ++i)
if (viewAnimator.getChildAt(i).getId() == viewIdToSwitchTo)
if (viewAnimator.getDisplayedChild() == i)
return;
viewAnimator.setDisplayedChild(i);
return;
用法:
setViewToSwitchTo(viewSwitcher, R.id.webViewLayout);
或:
setViewToSwitchTo(viewSwitcher, webViewLayout);
您甚至可以在视图之间切换时使用“inAnimation”和“outAnimation”属性来制作动画。
而且,如果代码变得太大,您可以使用片段而不是视图。一个用于 WebView,另一个用于视频。
关于 onPageFinished 被多次调用,您需要检查其中哪些是您认为真正完成的。由于每个网站都不同,并且可以有多个框架,因此您必须添加此逻辑。如果需要,可以监控 onPageStarted,如下所示:
https://forums.xamarin.com/discussion/15293/why-is-onpagefinished-firing-off-three-times-for-one-url-load-request https://***.com/a/25547544/878126顺便说一句,如果您更改清单中的方向,请注意,由于您有一个 WebView,您将不得不考虑如何处理方向更改,因为它不能很好地恢复其状态。
编辑:
这是布局文件:
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/viewSwitcher"
android:layout_
android:layout_
tools:context="test.test_android.MainActivity">
<VideoView
android:id="@+id/videoView1"
android:layout_
android:layout_ />
<WebView
android:id="@+id/webView"
android:layout_
android:layout_
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />
</ViewSwitcher>
在 onCreate 中,使用您的两个活动的代码,并将其添加到视频中:
setViewToSwitchTo(viewSwitcher, R.id.videoView1);
这将转到 webView(在您的情况下完成加载后):
setViewToSwitchTo(viewSwitcher, R.id.webView);
【讨论】:
感谢您的回答!onPageFinished
不会被多次调用。我在 Manifest 中更改方向的原因是因为我希望它始终处于纵向模式。另外,如果我使用 ViewSwitcher 或 ViewAnimator,这将如何解决在启动(动画)期间加载网页的问题?是否可以向我提供如何执行此操作的代码?
所以我必须使用您提供的两个代码之一?以及如何在我的代码中使用它?
是的,它可以正常工作。 Activity 的布局将 ViewSwitcher 作为父级:webView 之一,视频的一个。
我已经用这两种布局更新了我的问题,如果可能的话,你能帮我如何使用viewSwitcher
将它们组合成一个吗?
您只需要创建一个布局,其中 ViewSwitcher 作为 WebView 和 VideoView 的父级。根据发生的情况在它们之间切换。如果你使用 ViewAnimator,你还可以为错误状态添加另一个视图(因为 webView 也可能有错误)。【参考方案2】:
在 @android 开发者(非常感谢!)和 *** 帖子的大力帮助下,我将 MainActivity
、AnimationScreenActivity
两个活动合并到一个活动 (MainActivity) 中。
代码如下:
public class MainActivity extends AppCompatActivity
private String myURL = "https://www.testpage.com";
VideoView videoView;
ViewSwitcher viewSwitcher;
private WebView webView;
private boolean hasFinishedLoadingPage;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try
viewSwitcher = (ViewSwitcher) findViewById(R.id.viewSwitcher);
final VideoView videoView = (VideoView) findViewById(R.id.videoView1);
Uri video = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.myvideo);
videoView.setVideoURI(video);
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
@Override
public void onCompletion(MediaPlayer mp)
if (hasFinishedLoadingPage)
setViewToSwitchTo(viewSwitcher, webView);
// else webView.reload();
setViewToSwitchTo(viewSwitcher, webView);
);
videoView.start();
catch (Exception ex)
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setAllowContentAccess(true);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webSettings.getAllowFileAccessFromFileURLs();
webSettings.getAllowUniversalAccessFromFileURLs();
webView.setWebViewClient(new WebViewClient()
boolean isRedirected;
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
return false;
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
super.onPageStarted(view, url, favicon);
if (!isRedirected)
setViewToSwitchTo(viewSwitcher, videoView);
isRedirected = true;
@Override
public void onPageFinished(WebView webView, String url)
super.onPageFinished(webView, url);
hasFinishedLoadingPage = true;
);
/** Callback for web events */
webView.setWebChromeClient(new WebChromeClient()
);
webView.loadUrl(myURL);
public static void setViewToSwitchTo(@NonNull final ViewAnimator viewAnimator, @NonNull final View viewToSwitchTo)
if (viewAnimator == null)
return;
if (viewAnimator.getCurrentView() == viewToSwitchTo)
return;
for (int i = 0; i < viewAnimator.getChildCount(); ++i)
if (viewAnimator.getChildAt(i) == viewToSwitchTo)
viewAnimator.setDisplayedChild(i);
break;
【讨论】:
像魅力一样工作! 真正的救星! 很高兴它可以帮助你:)【参考方案3】:我的建议是避免进行 2 项活动,我怀疑这是您的问题之一。
只有一个带有VideoView
和WebView
的Activity 都在RelativeLayout 中,这样VideoView 就位于WebView 之上。
当 WebView 准备就绪时,只需 VideoView.setVisibity(View.GONE)
【讨论】:
感谢您的回答,但如果我这样做 VideoView.setVisibity(View.GONE) 它将在中间停止视频,我希望它无论如何都完成然后加载网页。你的意思是 VideoView 和 WebView 都有一个活动和一个布局吗? @Johny 我的意思是您在视频结束并加载 WebView 时更改可见性。与您的代码完全相同,但在单个 Activity 上。 所以首先我必须只使用一个同时具有 VideoView 和 WebView(而不是 2 个布局)的布局,以及一个可以同时完成所有视频部分和 WebView 的 Activity。我会试试这个,但有可能写出它应该的代码吗? @netesinstein 我发现当我登录onPageFinished
时,它被调用了三次。其他人也有同样的问题,他们使用了onPageStarted
和shouldOverrideUrlLoading
,但我尝试了没有结果。
这可能会发生。为避免这种情况,请使用:***.com/questions/3149216/…以上是关于在 Android 的视频闪屏期间预加载 WebView的主要内容,如果未能解决你的问题,请参考以下文章
React Native - Android - 应用导航期间闪屏
在 Android 应用程序开发中预加载或预缓冲 .mp4 视频