Android TV 应用为什么具有低分辨率的 Web 视图

huangapple go评论65阅读模式
英文:

Why is Android TV app having a Web View with low resolution

问题

我有一个仪表盘网站Grafana),我想在办公室的4K电视上使用带有Google TV4K的Chromecast进行展示我正试图创建一个非常小的Android TV应用程序最低SDK版本API 31),其中包含一个嵌入式Web浏览器用于显示这个静态仪表盘通过将APK上传到我的Google Drive并使用TV File Commander安装将应用程序安装在Chromecast上

当我在Chromecast上启动应用程序时Web视图以低分辨率运行我已将应用程序更改为访问此网站 - 似乎浏览器只以540x960像素运行
https://www.webfx.com/tools/whats-my-browser-size/

我该如何解决这个问题
英文:

I've a dashboard website (Grafana) that I would like to present on my 4K TV in the office using a Chromecast with Google TV (4K). I'm trying to create a very tiny Android TV app (minimum SDK: API 31) with a embedded web browser displaying this static dashboard. The application is installed on the Chromecast by uploading the APK to my Google Drive and installing it using TV File Commander.

When I start the application on my Chromecast the web view is running in low resolution. I've changed the app to visit this website instead -- and it seems that the browser is only running in 540x960 pixels:
https://www.webfx.com/tools/whats-my-browser-size/

How can I fix this?

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_browse_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:deviceIds="tv"
    tools:ignore="MergeRootFrame" >
    <WebView
            android:layout_width="match_parent"
            android:layout_height="match_parent" android:id="@+id/webView"/>
</FrameLayout>

MainActivity

package com.company.browser

import android.os.Bundle
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.fragment.app.FragmentActivity

class MainActivity : FragmentActivity() {

    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        webView = findViewById(R.id.webView)
        val webSettings: WebSettings = webView.settings
        webSettings.domStorageEnabled = true
        webSettings.javaScriptEnabled = true

        webView.loadUrl("https://www.webfx.com/tools/whats-my-browser-size/")
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >

    <uses-permission android:name="android.permission.INTERNET" />

    <uses-feature
        android:name="android.hardware.touchscreen"
        android:required="false" />
    <uses-feature
        android:name="android.software.leanback"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.Browser" >
        <activity
            android:name=".MainActivity"
            android:banner="@drawable/app_icon_your_company"
            android:exported="true"
            android:icon="@drawable/app_icon_your_company"
            android:label="@string/app_name"
            android:logo="@drawable/app_icon_your_company"
            android:screenOrientation="landscape" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

答案1

得分: 3

WebViews在Android TV上非常令人沮丧(至少对我来说是这样)。希望这能帮助您理解根本原因以及解决方法。

540x960分辨率来自哪里?

WebFx浏览器大小工具显示CSS像素。这些是逻辑像素,并以某种方式映射到物理屏幕像素,以考虑dpi。
我见过的大多数Android TV设备的 window.devicePixelRatio == 4。如果您可以访问JS控制台,您可以轻松检查它。

这意味着每个逻辑像素有4个物理像素。

4K是3840x2160

4K / 4 正好是540x960

devicePixelRatio 从哪里来,为什么是4?

WebView的 devicePixelRatio 是以与Android UI中的密度独立像素相同的方式计算的。

1:1的密度为160,其他密度桶是其倍数或分数。

您可以使用以下adb命令检查您设备的密度:

$ adb shell wm density
物理密度:640

上面的值(640)来自我的Chromecast。现在,根据上面的图像指南,它是640 = 160 * 4,或者是1:1密度的4倍。WebView由Chrome支持,执行此数学运算并将 window.devicePixelRatio 设置为4。除非您擅长打补丁并从头构建Chromium,否则无法访问该代码。

顺便说一下,Android 4K TV模拟器上的密度也是相同的(640)。您可以将其用于调试和实验。

密度640从哪里来?它是由设备开发人员在构建设备固件时设置的。

如何处理所有这些密度问题?

这是我脑海中出现的三个基本选项,但这并不是详尽无遗的列表,只是为了引导您朝正确的方向前进。

调整网页

您可以完全调整页面的CSS以考虑屏幕密度,使用 -webkit-device-pixel-ratio

#header {
    /* 尺寸 */
}

@media screen and (-webkit-device-pixel-ratio: 1.5) {
    /* 高密度屏幕的CSS */
    #header {
        /* 覆盖的尺寸或缩放值等。 */
    }
}

更多细节请参阅:
https://developer.android.com/develop/ui/views/layout/webapps/targeting#DensityCSS

调整设备的密度设置

这将影响每个应用程序的用户界面,并增加GPU的负担,但仍然是一个有效的选项。

$ adb shell wm density ${YOUR_DENSITY_VALUE}

窃取并注入页面缩放到加载的页面

非常繁琐,但有效。

webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        view?.loadUrl("javascript:document.body.style.zoom = 1/window.devicePixelRatio;")
        super.onPageFinished(view, url)
    }
}
英文:

WebViews on Android TVs are quite frustrating (at least for me). Hope this helps you to understand the root cause and the approaches to address it.

Where does the 540x960 resolution come from?

The WebFx browser size tool shows you the CSS pixels. Those are logical and mapped onto physical screen pixels in a certain way to take dpi into account.
Most of Android TV dongles I've seen have window.devicePixelRatio == 4. You can easily check it if you have access to JS console.

It means that it's 4 physical pixels per logical one.

4K is 3840x2160

4K / 4 is exactly 540x960

Where does devicePixelRatio come from and why 4?

devicePixelRatio for WebView is calculated the same way as density independent pixels in android UI.

Android TV 应用为什么具有低分辨率的 Web 视图

1:1 density is 160, other density buckets are multiples or fractions of it.

You can check your device's density using the following adb command:

$ adb shell wm density
Physical density: 640

The value above (640) is from my Chromecast. Now following the guidance on the image above it's 640 = 160 * 4 or 4x the 1:1 density. WebView backed by chrome does this math and sets window.devicePixelRatio to 4. That code is not accessible unless you're into patching and building chromium from scratch.

The density is the same (640) on Android 4K TV emulator, by the way. You can use it for debugging and experiments.

Where does density of 640 come from? It's set by device developers when they build the device's firmware.

How to deal with all of these density issues?

These are the three basic options that come into my mind, but it's not an exhaustive list, just to push you to the right direction.

Adjust the web page

You can fully adjust CSS of your page to take screen density into account using -webkit-device-pixel-ratio

#header {
    /* dimensions */
}

@media screen and (-webkit-device-pixel-ratio: 1.5) {
    /* CSS for high-density screens */
    #header {
        /* overridden dimensions or scale value etc. */
    }
}

More details here:
https://developer.android.com/develop/ui/views/layout/webapps/targeting#DensityCSS

Adjust device's density setting

It will affect the UI of every app and increase the load on GPU, but still a valid option.

$ adb shell wm density ${YOUR_DENSITY_VALUE}

Hack and inject page scaling into the loaded page

Very hacky, but works.

webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        view?.loadUrl("javascript:document.body.style.zoom = 1/window.devicePixelRatio;")
        super.onPageFinished(view, url)
    }
}

huangapple
  • 本文由 发表于 2023年6月8日 03:11:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76426418.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定