Как приостановить Flash-контент в Android WebView, когда моя активность не видна?

Я экспериментирую с использованием WebView для отображения Flash-контента внутри моей активности. Все работает довольно хорошо, но когда пользователь нажимает клавишу «Домой», чтобы перевести действие в фоновый режим, содержимое Flash продолжает работать (продолжает воспроизводиться звук и т. д.)

Я заметил, что и стандартный браузер Android, и браузер Dolphin, по-видимому, избегают этой проблемы и правильно приостанавливают содержимое Flash, когда активность просмотра переводится в фоновый режим.

В идеале я хотел бы решение, которое полностью убивает WebView, если действие завершается, но приостанавливает его в противном случае (в основном копируя поведение браузера по умолчанию)

Вот простой тест, который я собрал, загружая игру на Kongregate с фоновой музыкой:

    public class BrowserTest extends Activity {
    private WebView mWebView;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            mWebView = new WebView(this);
            mWebView.getSettings().setJavaScriptEnabled(true);
            mWebView.getSettings().setPluginsEnabled(true);

            mWebView.loadUrl("http://m.kongregate.com/games/Jiggmin/the-game-of-disorientation-mobile");
            setContentView(mWebView);
        }

        @Override
        protected void onPause(){
            super.onPause();

            mWebView.pauseTimers();
            if(isFinishing()){
                mWebView.loadUrl("about:blank");
                setContentView(new FrameLayout(this));
            }
        }

        @Override
        protected void onResume(){
            super.onResume();
            mWebView.resumeTimers();
        }
    }

Я взглянул на последний исходный код для стандартного браузера, и, похоже, он делает что-то похожее (вызывает pauseTimers/resumeTimers), хотя я боюсь, что код, на который я смотрел, устарел, потому что он вызывает функции, которые не кажется, больше не существует.

Я убедился, что вызов pauseTimers работает, протестировав простой JavaScript setInterval, который обновляет счетчик. Есть ли что-то еще очевидное, что я должен попробовать в отношении управления окнами или представлениями?

В документации к мобильному Flash player сказано:

Flash Player также автоматически приостанавливает воспроизведение SWF-файла, если он не находится в поле зрения или не является активным приложением, например, при поступлении вызова или срабатывании будильника, чтобы снизить нагрузку на ЦП, аккумулятор и память.

Кажется, это отлично работает как в стандартном браузере, так и в браузере Dolphin, но не в моем приложении. Буду признателен за любые идеи/решения!

Обновление: вот функция, которую мы добавили в нашу активность, чтобы заставить ее работать. Мы вызываем его с помощью «onPause» в функции onPause активности и «onResume» в функции onResume активности:

private void callHiddenWebViewMethod(String name){
    if( mWebView != null ){
        try {
            Method method = WebView.class.getMethod(name);
            method.invoke(mWebView);
        } catch (NoSuchMethodException e) {
            Log.error("No such method: " + name, e);
        } catch (IllegalAccessException e) {
            Log.error("Illegal Access: " + name, e);
        } catch (InvocationTargetException e) {
            Log.error("Invocation Target Exception: " + name, e);
        }
    }
}

person BenV    schedule 07.08.2010    source источник
comment
Как вы это называете? У вас есть фрагмент кода использования?   -  person Rijvi Rajib    schedule 24.04.2011
comment
Нет необходимости использовать отражение, начиная с уровня API 11. Просто вызовите общедоступные методы onPause() и onResume() WebView.   -  person cprcrack    schedule 01.05.2013


Ответы (2)


Я не вижу, где вы видите, что BrowserActivity или что-то еще звонит pauseTimers(). Я вижу, где onPause() для BrowserActivity в конечном итоге ведет к onPause() из WebView. Однако onPause() из WebView имеет аннотацию @hide и поэтому не является частью SDK. Неожиданно может показаться, что onPause() — это то, что вам нужно, учитывая комментарий:

Вызовите это, чтобы приостановить любую дополнительную обработку, связанную с этим представлением и связанными с ним DOM/плагинами/javascript/и т. д. Например, если представление выводится за пределы экрана, это может быть вызвано для уменьшения ненужного трафика ЦП и/или сетевого трафика. Когда представление снова станет «активным», вызовите onResume().

Обратите внимание на ссылку на «плагины», которая не упоминается в документации pauseTimers().

Я бы попробовал использовать отражение, чтобы увидеть, делает ли onPause() (и позже onResume(), когда вы хотите, чтобы что-то снова запустилось) то, что вам нужно. Если это так, отправьте сообщение об этом на b.android.com с просьбой добавить эти методы (или эквиваленты) в SDK. Похоже, что ваше требование будет общим, и решение, выходящее за рамки SDK, не является хорошим решением.

person CommonsWare    schedule 07.08.2010
comment
Вызов pauseTimers находится внутри метода pauseWebViewTimers действия Browser. Я не был знаком с аннотацией @hide, поэтому подумал, что, возможно, просматриваю какой-то старый/другой код. Я думаю, что ваше предложение попытаться вызвать onPause/onResume с использованием отражения является отличным, я дам вам знать, как это работает, спасибо! - person BenV; 08.08.2010
comment
Это отлично работает, большое спасибо за то, что рассказали мне об аннотации @hide, я даже не осознавал, что могу добраться до этих методов с помощью отражения. Я опубликую вопрос на b.android.com, как вы предложили! - person BenV; 08.08.2010
comment
@BenV: рад слышать, что это сработало! Если вы думаете об этом, разместите здесь комментарий со ссылкой на проблему, как только вы ее зарегистрируете. Я хотел бы следить за этим. - person CommonsWare; 08.08.2010
comment
Не проблема, вот ссылка на проблему: code.google. com/p/android/issues/detail?id=10282 - person BenV; 08.08.2010
comment
К вашему сведению: WebView.onPause() и WebView.onResume() теперь общедоступны в API уровня 11 и новее. - person jenzz; 11.12.2012
comment
Вызов onPause webView в onPause Activity приводит к остановке воспроизведения, когда включен полноэкранный режим. @Override public void onPause() { super.onPause(); попробуйте { Class.forName(android.webkit.WebView).getMethod(onPause, (Class[]) null).invoke(webView, (Object[]) null); } catch (Исключение e) { e.printStackTrace(); } } Какие-либо предложения ? - person subair_a; 30.01.2013

@Override
protected void onPause() {
    super.onPause();
    this.callHiddenWebViewMethod("onPause");
}

@Override
protected void onResume() {
    super.onResume();
    this.callHiddenWebViewMethod("onResume");
}

Вот как вы это называете в своей деятельности... Работает как шарм.

person Evan Leis    schedule 10.01.2012