1

I am working in an Android app and I want to preload splash screen while the webView is loading the webpage BUT i have a local .mp4 video instead of a picture.

So once the user clicks the app, the .mp4 will start playing (4 seconds). During that 4 seconds the webView should pre-load the webpage SO when the video is finished show my web page (if the web page is already loaded), otherwise wait in the splash screen until the webpage is ready and then load it.

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

Here is the 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();

    }
}

Here is the 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_width="match_parent"
    android:layout_height="match_parent"
    tools:context="test.test_android.MainActivity">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

Here is the 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_width="match_parent"
    android:layout_height="match_parent"
    tools:context="test.test.AnimationScreenActivity">

    <VideoView
        android:id="@+id/videoView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        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>

And finally the Manifest.xml where i set MainActivity as LAUNCHER:

<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"/>

So what i have until now is that once the user starts the app, the .mp4 starts and when the .mp4 finish THEN it waits for 10 seconds in the AnimationScreenActivity and THEN it loads the webpage.

Any help will be appreciated!

Johny
  • 625
  • 2
  • 6
  • 26

3 Answers3

3

You can have a single Activity that has what you have on the 2 Activities, by having a ViewSwitcher (or ViewAnimator) to switch between the layouts. This will also remove the need for the SPLASH_LOCK object.

While loading, switch the ViewSwitcher (or ViewAnimator) to the layout of the video, and when you are done loading the page, switch it to the layout of the WebView.

I've made a simple code to make it easier to switch between view. If you wish, you can use it:

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

Usage:

setViewToSwitchTo(viewSwitcher, R.id.webViewLayout);

or:

setViewToSwitchTo(viewSwitcher, webViewLayout);

You can even have an animation when switching between the views, using "inAnimation" and "outAnimation" attributes.

And, if the code gets too large, you can have fragments instead of views. One for the WebView, and another for the video.

About onPageFinished being called multiple times, you need to check which of them is the one that you consider as really being finished. Since each website is different, and can have multiple frames, you will have to add this logic. If you want, you can monitor onPageStarted, as shown here:

BTW, if you change the orientation in the manifest, do note that since you have a WebView, you will have to think what to do with orientation change, because it doesn't restore its state well.


EDIT:

Here's the layout file:

<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/viewSwitcher"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="test.test_android.MainActivity">

    <VideoView
        android:id="@+id/videoView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />

</ViewSwitcher>

in the onCreate, use the code of both of your activities, and add this to go to the video :

setViewToSwitchTo(viewSwitcher, R.id.videoView1);

and this to go to the webView (when it has done loading, in your case) :

setViewToSwitchTo(viewSwitcher, R.id.webView);
Community
  • 1
  • 1
android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • Thanks for your answer! `onPageFinished` is not called multiple times. The reason I change the orientation in Manifest is because I want it to be always in portrait mode. Also if I use ViewSwitcher or ViewAnimator, how will this solve the issue about the loading of the web during the splash (animation) ? Is it possible to provide me code how to do this? – Johny Apr 04 '17 at 08:03
  • So I have to use one of the two codes you provided? And how I can use it in my code? – Johny Apr 04 '17 at 08:47
  • Yes, it will work fine. The layout of the activity will have the ViewSwitcher as the parent of : the one of the webView, and the one with the video. – android developer Apr 04 '17 at 09:38
  • I have update my question with the two layouts, if possible can you help me how to combine them in one using `viewSwitcher`? – Johny Apr 04 '17 at 10:12
  • You only need to create a layout that has ViewSwitcher as a parent of a WebView and VideoView . Switch between them according to what occurs. If you use ViewAnimator, you can also add another view for error state (because the webView can have errors too). – android developer Apr 04 '17 at 11:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139845/discussion-between-johny-and-android-developer). – Johny Apr 04 '17 at 11:47
  • Updated answer yet again, with full layout & explanation of what to do with the code. – android developer Apr 04 '17 at 12:10
1

After a lot of help from @android developer (many thanks!) and stackoverflow posts, I have combined both activities MainActivity, AnimationScreenActivity in one activity (MainActivity).

Here is the code:

    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;
                }
        }
    }
Johny
  • 625
  • 2
  • 6
  • 26
0

My suggestion would be to avoid having 2 activities, I suspect that's one of your problems.

Have only one Activity with the VideoView and the WebView both inside a RelativeLayout so that VideoView is above the WebView.

When the WebView is ready, simply VideoView.setVisibity(View.GONE)

neteinstein
  • 17,529
  • 11
  • 93
  • 123
  • Thank you for your answer, but if i do VideoView.setVisibity(View.GONE) it will stop video in the middle, where i want it to finish no matter what and then load the webpage. Also do you mean have one activity and one layout as well for both VideoView and WebView ? – Johny Mar 20 '17 at 09:42
  • @Johny I mean you change the visibility when the video ends and the WebView is loaded. Exactly the same as your code but on a single Activity. – neteinstein Mar 20 '17 at 14:38
  • So first I have to use only one Layout that will have both VideoView and WebView (instead of 2 Layouts) and also one Activity that will do all also the Video part and the WebView. I will try this but is it possible to write the code how it should be? – Johny Mar 20 '17 at 14:52
  • @netesinstein i find out that when i Log in the `onPageFinished` that it is been called three times. Other people had the same issue, they used `onPageStarted` and `shouldOverrideUrlLoading` but i tried it with no result. – Johny Mar 20 '17 at 16:46
  • That can happen. To avoid that use this: http://stackoverflow.com/questions/3149216/how-to-listen-for-a-webview-finishing-loading-a-url/5172952#5172952 – neteinstein Mar 21 '17 at 14:52
  • @ neteinstein i managed to solve the issue with multiple calling of `onPageFinished`, but i am still stuck with the main issue (Pre-load WebView during the Video Splash Screen in Android). Is it possible to write code how it should like? – Johny Mar 22 '17 at 12:33