- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
[最后编辑。仍然不确定应该如何实现给出的答案。]
我无法理解 Android 应用程序中的线程问题。该应用程序基本上是一个html网页,我需要在webview和android应用程序之间来回加载和保存。我希望网页处理所有消息(因为我有一个很好的统一 css - 为了简单起见,我只在下面使用警报)。
单击保存等按钮时的主要错误:
W/WebView: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {527e3354} called on Looper (JavaBridge, tid 109) {527ece88}, FYI main Looper is Looper (main, tid 1) {527e3354})
at android.webkit.WebView.checkThread(WebView.java:2072)
at android.webkit.WebView.evaluateJavascript(WebView.java:903)
at com.example.jon.androidhtmltemplate.WebAppInterface.save(WebAppInterface.java:116)
at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:24)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.os.HandlerThread.run(HandlerThread.java:61)
W/System.err: java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {527e3354} called on Looper (JavaBridge, tid 109) {527ece88}, FYI main Looper is Looper (main, tid 1) {527e3354})
W/System.err: at android.webkit.WebView.checkThread(WebView.java:2082)
at android.webkit.WebView.evaluateJavascript(WebView.java:903)
W/System.err: at com.example.jon.androidhtmltemplate.WebAppInterface.save(WebAppInterface.java:116)
at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:24)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.os.HandlerThread.run(HandlerThread.java:61)
Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {527e3354} called on Looper (JavaBridge, tid 109) {527ece88}, FYI main Looper is Looper (main, tid 1) {527e3354})
at android.webkit.WebView.checkThread(WebView.java:2072)
W/System.err: ... 7 more
I/chromium: [INFO:CONSOLE(21)] "Uncaught Error: Error calling method on NPObject.", source: file:///android_asset/www/index.html (21)
I/Choreographer: Skipped 135 frames! The application may be doing too much work on its main thread.
I/Choreographer: Skipped 58 frames! The application may be doing too much work on its main thread.
I/chromium: [INFO:async_pixel_transfer_manager_android.cc(60)] Async pixel transfers not supported
E/dalvikvm: Could not find class 'android.support.v4.view.ViewCompat$OnUnhandledKeyEventListenerWrapper', referenced from method android.support.v4.view.ViewCompat.addOnUnhandledKeyEventListener
E/dalvikvm: Could not find class 'android.view.WindowInsets', referenced from method android.support.v4.view.ViewCompat.dispatchApplyWindowInsets
E/dalvikvm: Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering
I/chromium: [INFO:async_pixel_transfer_manager_android.cc(60)] Async pixel transfers not supported
I/Choreographer: Skipped 396 frames! The application may be doing too much work on its main thread.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
package com.example.jon.androidhtmltemplate;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webview = (WebView)findViewById(R.id.webView);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.loadUrl("file:///android_asset/www/index.html");
webview.addJavascriptInterface(new WebAppInterface(this, webview), "Android");
}
}
package com.example.jon.androidhtmltemplate;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.webkit.WebView;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
// This is my class to handle interaction between my webpage and the Android app
public class WebAppInterface {
Context mContext;
WebView webview;
/** Instantiate the interface and set the context */
WebAppInterface(Context c, WebView w) {
mContext = c;
webview = w;
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
@android.webkit.JavascriptInterface
public void load(boolean isLoadExternal){
String ret, script;
ret = loadLocalExternal(isLoadExternal);
script = "javascript:CallbackAndroidLoad(\"" + ret + "\")";
if (Build.VERSION.SDK_INT >= 19 /*Might need 21*/) {
webview.evaluateJavascript(script, null);
}else {
webview.loadUrl(script);
}
}
@android.webkit.JavascriptInterface
public String loadLocalExternal(boolean isExternal) {
int length;
String ret = "";
File path = isExternal ? mContext.getExternalFilesDir(null) : mContext.getFilesDir();
String filename = "myappsavefile.glf";
File file = new File(path, filename);
FileInputStream in;
byte[] bytes;
try {
length = (int) file.length();
bytes = new byte[length];
in = new FileInputStream(file);
in.read(bytes);
in.close();
ret = new String(bytes);
} catch (Exception e) {
ret = "";
}
return ret;
}
@android.webkit.JavascriptInterface
public void save(boolean saveLocal, boolean saveExternal, String fileContent){
boolean ret = true;
String script;
if(ret && saveLocal && !saveLocalExternal(false, fileContent + " local")) ret = false;
if(ret && saveExternal && !saveLocalExternal(true, fileContent + " external")) ret = false;
script = "javascript: CallbackAndroidSave(\"" + (ret ? "true" : "false") + "\")";
if (Build.VERSION.SDK_INT >= 19 /*Might need 21*/) {
webview.evaluateJavascript(script, null);
}else {
webview.loadUrl(script);
}
}
@android.webkit.JavascriptInterface
public boolean saveLocalExternal(boolean isExternal, String fileContent) {
boolean ret = true;
File path = isExternal ? mContext.getExternalFilesDir(null) : mContext.getFilesDir();
String filename = "chartmygolf.glf";
File file = new File(path, filename);
FileOutputStream outputStream;
try {
outputStream = mContext.openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(fileContent.getBytes());
outputStream.close();
} catch (Exception e) {
//e.printStackTrace();
ret = false;
}
return ret;
}
}
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph with very interesting content.</p>
<p id="id">This is another paragraph.</p>
<button onclick="save()">Save</button>
<button onclick="loadLocal()">Load Local</button>
<button onclick="loadExternal()">Load External</button>
</body>
<script>
var isAndroid = /Android/i.test(navigator.userAgent);
document.getElementById("id").innerHTML = "This is on Android";
function save(){
Android.save(true, true, "File Contents 1");
};
function loadLocal(){
Android.load(false);
};
function loadExternal(){
Android.load(true);
};
// ---
function CallbackAndroidLoad(fileContents){
document.getElementById("id").innerHTML = fileContents.length > 0 ? "Error: Load Fail" : ("Contents: " + fileContents);
};
function CallbackAndroidSave(isSuccess){
alert(isSuccess ? "Success" : "Failure");
};
</script>
</html>
Callback
是你第二个建议中的一个类,所以目前我会坚持你的第一个建议。
implements Callback
在
MainActivity
您的类(class)
第一个 建议?
public class WebAppInterface
每当有对 html 页面的回调时调用。是对的吗?
load
函数将变为:
@android.webkit.JavascriptInterface
public void load(boolean isLoadExternal){
String ret, script;
ret = loadLocalExternal(isLoadExternal);
script = "javascript:CallbackAndroidLoad(\"" + ret + "\")";
// This is the only bit of the function with a call back in it
// so I need to do the special stuff on this bit alone
activityObj.runOnUiThread(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= 19 /*Might need 21*/) {
webview.evaluateJavascript(script, null);
}else {
webview.loadUrl(script);
}
}
});
}
activityObj
?它从何而来?如果它必须与调用函数一起传递,我该怎么做?
This is the only bit of the function with a call back in it so I need to do the special stuff on this bit alone
.
最佳答案
JavascriptInterface
方法在后台线程而不是 UI 线程上调用。在处理 UI 时,您需要使用主 UI 线程。
由于您在单独的类中执行它,因此您需要通过 Activity
对象,然后在你所有的 JavascriptInterface
方法:
更改WebAppInterface
类如下:
public class WebAppInterface {
Activity activityObj;
WebView webview;
/** Instantiate the interface and set the context */
WebAppInterface(Activity activityObj, WebView w) {
mContext = c;
this.activityObj = activityObj;
}
...
}
activityObj.runOnUiThread(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= 19 /*Might need 21*/) {
webview.evaluateJavascript(script, null);
}else {
webview.loadUrl(script);
}
}
});
public interface Callback {
void loadLocalExternal(boolean isExternal);
//define other methods.
}
public class MainActivity extends AppCompatActivity implements Callback{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webview = (WebView)findViewById(R.id.webView);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.loadUrl("file:///android_asset/www/index.html");
webview.addJavascriptInterface(new WebAppInterface(this, this), "Android");
}
@Override
public void loadLocalExternal(boolean isExternal){
runOnUiThread(new Runnable() {
@Override
public void run() {
//Do your action here
}
});
}
}
public class WebAppInterface {
Context mContext;
private final Callback callback;
/** Instantiate the interface and set the context */
WebAppInterface(Context c, Callback callback) {
mContext = c;
this.callback = callback;
}
@android.webkit.JavascriptInterface
public String loadLocalExternal(boolean isExternal) {
callback.loadLocalExternal(isExternal);
}
...
}
关于android - WebView - 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50989032/
Webview shouldInterceptRequest方法总是返回null。我去了adblocking的use方法。我尝试了很多adblock方法,但是总是需要这个shouldIntercept
在我的 Native React 项目中,我想使用 WebView。 HTML是指外部的css文件,css文件是指一些自定义字体。 鉴于此层次结构: app/ app/index.ios.js app
我在一个页面上有多个 webview,当应用程序加载时,主页面卡住了将近 8-10 秒,我猜测这是所有 webview 加载各自网站所花费的时间,为什么 Ui 卡住了,我怎么能使 webview 加载
nativescript 中的 webview 是否有“导航”事件? 我已经在 Xamarin (c#) 中用 完成了 Browser.Navigating += Myfunction natives
我的浏览器 (webview) 以 HTML 页面开头 FILEJAVA.class.getResource ("FILEHTML.html")。 ToExternalForm () 每当我访问谷歌时
我们正在开发一个 JavaFX 2.x 应用程序,它需要提供一些 GIS 支持。我们得出的结论是,通过嵌入式 WebView 使用 GoogleMaps 是最快的选择。它的问题在于每次我们的应用程序启
有没有办法销毁 WebView 实例?如果页面加载,并说视频开始播放,我希望能够,当我隐藏 WebView 时,基本上可以销毁它,或者至少重置它。 我知道我可以听 visibleProperty 并执
有没有办法在不启用远程模块的情况下在 webview 和主窗口之间进行通信? When this attribute is false the guest page in webview will
我使用以下代码来拦截Web View 中的对话框,但看不到内容或无法与之交互: Element webview= querySelector("#webview"); Map map=new
我正在创建一个页面,该页面将在 Java 的 WebView 中打开,或在外部浏览器中手动打开。如果页面是从 Java 加载的——我需要它来执行特定的回调,因为 Java 被用作一种后端,但如果页面是
我有一个 React Native WebView ,它运行一个小的 HTML 文档。该文档显示了一些图像。 我希望显示位于应用程序的 Documents 文件夹中的图像,即图像不是静态 Assets
我正在使用 JavaFX webview 开发一个网络爬虫。出于抓取目的,我不需要加载图像。当页面被加载时,Webkit 会产生很多 UrlLoader 线程。所以我认为最好禁用图像,这样我会节省很多
这个问题在这里已经有了答案: Android webview launches browser when calling loadurl (11 个答案) 关闭 7 年前。 我花了两天的时间来寻找一
我正在加载一个网页,我想使用基本身份验证登录,我有使用 Swift 的经验并且能够像下面那样执行基本身份验证,但我无法为我的应用程序的 Flutter 版本实现基本身份验证。 ---- swift 代
我用 webview 创建了应用程序,我想在 webview 中加载所有内部链接并在 android 浏览器中加载外部链接。现在的问题是我正在使用 html 广告,当我点击广告时我想打开外部浏览器,但
我需要在父背景图案上显示我的 webview 内容。有没有直接的方法来做到这一点? 最佳答案 这可能有用 final com.sun.webkit.WebPage webPage = com.sun.
是否可以从 webview 中加载的页面读取 http 请求和响应数据。我想要做的是在用户单击 webview 中页面内的链接后从响应中获取二进制数据。任何帮助或线索将不胜感激 最佳答案 创建您自己的
我有一个简单的WebView在 Android 上运行 Web 应用程序。问题是当我旋转手机以将其更改为横向 webview重新加载并回到开头。 我怎样才能防止这种行为? 罗恩 最佳答案 从 Andr
我创建了一个带有 webview 标签的自定义浏览器。当我在 google.it(或 google.com)中导航时,有时会出现一条消息说 chrome 已过时。我的应用版本是: Node.js 8.
我正在使用 Electron 创建简单的网络浏览器。我的用例是我需要通过不同/各自的代理 IP 路由每个 URL。如果用户输入 google.com,则必须通过 123.123.122.1:8081
我是一名优秀的程序员,十分优秀!