在后台运行WebView



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

据我所知,webview必须从UI线程中进行操作,这使得事情变得更加困难。

关于如何让应用程序通知用户,无论他们是否打开应用程序,有任何建议/解决方案吗?

当WebView需要在一个线程中被操作时,它不一定需要是UI线程(除非你想将WebView附加到视图层次结构中),但是它需要是所有WebView的同一个线程。

虽然它不是明确支持(或大量测试)的东西,但WebView没有做什么特别的事情来阻止你在服务中运行它。WebView确实在Context中调用了一些通常在Service中不起作用的方法(比如getTheme()),所以你必须用一个ContextWrapper来解决这个问题。你还需要手动调用WebView.layout来欺骗WebView认为它有一个大小。你可能需要做更多的事情,但没有其他的事情会出现在脑海中。

你是说真的吗?

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

你不能从后台线程扩展或修改任何视图。但是如果你想要一个网页的内容,你可以在后台线程中使用HTTP GET获取它。您需要对url使用GET来获取它的HTML数据。

它将检查是否有可能运行WebView实例,并以编程方式控制它加载页面,而不必在页面加载期间占用屏幕。然后,当你知道你有材料加载,我会想切换到它的显示在瞬间。我将做一些测试,看看是否可以在移动设备上实现。

我发现Ori Harel在https://medium.com/@oriharel/how-to-run-javascript-code-in-a-background-service-on- android8ec1a12ebe92:

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);
    }
    ...
}

最新更新