2010-08-07 8 views
20

Estoy experimentando con el uso de un WebView para mostrar contenido Flash dentro de mi actividad. Todo funciona bastante bien, pero cuando el usuario pulsa la tecla de inicio para poner la actividad en segundo plano, el contenido de Flash sigue en funcionamiento (el sonido sigue sonando, etc.)¿Cómo detengo el contenido de Flash en una vista web de Android cuando mi actividad no está visible?

Me he dado cuenta de que tanto el navegador de Android como Dolphin Browser parece evitar este problema y pausar correctamente el contenido de Flash cuando la actividad de exploración se pone en segundo plano.

Idealmente me gustaría una solución que mata a la vista Web por completo si la actividad está acabando, pero hace una pausa de otra manera (básicamente, copiando el comportamiento por defecto del navegador)

Aquí es una prueba sencilla que arme que carga un juego en Kongregate que tiene música de fondo:

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

me tomó un vistazo a la última fuente para el navegador de valores, y parece estar haciendo algo similar (llamando pauseTimers/resumeTimers), aunque temo el código I han estado mirando está desactualizado, porque está llamando funciones que no parecen existir mi.

Comprobé que la llamada a pauseTimers funciona probando con un simple JavaScript setInterval que actualiza un contador. ¿Hay algo más obvio que debería intentar con respecto a la administración de ventanas o vistas?

La documentación para el flash player móvil dice:

Flash Player también se detendrá automáticamente la reproducción SWF no está a la vista o de la aplicación en primer plano, por ejemplo, cuando se recibe una llamada o alarma se apaga, a reducir el uso de la CPU, el uso de la batería y el uso de la memoria.

Esto parece funcionar perfectamente tanto en el navegador de valores como en el navegador Dolphin, pero no en mi aplicación. ¡Cualquier idea/solución sería muy apreciada!

Actualización: Aquí está la función que terminamos agregando a nuestra actividad para hacer que esto funcione. La llamamos con "onPause" en función de la actividad onPause y "onResume" en función de la actividad 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); 
     } 
    } 
} 
+0

¿Cómo llamas esto? ¿Tienes un fragmento de código del uso? –

+1

No es necesario utilizar la reflexión desde el nivel API 11. Simplemente llame al público en los métodos onPause() y onResume() de WebView. – cprcrack

Respuesta

8

no veo donde se ve que BrowserActivity o algo está llamando pauseTimers(). Veo donde onPause() para BrowserActivity finalmente rutas a onPause() de WebView. Sin embargo, onPause() de WebView tiene la anotación @hide y, por lo tanto, no forma parte del SDK. Fruto de la casualidad, parecería que onPause() es lo que quiere, dado el comentario:

Llame a este para detener cualquier procesamiento adicional asociado con este punto de vista y su asociada DOM/plugins/javascript/etc . Para el ejemplo , si se toma la vista fuera de la pantalla, esto podría llamarse reducir el tráfico innecesario de la CPU y/o la red . Cuando la vista es nuevamente "activa", llame a Reanudar().

Tenga en cuenta la referencia a "complementos", que no se menciona en la documentación pauseTimers().

Yo trataría de usar la reflexión para ver si onPause() (y más tarde onResume(), cuando desee que las cosas se reinicien de nuevo) hace lo que necesita. Si lo hace, publique un problema al b.android.com al respecto, pidiéndoles que agreguen estos métodos (o equivalentes) al SDK. Parece que su requisito será común, y una solución que va más allá del SDK no es una buena solución.

+1

La llamada a pauseTimers está dentro del método pauseWebViewTimers de la actividad del navegador. No estaba familiarizado con la anotación @hide, así que es por eso que pensé que tal vez estaba buscando algún tipo de código viejo/diferente. Creo que su sugerencia de intentar invocar OnPause/onResume utilizando la reflexión es excelente, le dejaré saber cómo funciona, ¡gracias! – BenV

+0

Esto funciona perfectamente, muchas gracias por informarme sobre la anotación @hide, ni siquiera me di cuenta de que podía acceder a esos métodos mediante el reflejo. ¡Publicaré un problema en b.android.com como sugirió! – BenV

+0

@BenV: ¡me alegra oír que funcionó! Si lo piensas, pon un comentario aquí con un enlace al problema una vez que lo hayas archivado. Me gustaría vigilar este. – CommonsWare

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

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

Así es como lo llamas en tu actividad ... Funciona como un encanto.

Cuestiones relacionadas