在后台运行WebView

时间:2014-05-15 09:43:40

标签: android android-webview android-service android-networking

我正在开发一个应用程序,它利用WebView登录网站,从中提取内容,然后在内容更新时通知用户。我已经获得了WebView来获取内容,但是我需要知道如何将WebView作为服务运行以使其在后台运行。

据我所知,必须从UI线程中操纵WebViews,这会让事情变得更加困难。

有关如何让应用程序通知用户而不管他们是否打开应用程序的任何建议/解决方法?

5 个答案:

答案 0 :(得分:9)

虽然WebView需要在单个线程上进行操作,但它不一定需要是UI线程(除非您想将WebView附加到视图层次结构中),但是它需要与所有的线程相同。网页视图。

虽然它没有明确支持(或经过严格测试),但WebView没有什么特别的功能可以阻止您在服务中运行它。 WebView确实在Context上调用了几个通常不在Service中工作的方法(比如getTheme()),所以你必须使用ContextWrapper解决这个问题。您还需要手动调用WebView.layout来欺骗WebView,使其认为它有一个大小。你可能需要做更多的事情,但没有别的想法。

答案 1 :(得分:2)

你的意思是?

runOnUiThread(new Runnable(){
        public void run() {
            ... something 
        }
    });

答案 2 :(得分:1)

您无法从后台线程中膨胀或修改任何视图。但是,如果您想要网页的内容,可以使用HTTP GET在后台线程中获取它。您需要在网址上使用GET来获取其HTML数据。

答案 3 :(得分:0)

它将检查是否有可能运行一个WebView实例,并以编程方式控制它来加载页面,而不必在页面加载期间占用屏幕。然后,当您知道已装载物料时,我将要立即切换到其显示。我将做一些测试,看是否可以在移动设备上完成。

答案 4 :(得分:0)

我从 https://medium.com/@oriharel/how-to-run-javascript-code-in-a-background-service-on-android-8ec1a12ebe92 的 Ori Harel 找到了一个不错的解决方案:

public class BackgroundService extends Service {

    ...

    @Override
    public int onStartCommand(Intent intent, int flags, int startId{

        
        final WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                      | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT
        );

        params.gravity = Gravity.TOP | Gravity.START;
        params.x = 0;
        params.y = 0;
        params.width = 0;
        params.height = 0;

        final WebView wv = new WebView(this);

        wv.setWebViewClient(new WebViewClient() {

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                Log.d("Error","loading web view: request: "+request+" error: "+error);
            }

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {

                
                if (request.getUrl().toString().contains("/endProcess")) {
                    
                    windowManager.removeView(wv);

                    wv.post(new Runnable() {
                        @Override
                        public void run() {
                            wv.destroy();
                        }
                    });
                    stopSelf();
                    return new WebResourceResponse("bgsType", "someEncoding", null);
                }
                else {
                    return null;
                }
            }
        });
        wv.loadUrl(bgsUrl);
        windowManager.addView(wv, params);
    }

    ...
}