如何从android活动调用现有的javascript函数

时间:2016-10-13 21:17:36

标签: javascript java android android-webview

我正在构建一个电子书阅读器,所以我有一个webview正在加载一个本地存储在设备上的页面,它从电子书本身检索到。在这个页面上,它有一个javascript函数controls.nextPage()加载和运行就好了;它习惯于不实际导航到新的网页,而是使用javascript重绘虚拟页面。我将此功能绑定到网页本身的一个按钮,以便我可以手动点击它进行测试,再次,当我触摸webview上的按钮时,工作正常。

现在我试图从我的应用程序中触发这个确切的功能。理想情况下,我想通过手势滑动来实现这一点,但这对于这个特定问题来说太复杂了,因为我还需要首先解决手势的其他问题。现在,我在导航抽屉中设置了一个按钮来触发它并测试它:

NavigationView navigationViewRight = (NavigationView) findViewById(R.id.nav_view_webview_right);
navigationViewRight.setNavigationItemSelectedListener(
    new NavigationView.OnNavigationItemSelectedListener() {
        @SuppressWarnings("StatementWithEmptyBody")
        @Override
        public boolean onNavigationItemSelected(MenuItem item) {
            // Handle navigation view item clicks here.
            int id = item.getItemId();

            if (id == R.id.nav_camera) {
                // *** - Focus here - *** //
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mWebview.evaluateJavascript("controls.pageNext()", null);
                    }
                });
            } else if (id == R.id.nav_share) {
            }

            drawer.closeDrawer(GravityCompat.END);
            return true;
        }
    }
);

注意,我也尝试过调用window.controls.pageNext()无效。

所以我的页面已加载,我点击了我的页面内按钮来测试该功能;作品。我去了应用程序中的导航抽屉按钮?错误(使用window.controls.pageNext()时:

[INFO:CONSOLE(1)] "Uncaught TypeError: Cannot read property 'pageNext' of undefined", source:  (1)

所以似乎evaluateJavascript()正在新环境/线程中运行。我怎么能告诉它不要?

为了解决这个问题,我试图创建一个空的javascript界面​​,希望我可以简单地将我的页面javascript初始化为它,从而能够从Android调用它。

mWebview.addJavascriptInterface(new TestInterface(), "TestInterface");

public class TestInterface {
    @JavascriptInterface
    public void test() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mWebview.evaluateJavascript("console.log('test')", null);
            }
        });
    }
}

从我的webapp,javascript可以调用界面就好了。调用TestInterface.test();会产生:

[INFO:CONSOLE(1)] "test", source:  (1)

但是当我尝试从我的webapp为该界面分配一个新功能时:

TestInterface.testTwo = function() {
    console.log('testTwo');
};
TestInterface.testTwo();

Android不会拥有它:

[INFO:CONSOLE(674)] "testTwo", source: http://127.0.0.1:8080/js/main.js (674)

奇怪的是,它并没有给我很多信息。我知道我的页面的其余部分在testTwo()没有test()尝试后加载了问题,因此我假设无法加载其余的脚本。

最后,出于好奇,我改变了我的导航抽屉按钮,尝试运行这样的新功能:

mWebview.evaluateJavascript("TestInterface.testTwo()", null);

日志:

[INFO:CONSOLE(1)] "Uncaught TypeError: TestInterface.testTwo is not a function", source:  (1)

是的但是还有别的吗?我不知道。思考?谢谢。

1 个答案:

答案 0 :(得分:0)

所以我最终想出了我的问题。通过运行mWebview.evaluateJavascript("window.location", null);我意识到我实际上并没有真正在我认为的页面上。我的电子书页面被加载到iframe或其他类型的骨架/包装器中,使得在运行evaluateJavascript()时webapp函数实际上不可用。

所以一旦弄明白,我可以确认一些我最初质疑的事情:

  

所以似乎是evaluateJavascript()正在以新鲜的方式运行   环境/线程。我怎么能告诉它不要?

没有。只需确保您知道实际加载了哪个页面。

  

为了解决这个问题,我试图创建一个空的javascript界面​​,希望我可以简单地将我的页面javascript初始化为它,从而能够从Android调用它。

这确实有效。我不确定我之前的错误是什么,但如果我在Android中创建一个javascript界面​​,它的功能可用于webapp我实际上可以从webapp中将新对象写入接口对象。因此,可以在Android应用中通过以下方式在网络应用中将新对象初始化为TestInterfacemWebview.evaluateJavascript("TestInterface.someNewFunctionFromWebapp()", null);

但是我不能覆盖该javascript接口对象的任何现有对象/属性。所以TestInterface.test()是不可变的。