Android: Uso de WebView fuera de un contexto de actividad

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

  • Ya que tengo que hacer llamar a algunos javascript en la página cargada no puedo utilizar cualquier HttpGet, etc
  • Por lo tanto, tengo que utilizar una instancia de WebView que sólo se puede ejecutar en un hilo de interfaz de usuario.
  • Cualquier intento de iniciar una actividad que utilice un WebView resulta en una vista que llega al primer plano de los teléfonos (según el diseño de actividades de Android)
  • Cualquier intento de utilizar un WebView fuera de un contexto de actividad generó un error al indicar que no se puede usar WebView en un subproceso no perteneciente a la interfaz de usuario.
  • Por varias razones de complejidad, no puedo considerar el uso de bibliotecas como Rhino para el raspado web sin interfaz de usuario.

¿Hay alguna forma de solucionar este problema?

Puede mostrar una vista web desde un servicio. El código siguiente 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); } } 

También esto requerirá el permiso android.permission.SYSTEM_ALERT_WINDOW .

Corregirme si estoy equivocado, pero la respuesta correcta a esta pregunta es que no hay manera posible de usar un WebView en segundo plano 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: Usar una actividad con "Theme.NoDisplay" para lanzar un servicio de fondo con un WebView para hacer algo de trabajo. Sin embargo, aunque ninguna vista sea visible, el cambio a esa actividad para ese segundo para iniciar los servicios interrumpe al usuario (por ejemplo, detener un juego en ejecución que se estaba reproduciendo).

Noticias totalmente desastrosas para mi aplicación así que todavía estoy esperando que alguien me dará una manera de usar un WebView que no necesita una actividad (o un sustituto de un WebView que puede lograr lo mismo)

Puede usar esto para ocultar la Actividad

  <activity android:name="MyActivity" android:label="@string/app_name" android:theme="@android:style/Theme.NoDisplay"> 

Hacer esto evitará que la aplicación muestre cualquier actividad. Y entonces usted puede hacer sus cosas en la Actividad.

Un WebView no puede existir fuera de una Actividad o Fragmento debido a que es una interfaz de usuario. Sin embargo, esto significa que sólo se necesita una Actividad para crear el WebView, no manejar todas sus solicitudes.

Si crea el WebView invisible en su actividad principal y lo tiene accesible desde un contexto estático, debería ser capaz de realizar tareas en la vista en segundo plano desde cualquier lugar, ya que creo que todas las E / S de WebView se realizan asincrónicamente.

Para quitar el ick de ese acceso global, usted podría lanzar siempre un servicio con una referencia al WebView para hacer el trabajo que usted necesita.

La solución era 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

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 usted puede tratar de utilizar HTTP para llamar a la url directamente, y el proceso en la respuesta devuelta de HTTP

Sé que ha sido un año y medio, pero ahora estoy enfrentando el mismo problema. Lo solucioné eventualmente ejecutando mi código Javascript dentro de un motor de nodo que se ejecuta dentro de mi aplicación para Android. Se llama JXCore . Puedes echar un vistazo. También, eche un vistazo a este ejemplo que ejecuta Javascript sin WebView. Realmente me gustaría saber lo que terminó usando?

¿Por qué no crear un servicio de backend que hace el raspado para usted?

Y luego sólo los resultados de la encuesta de un Webservice RESTful o incluso utilizar un middleware de mensajería (por ejemplo, ZeroMQ).

Tal vez más elegante si se ajusta a su caso de uso: deje que el servicio de raspado envíe sus mensajes Push de aplicación a través de GCM 🙂

  • Cómo comprobar si se inició IntentService
  • IntentService onHandleIntent () sigue funcionando después de onDestroy () despedido
  • ¿Qué sucede cuando mi actividad se destruye cuando estoy usando IntentService con ResultReceiver
  • Android IntentService Error de instancia
  • Capturar IntentService Intents antes onHandleIntent
  • IntentService responde a muertos ResultReceiver
  • ¿Es seguro el método onStartCommand (...) de IntentService?
  • ¿El enfoque de diseño de la aplicación de cliente restante en google io 2010 sigue actualizado?
  • Cómo crear tostadas de IntentService? Se queda atascado en la pantalla
  • Android LocationLister implementado en IntentService nunca ejecuta el método OnLocationChanged ()
  • Evitar que el "proceso de Android" sea un error "incorrecto"
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.