Android: uso de WebView fuera de un contexto de actividad

Estoy tratando de lograr Web Scraping a través de un IntentService de fondo que raspa periódicamente un sitio web sin una visualización en el teléfono de los usuarios.

  • Como tengo que llamar un javascript en la página cargada, no puedo usar ningún HttpGet, etc.
  • Por lo tanto, tengo que usar una instancia de WebView que solo se puede ejecutar en una secuencia de UI.
  • Cualquier bash de iniciar una actividad que utiliza un WebView da como resultado una vista que entra en primer plano de los teléfonos (según el diseño de actividades de Android).
  • Cualquier bash de usar un WebView fuera del contexto de una Actividad dio como resultado un error que apunta al hecho de que no puede usar WebView en un hilo que no sea UI.
  • Por diversos motivos de complejidad, no puedo considerar el uso de bibliotecas como Rhino para el web scraping sin UI.

¿Hay alguna forma de solucionar este problema?

Puede mostrar una vista web de un servicio. El siguiente código crea una ventana a la que su servicio tiene acceso. La ventana no es visible porque el tamaño es 0 por 0.

public class ServiceWithWebView extends Service { @Override public void onCreate() { super.onCreate(); WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); params.gravity = Gravity.TOP | Gravity.LEFT; params.x = 0; params.y = 0; params.width = 0; params.height = 0; LinearLayout view = new LinearLayout(this); view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)); WebView wv = new WebView(this); wv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); view.addView(wv); wv.loadUrl("http://google.com"); windowManager.addView(view, params); } } 

Además, esto requerirá el permiso android.permission.SYSTEM_ALERT_WINDOW .

Corrígeme si me equivoco, pero la respuesta correcta a esta pregunta es que NO HAY forma posible de utilizar un WebView en el fondo mientras el usuario está haciendo otras cosas en el teléfono sin interrumpir al usuario por medio de una Actividad.

He aplicado las sugerencias de Randy y Code_Yoga: uso de una actividad con “Theme.NoDisplay” para iniciar un servicio en segundo plano con WebView para hacer un poco de trabajo. Sin embargo, aunque no hay vista visible, el cambio a esa actividad por ese segundo para iniciar los servicios interrumpe al usuario (por ejemplo, pausar un juego en ejecución que se estaba reproduciendo).

Noticias totalmente desastrosas para mi aplicación, así que todavía espero que alguien me dé una forma de usar una WebView que no necesite una Actividad (o un sustituto de una WebView que pueda lograr lo mismo)

Puedes usar esto para ocultar la Actividad

   

Hacer esto evitará que la aplicación muestre cualquier actividad. Y luego puedes hacer tus cosas en la Actividad.

la solución fue así, pero con Looper.getMainLooper ():

https://github.com/JonasCz/save-for-offline/blob/master/app/src/main/java/jonas/tool/saveForOffline/ScreenshotService.java

 @Override public void onCreate() { super.onCreate(); //HandlerThread thread = new HandlerThread("ScreenshotService", Process.THREAD_PRIORITY_BACKGROUND); //thread.start(); //mServiceHandler = new ServiceHandler(thread.getLooper()); // not working mServiceHandler = new ServiceHandler(Looper.getMainLooper()); // working } 

con la ayuda de @JonasCz: https://stackoverflow.com/a/28234761/466363

Un WebView no puede existir fuera de una Actividad o Fragmento debido a que es una IU. Sin embargo, esto significa que una Actividad solo es necesaria para crear WebView, no para manejar todas sus solicitudes.

Si crea el WebView invisible en su actividad principal y lo tiene accesible desde un contexto estático, debería poder realizar tareas en la vista en segundo plano desde cualquier lugar, ya que creo que todo el IO de WebView se realiza de forma asincrónica.

Para eliminar el acceso global, siempre puede lanzar un servicio con una referencia a WebView para hacer el trabajo que necesita.

o un sustituto de un WebView que puede lograr el mismo <=== si no desea mostrar la información cargada en la interfaz de usuario, tal vez puede intentar usar HTTP para llamar directamente a la url y procesar la respuesta devuelta por HTTP

Sé que ha pasado un año y medio, pero ahora estoy enfrentando el mismo problema. Lo resolví eventualmente al ejecutar mi código JavaScript dentro de un motor Node que se ejecuta dentro de mi aplicación Android. Se llama JXCore . Puedes echar un vistazo. Además, eche un vistazo a esta muestra que ejecuta Javascript sin WebView. Realmente me gustaría saber qué terminaste usando?

¿Por qué no creas un servicio de fondo que hace el trabajo por ti?

Y luego simplemente sondea los resultados de un servicio web RESTful o incluso utiliza un middleware de mensajería (por ejemplo, ZeroMQ).

Tal vez más elegante si se ajusta a tu caso de uso: deja que el servicio de raspado envíe tus mensajes de aplicación push a través de GCM 🙂