【问题标题】:Determine if a WebView is invisible using only JS仅使用 JS 确定 WebView 是否不可见
【发布时间】:2018-11-16 04:30:20
【问题描述】:

我有一个带有 webView 的 Android 测试应用,如下所示:

<WebView
        android:alpha="0"
        android:id="@+id/myWebView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

我的主要活动加载了一个我正在运行 JS 内容的页面。 JS 使用启用:

webSettings.setJavaScriptEnabled(true);

我的应用上有一个按钮可以将 alpha 值从 0 切换到 1(显示/隐藏 webView)。

有什么“创造性”的方式来检测JS端的变化吗?

我尝试过的事情:

更新:

澄清一下,我正在寻找JS Only解决方案,实际的JS代码是在WebView环境中使用的SDK。

我无法控制 Android 应用,完全控制 WebView 内容。

【问题讨论】:

  • 为什么不能检查 webview 的文档/正文元素的可见性或显示样式?您在使用 Visibility API 时遇到了什么问题?
  • 也许你找到一种方法,从 JS 中截取 WebView 的屏幕截图,看看它是否具有相同的颜色。

标签: javascript android google-chrome android-webview alpha


【解决方案1】:

你可以继承android的WebView,覆盖它的setAlpha方法并添加一些逻辑让网页知道当前的alpha值。

这是一个简化的例子:

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.webkit.WebView;

public class MyWebView extends WebView {

    public MyWebView(Context context) {
        super(context);
        init();
    }

    public MyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public MyWebView(Context context,
                     AttributeSet attrs,
                     int defStyleAttr,
                     int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void init() {
        getSettings().setJavaScriptEnabled(true);
    }

    @Override
    public void setAlpha(float alpha) {
        super.setAlpha(alpha);
        propagateAlphaToWebPage(alpha);
    }

    private void propagateAlphaToWebPage(float alpha) {
        // setWebViewAlpha is a JS function that should be defined in your html's js 
    String jssnippet = "setWebViewAlpha("+alpha+");";
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
        evaluateJavascript(jssnippet, null);
    } else {
        loadUrl("javascript:"+jssnippet);
    }
}
}

其他可能对您有帮助的相关问题:

【讨论】:

  • 感谢您的回复,但我正在寻找仅 JS 的解决方案
  • 哈,是的,我不确定您是否只需要 JS,因为您在问题中添加了 android xml。 Visibility API 有一个非常可靠的示例,唯一的问题是对 android 的支持有点少,请参阅 Visibility API#AutoCompatibilityTable > Mobile
  • 可见性 API 在这里不起作用。我认为@RoniGadot 应该看看浏览器完成的 JS 调整,比如检查 GPU 内存。
【解决方案2】:

下面是完整的代码,它将告诉JavaScript WebView 是否可见。

步骤:

  1. 创建一个包含ToggleButton 和WebView 的布局。
  2. 使用htmlWebView.loadUrl("file:///android_asset/index.html"); 和相关代码加载您的html
  3. 创建一个函数onToggleButtonPressed(),它将被称为切换按钮的onClick
  4. 在onToggleButtonPressed() 显示/隐藏WebView 并同时使用htmlWebView.evaluateJavascript() 方法将状态传递给JavaScript。将visibilityStatusFromAndroid() 传递给 JavaScript
  5. 从 visibilityStatusFromAndroid() 函数获取 JavaScript 中的状态

Android 布局xml代码:

<ToggleButton
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:background="@color/red"
    android:onClick="onToggleButtonPressed"
    android:text="Button1"
    android:textOn="Show"
    android:textOff="Hide"
    tools:ignore="MissingConstraints"
    tools:layout_editor_absoluteX="148dp"
    tools:layout_editor_absoluteY="0dp" />

<WebView
    android:id="@+id/webView"
    android:layout_width="368dp"
    android:layout_height="447dp"
    android:layout_alignParentStart="true"
    android:layout_below="@+id/button"
    tools:ignore="MissingConstraints"
    tools:layout_editor_absoluteX="8dp"
    tools:layout_editor_absoluteY="56dp"
    android:layout_alignParentLeft="true" />

