Android与JS的交互汇总

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调转到下载连接...


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值