Android:在Activity上下文之外使用WebView

我正在尝试通过后台IntentService实现Web Scraping,该后台定期抓取网站而不在用户手机上显示视图。

  • 因为我必须在加载的页面上调用一些javascript,所以我不能使用任何HttpGet等。
  • 因此,我必须使用只能在UI线程上运行的WebView实例。
  • 任何尝试启动使用WebView的Activity都会导致View进入手机前景(根据Android的活动设计)
  • 任何在Activity上下文之外使用WebView的尝试都会导致错误,指出您无法在非UI线程上使用WebView。
  • 出于各种复杂性的原因,我不能考虑使用像Rhino这样的库来实现无UI的网页抓取。

有什么方法可以解决这个问题吗?

Solutions Collecting From Web of "Android:在Activity上下文之外使用WebView"

您可以从服务显示Web视图。 下面的代码创建了一个您的服务可以访问的窗口。 窗口不可见,因为大小为0乘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); } } 

这也需要android.permission.SYSTEM_ALERT_WINDOW权限。

如果我错了,请纠正我,但对这个问题的正确答案是,当用户在手机上做其他事情而不通过活动中断用户时,没有办法在后台使用WebView。

我已经应用了Randy和Code_Yoga的建议:使用带有“Theme.NoDisplay”的活动来启动带有WebView的后台服务来完成一些工作。 然而,即使没有可见的视图,在第二次启动服务时切换到该活动会中断用户(例如,暂停正在播放的正在运行的游戏)。

对于我的应用程序来说完全是灾难性的消息,所以我仍然希望有人能给我一种方法来使用不需要Activity的WebView(或者可以替代可以实现相同function的WebView)

您可以使用它来隐藏活动

   

这样做会阻止应用显示任何活动。 然后你可以在Activity中做你的东西。

解决方案是这样的,但使用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 } 

在@JonasCz的帮助下: https ://stackoverflow.com/a/28234761/466363

由于它是一个UI,因此WebView不能存在于Activity或Fragment之外。 但是,这意味着只需要一个Activity来创建WebView,而不是处理它的所有请求。

如果在主活动中创建不可见的WebView并使其可以从静态上下文访问,那么您应该能够在任何地方在后台执行视图中的任务,因为我相信所有WebView的IO都是异步完成的。

要消除全局访问的ick,您可以随时启动一个带有WebView引用的服务来完成您需要的工作。

或者可以完成相同的WebView的替代< ===如果你不希望在UI上显示加载的信息,也许你可以尝试使用HTTP直接调用url,并处理来自HTTP的返回响应

我知道这已经过了一年半,但我现在面临同样的问题。 我最终通过在我的Android应用程序中运行的Node引擎中运行我的Javascript代码来解决它。 它叫做JXCore 。 你可以看看。 另外,看一下在没有WebView的情况下运行Javascript的示例 。 我真的很想知道你最终使用了什么?

为什么不创建一个为您进行抓取的后端服务?

然后,您只需从RESTful Web服务轮询结果,甚至使用消息传递中间件(例如ZeroMQ)。

如果它适合您的使用案例,可能更优雅:让Scraping Service通过GCM发送您的应用程序推送消息:)