1、首先看一下Android中webview的屬性設置
//垂直不顯示
this.setVerticalScrollBarEnabled(false);
//設置編碼
this.getSettings().setDefaultTextEncodingName("utf-8");
//與JS交互必不可少的屬性
this.getSettings().setJavaScriptEnabled(true);
this.getSettings().setDomStorageEnabled(true);
//支持JS打開新窗口
this.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
mStoreDetailJSObject = new StoreDetailJSObject(context);
//綁定JS操作對象
this.addJavascriptInterface(mStoreDetailJSObject, StoreDetailJSObject.JSOBJ_NAME);
this.getSettings().setSupportZoom(true);
//清理緩存
clearCache(true);
clearHistory();
this.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
this.getSettings().setPluginState(WebSettings.PluginState.ON);
//擴大比例的縮放
this.getSettings().setUseWideViewPort(true);
//自適應屏幕
this.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
this.getSettings().setLoadWithOverviewMode(true);
this.setOverScrollMode(OVER_SCROLL_NEVER);
this.setFadingEdgeLength(0);
2、JS調用原生代碼
上面用到了addJavascriptInterface方法綁定與JS交互的對象,下面是StoreDetailJSObject類
public class StoreDetailJSObject {
private JSWebView webView;
private Context context;
public static final String JSOBJ_NAME = "JSCallDetail";
public StoreDetailJSObject(Context context){
this.context = context;
}
public StoreDetailJSObject(Context context, JSWebView webView){
this.context = context;
this.webView = webView;
}
/**
* 獲取APP token
* @return
*/
@JavascriptInterface
public String getAppToken(){
if (!CenterObserver.getInstance().isLogin()){
context.startActivity(new Intent(context, LoginTrinityActivity.class));
}
return MyApplication.App.getToken();
}
/**
* 跳轉原生界面
*/
@JavascriptInterface
public void appChannl(int id){
if (PhoneUtils.isFastDoubleClick()){
//連續點擊
return;
}
Intent it = new Intent(context,MainActivity.class);
context.startActivity(it);
}
/**
* 調用電話撥號
*/
// @JavascriptInterface
// public void callTelServer(final String tel){
// AlertDialog.Builder builder = new AlertDialog.Builder(context);
// builder.setTitle(context.getResources().getString(R.string.tip_title));
// builder.setMessage(tel);
// builder.setNegativeButton(context.getResources().getString(R.string.cancel_dialog), null);
// builder.setPositiveButton(context.getResources().getString(R.string.text_call_tel),
// new DialogInterface.OnClickListener() {
//
// @Override
// public void onClick(DialogInterface arg0, int arg1) {
// Intent intent = new Intent(Intent.ACTION_CALL,
// Uri.parse("tel:" + tel));
// context.startActivity(intent);
// }
// });
// builder.show();
// }
}
上面的@JavascriptInterface標註是JS調用原生必不可少的
那麼在JS中怎麼調用這些方法呢,上面的類中關聯了綁定對象名稱這裏叫JSCallDetail
so:
在JS中調用:JSCallDetail.getAppToken();即可
帶參:JSCallDetail.appChannl(int id);傳遞參數給Android端
3、原生調用JS代碼
a、通過loadUrl方法調用JS中的方法
webView.loadUrl("javascript:show('"+info+"')");
b、根據ID獲取指定標籤的屬性
private void callJsCode() {
String js = "document.getElementById('can_share_url').value";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
mWebView.evaluateJavascript(js, new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
LogUtil.e("can_share_url = "+value);
}
});
}else{
String value = mWebView.callJsMethodOld(js);
}
}
代碼中根據id爲can_share_url獲取對應標籤的value屬性的值在onReceiveValue方法中返回 不過使用evaluateJavascript方法調用JS代碼只能在SDK版本爲Build.VERSION_CODES.KITKAT(19,4.4)或者以上才行
那麼在4.4以下就要使用反射來實現了:
/**
* 4.4之前通過java反射機制 調用JS
* @param script
* @return
*/
public String callJsMethodOld(String script){
try {
//由webview取到webviewcore
Field field_webviewcore = WebView.class.getDeclaredField("mWebViewCore");
field_webviewcore.setAccessible(true);
Object obj_webviewcore = field_webviewcore.get(this);
//由webviewcore取到BrowserFrame
Field field_BrowserFrame = obj_webviewcore.getClass().getDeclaredField("mBrowserFrame");
field_BrowserFrame.setAccessible(true);
Object obj_frame = field_BrowserFrame.get(obj_webviewcore);
//獲取BrowserFrame對象的stringByEvaluatingJavaScriptFromString方法
Method method_stringByEvaluatingJavaScriptFromString = obj_frame.getClass().getMethod("stringByEvaluatingJavaScriptFromString", String.class);
//執行stringByEvaluatingJavaScriptFromString方法
Object obj_value = method_stringByEvaluatingJavaScriptFromString.invoke(obj_frame, script);
//返回執行結果
return String.valueOf(obj_value);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
同樣的如果是調用JS方法:
String js = "show("+info+")";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
mWebView.evaluateJavascript(js, new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
LogUtil.e("value= "+value);
}
});
}else{
String value = mWebView.callJsMethodOld(js);
}
直接傳入方法就行,這些調用都限制在APP內部操作3、外部瀏覽器調轉到App
a、使用原始方法
首先在AndroidManifest.xml的Activity下追加以下內容。
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="test.app" android:pathPrefix="/openwith"/>
</intent-filter>
那麼在Html中<a href="myapp://test.app/openwith?id=1">啓動應用程序</a>
b、使用第三方jar包ActivityRouter (包含內部原生跳轉)
基於apt技術,通過註解方式來實現URL打開Activity功能,並支持在WebView和外部瀏覽器使用,支持多級Activity跳轉,支持Bundle、Uri參數注入並轉換參數類型。
特點
支持註解方式、手動方式註冊Activity。
支持注入Bundle、Uri的參數並轉換格式。
支持多級跳轉。
支持外部瀏覽器打開。
支持HTTP協議。
支持目標Activity的URL構造器訪問。
支持多個Module。
接入:https://github.com/joyrun/ActivityRouter
JS中有一個小技巧判斷調用內部JS打開原生還是調用外部連接打開APP
通過try catch來執行內部調用代碼 如:JSCallDetail.getAppToken();
若調用失敗會執行catch塊,所以在catch中執行外部瀏覽器打開APP的連接
try{ JSCallDetail.getAppToken();
}catch{window.location.href="myapp://test.app/openwith?id="+id} 如果沒有APP調轉到下載連接...