Java 安卓:我怎么知道CSS注入完成了?
我只是在将CSS文件注入HTML之后才尝试显示我的webview。 我试着把它放在onPageCommitVisible函数上,但它只能运行23个API和上面的D。有人知道只有在CSS完成加载后,我如何才能显示webview?现在它“跳转”了,我在第一秒钟看到了原来的CSS,在新的CSS被替换之前Java 安卓:我怎么知道CSS注入完成了?,java,android,html,css,Java,Android,Html,Css,我只是在将CSS文件注入HTML之后才尝试显示我的webview。 我试着把它放在onPageCommitVisible函数上,但它只能运行23个API和上面的D。有人知道只有在CSS完成加载后,我如何才能显示webview?现在它“跳转”了,我在第一秒钟看到了原来的CSS,在新的CSS被替换之前 @Override public void onPageFinished(WebView view, String url) { Utils.logDebug(
@Override
public void onPageFinished(WebView view, String url) {
Utils.logDebug(this, "Page finished");
if (android.os.Build.VERSION.SDK_INT < 23) {
injectCSS(view);
}
super.onPageFinished(view, url);
showWebView(true);
onPageChange();
}
这个函数将CSS代码注入HTML,正如您在函数中看到的那样 很少有地方可以处理这个问题
- 您可以使用
而不是evaluateJavaScript
(API级别19),并通过回调将webview设置为可见李>loadUrl
- 您可以使用
注册自己的javascript接口,并在脚本末尾调用它addJavaScriptInterface
- 您可以设置
并覆盖WebChromeClient
,然后在脚本中使用特定消息发出警报onJsAlert
- 更新:此外,这可以通过截取一个“css”请求,并在加载的文件中附加所需内容来实现。这将允许您在
之前插入样式。检查这条线onPageFinished
package com.j2ko.webviewapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
public class MainActivity extends AppCompatActivity {
private static final String MAIN_FUNC_FMT = "(function() { %s })()";
private static final String FUNC_BODY_FMT =
"var parent = document.loadedgetElementsByTagName('head').item(0);" +
"var css = document.createElement('style');" +
"css.type = 'text/css';" +
"css.innerHTML = %s;" +
"parent.appendChild(css);";
private static final String BASE64_DECODE_FMT = "window.atob('%s')";
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//Change it to whatever
injectWithEvaluateAndInterface(view);
}
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
}
});
mWebView.setVisibility(View.INVISIBLE);
mWebView.loadUrl("http://wiki.org");
}
private static class CSSInjectBuilder {
private final String mOrigin;
private String mAtEnd = null;
private boolean mUseBase64 = false;
public CSSInjectBuilder(String css) {
mOrigin = css;
}
public CSSInjectBuilder withBase64() {
mUseBase64 = true;
return this;
}
public CSSInjectBuilder withExpressionAtEnd(String expression){
mAtEnd = expression;
return this;
}
String build() {
String func_body = FUNC_BODY_FMT;
if (mAtEnd != null) {
func_body += mAtEnd;
}
final String css;
if (mUseBase64) {
byte[] buffer = mOrigin.getBytes();
css = String.format(BASE64_DECODE_FMT, Base64.encodeToString(buffer, Base64.NO_WRAP));
} else {
css = "'" + mOrigin + "'";
}
func_body = String.format(func_body, css);
return String.format(MAIN_FUNC_FMT, func_body);
}
}
byte[] loadAsset() {
try {
InputStream inputStream = getAssets().open("style.css");
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
return buffer;
} catch (Exception e) {
}
return null;
}
String loadCSS() {
return new String(loadAsset());
}
void injectWithEvaluate(final WebView view) {
view.evaluateJavascript(new CSSInjectBuilder(loadCSS()).withBase64().build(), new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
view.setVisibility(View.VISIBLE);
}
});
}
void injectWithEvaluateAndInterface(WebView view) {
view.addJavascriptInterface(new WebViewInterface(), "WebViewBackEnd");
final String injector = new CSSInjectBuilder(loadCSS())
.withBase64()
.withExpressionAtEnd("window.WebViewBackEnd.CSSInjectionComplete();")
.build();
view.evaluateJavascript(injector, null);
}
void injectWithLoadUrlSimple(WebView view) {
view.loadUrl("javascript:" + loadCSS());
view.setVisibility(View.VISIBLE);
}
void injectWithLoadUrlAndCheckAlert(final WebView view) {
view.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
if (message.equals("CSSInjectionComplete")) {
view.setVisibility(View.VISIBLE);
return true;
}
return super.onJsAlert(view, url, message, result);
}
});
//alert could hang aplying scripts so put it on timeout
final String injector = new CSSInjectBuilder(loadCSS())
.withBase64()
.withExpressionAtEnd("setTimeout(function(){alert('CSSInjectionComplete');}, 1);")
.build();
view.loadUrl("javascript:" + injector);
}
private class WebViewInterface {
@JavascriptInterface
public void CSSInjectionComplete(){
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.setVisibility(View.VISIBLE);
}
});
}
}
}
package com.j2ko.webviewapp;
导入android.support.v7.app.AppActivity;
导入android.os.Bundle;
导入android.util.Base64;
导入android.util.Log;
导入android.view.view;
导入android.webkit.JavascriptInterface;
导入android.webkit.JsResult;
导入android.webkit.ValueCallback;
导入android.webkit.WebChromeClient;
导入android.webkit.WebView;
导入android.webkit.WebViewClient;
导入java.io.InputStream;
导入java.io.StringReader;
导入java.io.StringWriter;
公共类MainActivity扩展了AppCompatActivity{
私有静态最终字符串MAIN_FUNC_FMT=“(函数(){%s})(”;
私有静态最终字符串函数\u BODY\u FMT=
“var parent=document.loadedgetElementsByTagName('head')。项(0);”+
“var css=document.createElement('style')+
“css.type='text/css';”+
“css.innerHTML=%s;”+
“parent.appendChild(css);”;
私有静态最终字符串BASE64_DECODE_FMT=“window.atob('%s')”;
网络视图;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView=(WebView)findViewById(R.id.WebView);
mWebView.getSettings().setJavaScriptEnabled(true);
setWebViewClient(新的WebViewClient()){
@凌驾
公共void onPageFinished(WebView视图,字符串url){
super.onPageFinished(视图、url);
//换成什么都行
injectWithEvaluateAndInterface(视图);
}
@凌驾
public void onLoadResource(WebView视图,字符串url){
super.onLoadResource(视图、url);
}
});
mWebView.setVisibility(视图.不可见);
mWebView.loadUrl(“http://wiki.org");
}
私有静态类CSSInjectBuilder{
私人最终字符串莫里金;
私有字符串mAtEnd=null;
私有布尔值mUseBase64=false;
公共CSSInjectBuilder(字符串css){
mOrigin=css;
}
使用Base64()的公共CSSInjectBuilder{
mUseBase64=真;
归还这个;
}
带有ExpressionAttend(字符串表达式)的公共CSSInjectBuilder{
mAtEnd=表达式;
归还这个;
}
字符串构建(){
字符串func_body=func_body_FMT;
如果(mAtEnd!=null){
func_body+=mAtEnd;
}
最终字符串css;
如果(64){
byte[]buffer=mOrigin.getBytes();
css=String.format(BASE64_DECODE_FMT,BASE64.encodeToString(buffer,BASE64.NO_WRAP));
}否则{
css=“””+mOrigin+“”;
}
func_body=String.format(func_body,css);
返回字符串.format(主函数、函数体);
}
}
字节[]loadAsset(){
试一试{
InputStream InputStream=getAssets().open(“style.css”);
字节[]缓冲区=新字节[inputStream.available()];
inputStream.read(缓冲区);
inputStream.close();
返回缓冲区;
}捕获(例外e){
}
返回null;
}
字符串loadCSS(){
返回新字符串(loadAsset());
}
void injectWithEvaluate(最终WebView视图){
view.evaluateJavascript(新的CSSInjectBuilder(loadCSS()).withBase64().build(),新的ValueCallback()){
@凌驾
公共无效onReceiveValue(字符串值){
view.setVisibility(view.VISIBLE);
}
});
}
void injectWithEvaluateAndInterface(WebView视图){
addJavascriptInterface(新的WebViewInterface(),“WebViewBackEnd”);
最终字符串注入器=新CSSInjectBuilder(loadCSS())
.withBase64()
.WithExpressionAttend(“window.WebViewBackEnd.CSSInjectionComplete();”)
.build();
evaluateJavascript(注入器,null);
}
void injectWithLoadUrlSimple(WebView视图){
loadUrl(“javascript:+loadCSS());
view.setVisibility(view.VISIBLE);
package com.j2ko.webviewapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
public class MainActivity extends AppCompatActivity {
private static final String MAIN_FUNC_FMT = "(function() { %s })()";
private static final String FUNC_BODY_FMT =
"var parent = document.loadedgetElementsByTagName('head').item(0);" +
"var css = document.createElement('style');" +
"css.type = 'text/css';" +
"css.innerHTML = %s;" +
"parent.appendChild(css);";
private static final String BASE64_DECODE_FMT = "window.atob('%s')";
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//Change it to whatever
injectWithEvaluateAndInterface(view);
}
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
}
});
mWebView.setVisibility(View.INVISIBLE);
mWebView.loadUrl("http://wiki.org");
}
private static class CSSInjectBuilder {
private final String mOrigin;
private String mAtEnd = null;
private boolean mUseBase64 = false;
public CSSInjectBuilder(String css) {
mOrigin = css;
}
public CSSInjectBuilder withBase64() {
mUseBase64 = true;
return this;
}
public CSSInjectBuilder withExpressionAtEnd(String expression){
mAtEnd = expression;
return this;
}
String build() {
String func_body = FUNC_BODY_FMT;
if (mAtEnd != null) {
func_body += mAtEnd;
}
final String css;
if (mUseBase64) {
byte[] buffer = mOrigin.getBytes();
css = String.format(BASE64_DECODE_FMT, Base64.encodeToString(buffer, Base64.NO_WRAP));
} else {
css = "'" + mOrigin + "'";
}
func_body = String.format(func_body, css);
return String.format(MAIN_FUNC_FMT, func_body);
}
}
byte[] loadAsset() {
try {
InputStream inputStream = getAssets().open("style.css");
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
return buffer;
} catch (Exception e) {
}
return null;
}
String loadCSS() {
return new String(loadAsset());
}
void injectWithEvaluate(final WebView view) {
view.evaluateJavascript(new CSSInjectBuilder(loadCSS()).withBase64().build(), new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
view.setVisibility(View.VISIBLE);
}
});
}
void injectWithEvaluateAndInterface(WebView view) {
view.addJavascriptInterface(new WebViewInterface(), "WebViewBackEnd");
final String injector = new CSSInjectBuilder(loadCSS())
.withBase64()
.withExpressionAtEnd("window.WebViewBackEnd.CSSInjectionComplete();")
.build();
view.evaluateJavascript(injector, null);
}
void injectWithLoadUrlSimple(WebView view) {
view.loadUrl("javascript:" + loadCSS());
view.setVisibility(View.VISIBLE);
}
void injectWithLoadUrlAndCheckAlert(final WebView view) {
view.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
if (message.equals("CSSInjectionComplete")) {
view.setVisibility(View.VISIBLE);
return true;
}
return super.onJsAlert(view, url, message, result);
}
});
//alert could hang aplying scripts so put it on timeout
final String injector = new CSSInjectBuilder(loadCSS())
.withBase64()
.withExpressionAtEnd("setTimeout(function(){alert('CSSInjectionComplete');}, 1);")
.build();
view.loadUrl("javascript:" + injector);
}
private class WebViewInterface {
@JavascriptInterface
public void CSSInjectionComplete(){
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.setVisibility(View.VISIBLE);
}
});
}
}
}