我正在构建一个电子书阅读器,所以我有一个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)
是的但是还有别的吗?我不知道。思考?谢谢。
答案 0 :(得分:0)
所以我最终想出了我的问题。通过运行mWebview.evaluateJavascript("window.location", null);
我意识到我实际上并没有真正在我认为的页面上。我的电子书页面被加载到iframe或其他类型的骨架/包装器中,使得在运行evaluateJavascript()
时webapp函数实际上不可用。
所以一旦弄明白,我可以确认一些我最初质疑的事情:
所以似乎是evaluateJavascript()正在以新鲜的方式运行 环境/线程。我怎么能告诉它不要?
没有。只需确保您知道实际加载了哪个页面。
为了解决这个问题,我试图创建一个空的javascript界面,希望我可以简单地将我的页面javascript初始化为它,从而能够从Android调用它。
这确实有效。我不确定我之前的错误是什么,但如果我在Android中创建一个javascript界面,它的功能可用于webapp我实际上可以从webapp中将新对象写入接口对象。因此,可以在Android应用中通过以下方式在网络应用中将新对象初始化为TestInterface
:
mWebview.evaluateJavascript("TestInterface.someNewFunctionFromWebapp()", null);
但是我不能覆盖该javascript接口对象的任何现有对象/属性。所以TestInterface.test()
是不可变的。