Java 代码:

    WebView htmlWebView; // put it outside onCreate() to make it accessible in onToggleButtonPressed() 

    htmlWebView = (WebView)findViewById(R.id.webView);
    htmlWebView.setWebViewClient(new WebViewClient());
    htmlWebView.loadUrl("file:///android_asset/index.html");
    WebSettings webSetting = htmlWebView.getSettings();
    webSetting.setJavaScriptEnabled(true);

public void onToggleButtonPressed(View view) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

        boolean on = ((ToggleButton) view).isChecked();
        String visibility;
        if (on) {
            htmlWebView.setVisibility(View.GONE);
            visibility = "NOT VISIBLE";
                htmlWebView.evaluateJavascript("javascript: " +
                        "visibilityStatusFromAndroid(\"" + visibility + "\")", null);
        } else {
            htmlWebView.setVisibility(View.VISIBLE);
            visibility = "VISIBLE NOW";
            htmlWebView.evaluateJavascript("javascript: " +
                    "visibilityStatusFromAndroid(\"" + visibility + "\")", null);

        }
    }
}

JavaScript 文件:

function visibilityStatusFromAndroid(message) {
  if (message === "NOT VISIBLE") {
    console.log("webview is not visible");
    // do your stuff here

  } else if (message === "VISIBLE NOW") {
    console.log("webview is visible now");
    // do your stuff here

  }
}

就是这样。你完成了!

这是 Video 的工作代码。

更新:

您可以使用一个选项来检测可见性仅使用 JavaScript 是 document.hasFocus(),但如果屏幕上有任何 EditText 并且用户将关注该 EditText,这将不起作用。 p>

以防万一下面是您可以用于document.hasFocus()的代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>TEST</title>
<style>
#message { font-weight: bold; }
</style>
<script>
setInterval( checkPageFocus, 200 ); // you can change interval time to check more frequently

function checkPageFocus() {
  var info = document.getElementById("message");

  if ( document.hasFocus() ) {
    info.innerHTML = "The document is VISIBLE.";
  } else {
    info.innerHTML = "The document is INVISIBLE.";
  }
}

</script>
</head>
<body>
  <h1>JavaScript hasFocus example</h1>
  <div id="message">Waiting for user action</div>
</body>
</html>

【讨论】:

  • 谢谢,但我需要一个只有 JS 的解决方案,没有 Java 代码
  • 投反对票的人提到投反对票的原因。请不要在没有充分/正当理由的情况下破坏某人的努力。如果您认为有需要改进的地方,可以在评论中提及,但如果您不能提及原因,请不要投反对票。
【解决方案3】:

(目前)没有仅限 JS 的解决方案。

WebView 的内容不应该能够获取有关其环境的信息。
唯一的例外是环境本身自愿提供的信息。

这会与基本沙盒相矛盾,并可能导致安全问题。

由于没有标准 API 可以为您提供所需的信息,您必须自己更改环境才能将其公开给 WebView。

如果您无法更改环境,那么您所请求的(理论上)对于当前的浏览器/android 来说是不可能的。


@Hack 为了找到一个我们可以利用来获取 alpha 值的实际漏洞,我们需要更多关于 JS SDK、环境以及对 android/webview 端的影响有多大的详细信息你有的应用程序。
即使如此,在投入大量精力之后,结果也很可能是相同的。

【讨论】:

  • 同意,但是,当用户单击内容时,我对查找 webView 位置的想法相同。可以使用 screenX/Y 位置以及客户端 X/Y 和 BODY 宽度高度来计算此信息。在实际 webView 未呈现时寻找一些 JS 环境变化。
猜你喜欢
  • 2013-02-15
  • 2011-02-09
  • 2016-02-07
  • 1970-01-01
  • 2011-08-20
  • 2017-10-16
  • 1970-01-01
  • 2014-02-11
  • 2011-07-30
相关资源
最近更新 更多