Johny
Johny

Reputation: 625

Pre-load WebView during the Video Splash Screen in Android

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!

Upvotes: 1

Views: 2297

Answers (3)

Johny
Johny

Reputation: 625

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

Upvotes: 1

android developer
android developer

Reputation: 115952

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

Upvotes: 3

neteinstein
neteinstein

Reputation: 17613

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)

Upvotes: 0

Related Questions