【问题标题】:Capturing page redirects via javascript in Android's WebView在 Android 的 WebView 中通过 javascript 捕获页面重定向
【发布时间】:2016-03-30 20:54:59
【问题描述】:

我的应用中有一个 WebView,它显示了一个不属于我的页面。我想要的行为是,如果用户点击了任何链接,则会启动设备的浏览器应用程序,并在那里加载生成的页面。不幸的是,这个页面做了一些奇怪的事情,所以shouldOverrideUrlLoading() 不会触发。

我尝试的解决方案是将一些 javascript 挂接到 pushState 并使用接口运行 Android 代码来启动浏览器应用程序。

这是我的界面:

public class LaunchExternalBrowserHack {
    Context mContext;

    LaunchExternalBrowserHack(Context c) {
        mContext = c;
    }

    @JavascriptInterface
    public void launchExternalBrowser(String url) {
        openUrl(url);
    }
}

我在onPageFinished()的页面中注入了一些javascript:

public void onPageFinished(WebView view, String url) {
     mWebView.loadUrl(javascript);
}

这是我的 javascript:

private final String javascript = "javascript:history.pushState = function (state, title, url) { console.log(url); console.log(location.href); Uphoria.launchExternalBrowser(location.origin, url); };";

当然,我正在将接口添加到WebView

mWebView.addJavascriptInterface(new LaunchExternalBrowserHack(getContext()), "Android");

所以这似乎有效。浏览器应用程序正在启动,下一页正在打开。

不过,WebView 也在向前发展。我想阻止这种情况,但我找不到阻止 WebView 向前移动的方法,同时仍然允许我捕获转发 url 并启动浏览器应用程序。正如我之前提到的,在这个网页上,shouldOverrideUrlLoading不会触发。

想法?

【问题讨论】:

  • 您提到在onReceiveValue(...) 中没有得到结果。您能看到将 javascript 更改为函数调用是否可行吗?就像this answer 建议的那样。具体来说,采用这种风格:(function() { return { var1: \"variable1\", var2: \"variable2\" }; })();

标签: javascript android android-webview


【解决方案1】:

用户正试图离开页面。阻止他搬出去,返回false。让他离开,不要返回任何东西,但你可以执行你可能想要的任何代码。当发生导航事件(包括页面刷新)时立即触发此事件。

private final String javascript = "window.onbeforeunload = function(){ dosomething(); }; window.unload = function(){ dosomething(); }; function dosomething() { /* Write code here */  };"

您需要包含上面的整个 javascript 代码,因为有些浏览器使用 onbeforeunload,有些使用 unload

编辑

仔细阅读您的问题后,我发现我的解决方案没什么用。

这是使用history 的另一种方法。如果您的历史记录是空白的,则意味着它的第一页。但是如果你有一些历史记录,这意味着导航已经发生了。

您可以如下检查

private final String javascript = "javascript:"+"if(window.history.length>=1 && document.referrer=='') Android.launchExternalBrowser(location.href);";

【讨论】:

    【解决方案2】:

    这个答案是错误的。保留在这里是因为它有重要的相关 cmets。

    您没有从 Javascript 中获得结果的原因是您没有直接调用函数。您正在 Javascript 中分配一个返回值的函数,但它不会将其返回给您的代码,而是将其返回给任何调用 history.pushState()

    private final String javascript = "javascript:" + "var pushState = history.pushState; history.pushState = function () " +
            "{ pushState.apply(history, arguments); console.log(arguments); return location.href; " +
            "};";
    

    相反,您可以测试这样的事情是否会为您返回一个值:

    private final String javascript = "(function() { return location.href; })();";
    

    【讨论】:

    • 这不会马上返回吗?我希望当用户点击导致他/她离开的东西时触发处理程序。
    • 是的,它会立即返回。我认为您不能以您正在考虑的样式运行回调。您正在通过该函数直接评估 Javascript。您将立即发送 JS,它将被评估并返回一个值(如果给定)。但是,在您的代码中,您正在评估一个函数的设置,就是这样。你可以想象使用webView.addJavascriptInterface。你调查过吗?
    • 是的,但我的界面似乎在 Android 4.4+ 上无法启动。它在 4.4 之前工作正常。
    • 啊,是的,你当然有。唔。关于evaluateJavascript,您似乎是对的。需要更多调查。
    • 看来addJavascriptInterface 确实在 4.4+ 中工作。如果您查看上面我调用apply 的js,我认为这会将我的函数变成递归函数。它不起作用,因为我正在填满堆栈。我现在可以正确启动浏览器应用程序并在那里为所有版本的 Android(4.1+)打开 url。但是,我也需要找到一种方法来阻止 WebView 向前导航。到目前为止,我还没有成功地弄清楚这一点。
    猜你喜欢
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    相关资源
    最近更新 更多