Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebView targeting 29 not showing content

I have an app with this up-to-date declaration:

compileSdkVersion 29
buildToolsVersion '29.0.2'
useLibrary 'org.apache.http.legacy'

defaultConfig {
    minSdkVersion 19
    targetSdkVersion 29
    ...

And also I have few WebViews in app - full sized Activity, Fragment version and also an ad which is fixed size (lets say 300x300dp, centered horizontally) View placed on list with native widgets. This last one is not loading anymore after target update (only this one, all other are working), but when I change (revert) just this on line:

    targetSdkVersion 28

it is working as before update. Whole WebView setting for this ad looks like this:

webView = findViewById(R.id.ad_banner_webview);
webView.setLayerType(Build.VERSION.SDK_INT <= 19 ?
            WebView.LAYER_TYPE_SOFTWARE : // on older devices non-fullactivity webview is blinking/glitching
            WebView.LAYER_TYPE_HARDWARE, null);
webView.setBackgroundColor(Color.TRANSPARENT);
final String userAgent = AppInfo.getInstance(webView.getContext()).getUserAgent();
webView.getSettings().setUserAgentString(userAgent);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setTextZoom(100);
webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new CustomWebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        if (!isDummy)
            webViewContainer.setTag(System.currentTimeMillis());
    }
});

//disabling long touch - text not selectable
webView.setOnLongClickListener(v -> true);
webView.setLongClickable(false);
webView.setHapticFeedbackEnabled(false);

Note that on API 19 (lowest supported) webView has setLayerType(WebView.LAYER_TYPE_SOFTWARE) called and is working always, no matter of targeting...

Question is simple: what is the reason of this behavior and how to fix this?

I was looking in DOCs what may changed my app behavior after target update, but there is no word about WebView. Also I've found some hidden info about changes in rendering by WebView - so-called Trichrome, but still don't have idea is it related - I don't have any special log/output with any clue and issue is present from 5.0 to 10, on these I'm using LAYER_TYPE_HARDWARE

like image 886
snachmsm Avatar asked Sep 23 '19 11:09

snachmsm


1 Answers

turning out that way of loading content matters a lot... we have loadUrl, loadData and loadDataWithBaseURL methods in WebView and all three are treating given input data in a very different ways

in my case problematic was loadData with code similar to this:

<body style="margin: 0; padding: 0"><div class='banner-wrap'>        
<iframe class='html5-iframe' src='https://example.com/html5/123.html#https://example-ads.com/deliver/ad.php?param=123__destination=https%3A%2F%2Fwww.anothersite.com%2F' width='300' height='300'>
</iframe>    
<a href='https://example.com/html5/123.html#https://example-ads.com/deliver/ad.php?param=123__destination=https%3A%2F%2Fwww.anothersite.com%2F' target='_blank'>
</a>    
</div></body>

note that url is html escaped (% present), but with one exception: the # in url. with this character present in URL iframe won't load content... and was loading when targeting <=28. when using loadUrl giving this with-#-url everything works fine no matter of target. but I'm fitting into already exisiting ad distribution system and it won't be changed for app. also I think that manipulating given HTML code to extract src url isn't a proper way (system may be upgraded somehow someday)...

my solution for now is to use base64 and set same encoding for WebView:

String base64version = Base64.encodeToString(htmlData.getBytes(), Base64.DEFAULT);
webView.loadData(base64version, "text/html; charset=UTF-8", "base64");
like image 122
snachmsm Avatar answered Nov 16 '22 20:11

snachmsm