0

I need to be able to pause and resume an app that uses a WebView based on whether the app is in the foreground or the background. Currently the app, which has audio, keep running in the background making sound when it loses focus, even when I go to the lock screen. This is very annoying to a user! Apart from that the app works well.

My Android app consists entirely of a single WebView that contains a single HTML page. The HTML page contains JavaScript which changes the HTML page over time, the app looks like a book and the book's pages turn. Each book page also has audio associated with it which plays when the page turns. The key point though is its a single self-changing HTML page inside a WebView.

I have read lots and lots of articles about storing state, Android lifecycle, onPause() and onResume() and it all seems to assume you have programmatic control of what's happening inside the app at runtime. But I just have one object, a WebView, and the single HTML page with CSS, JavaScript, audio and images running inside it, which is inaccessible to me.

Here is the cut-down code I thought would work and which seems to be trying to do the right thing, namely when the app pauses it tries to pause the WebView, and when the app resumes it tries to resume the WebView.

public class MainActivity extends AppCompatActivity {
    private WebView mywebview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mywebview = (WebView)findViewById(R.id.webView);
        WebSettings webSettings = mywebview.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowFileAccess();
        webSettings.setAllowFileAccessFromFileURLs();
        webSettings.setAllowUniversalAccessFromFileURLs();
        mywebview.loadUrl("file:///android_asset/book.html");
        mywebview.setWebViewClient(new WebViewClient());
    }

    // Pause/Resume webview on app going to background
    @Override
    public void onPause(){
        super.onPause();
        mywebview.onPause();
    }
    @Override
    public void onResume(){
        super.onResume();
        mywebview.onResume();
    }

}

Unfortunately it doesn't work.

Can someone please advise how to make this work, or if I am taking the wrong approach and what the right approach is. I would really appreciate code examples, I am new to Android Studio.

Mark Kortink
  • 1,770
  • 4
  • 21
  • 36
  • One option if you need interact with the Android framework/lifecycle and want to stay with a WebView/JavaScript is to use an existing third-party framework like: [Apache Cordova](https://cordova.apache.org/docs/en/10.x/guide/overview/index.html) – Morrison Chang Jun 18 '21 at 22:38
  • Does this answer your question? [Android - when exiting a WebView, the audio still keeps playing](https://stackoverflow.com/questions/17689055/android-when-exiting-a-webview-the-audio-still-keeps-playing) – Amin Jun 19 '21 at 01:11
  • @Amin the answer to that question is close to what tried in my code snippets. Thanks – Mark Kortink Jun 19 '21 at 06:54

1 Answers1

-1

After a lot of trial and error and reading the following worked for me.

public class MainActivity extends AppCompatActivity {
    private WebView mywebview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mywebview = (WebView)findViewById(R.id.webView);
        WebSettings webSettings = mywebview.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowFileAccessFromFileURLs(true);
        mywebview.loadUrl("file:///android_asset/book.html");
        mywebview.setWebViewClient(new WebViewClient());
    }

    @Override
    public void onBackPressed(){
        //NO CODE DISABLES BACK BUTTON
        //super.onBackPressed();
        suspendApp();
    }

    // Pause WebView on app going to background
    @Override
    public void onPause(){
        super.onPause();
        suspendApp();
    }

    // Resume WebView on app going to background
    @Override
    public void onResume(){
        super.onResume();
        mywebview.onResume();
    }

    public void suspendApp() {
        mywebview.onPause();
        mywebview.destroy();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
        finish();
    }

}

This solution has the following characteristics.

  1. If the app loses focus because user touches back, home or drawer buttons or a phone call comes in the app stops instantly, including audio, but remains in the drawer of background apps.
  2. If the user reactivates the app from the drawer, it restarts from the beginning, not where it was stopped. For my app this is OK, but may not be what most apps need.

If the destroy() call is omitted the same behaviour happens, but the webview allows the audio to finish before stopping the app. I am assuming this means the onPause() call allows executing JavaScript to complete before it stops the app.

Mark Kortink
  • 1,770
  • 4
  • 21
  • 36