Android:在活动上下文之外使用WebView

我正试图通过一个后台IntentService来实现Web Scraping,它定期地在用户手机上显示一个没有显示视图的网站。

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

有什么办法解决这个问题?

你可以显示一个服务的Web视图。 下面的代码创build一个您的服务可以访问的窗口。 该窗口不可见,因为大小为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的build议:使用“Theme.NoDisplay”的活动来启动一个带有WebView的后台服务来完成一些工作。 然而,即使没有视图可见,为了启动服务而切换到该活动以中断用户(例如暂停正在运行的正在运行的游戏)。

完全灾难性的消息,我的应用程序,所以我仍然希望有人会给我一个方法来使用WebView,不需要一个活动(或替代WebView可以完成相同的)

你可以用这个来隐藏Activity

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

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

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

如果您在主要活动中创build了不可见的WebView,并且可以从静态上下文访问这些WebView,那么您应该能够从任何位置在后台执行视图中的任务,因为我相信所有WebView的IO都是asynchronous完成的。

为了消除全球访问的烦恼,您可以随时启动一个引用WebView的服务来完成您所需要的工作。

解决scheme是这样的,但与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

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

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

你为什么不创build一个后端服务,为你做的刮?

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

也许更符合你的用例更优雅:让Scraping服务通过GCM发送你的应用程序推送消息:)