Android 适配——原生与H5交互

https://rainmonth.github.io/posts/A180415.html

Android 原生与H5交互

[TOC]

JS中调用Android的函数方法

在Android程序中建立接口,并用建立的handler对象处理

1
2
3
4
5
6
7
8
9
10
11
private Handler handler = new Handler();
final class InJavaScript{
public void runOnAndroidJavaScript(final String str){
handler.post(new Runnable() {
public void run() {
// todo 对传递过来的参数进行处理

}
})
}
}

通过给WebView添加JavaScriptInterface接口

即调用addJavaScriptInterface(new InJavaScript(), “injs”),其中第一个参数为前面定义的接口的实例,第二个参数为该对象对应的名字

在js代码中通过类似一下函数的方法调用Android中定义好的方法

1
2
3
4
function sendToAndroid() {
var str = "Call the Android method in js";
window.injs.runOnAndroidJavaScript(str);// injs为Android程序中建立的InJavaScript对象的一个实例名字
}

Android中调用JS中的方法

在JS代码中定义好要被Android程序调用的方法

1
2
3
function getFromAndroid(str) {
document.getElementById("android").innerHTML = str;
}

在Android程序中通过以下方式调用该方法(要注意调用的格式javascript:+要调用的方法名)

1
2
3
4
5
6
7
Button button = (Button) findViewById(R.id.button);  
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
//调用javascript中的方法
webView.loadUrl("javascript:getFromAndroid('Cookie call the js function from Android')");
}
});

通过约定的scheme来完成H5到原生App的跳转

  1. 在H5要跳转到的原生页面所在的Activity中设定好scheme,如SplashActivity中

    1
    2
    3
    4
    5
    6
    7
    <activity android:name=".SplashActivity">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
    <data android:scheme="myapp" android:host="path" />
    </intent-filter>
    </activity>

其中schema表示这个链接的前缀,host代表短链的名字。如果你要在你的schema里面传参数,比如你要传uid和user_type,那么就跟普通的url的get参数格式一样:mls://userpage?uid=123&user_type=mogujie。

注意,中间千万不能有空格

  1. SplashActivity接受参数

    1
    2
    3
    4
    5
    6
    7
    8
    String uid,userType;  
    private void parseUriParams() {
    Uri uri = getIntent().getData();
    if (uri != null) {
    uid = uri.getQueryParameter("uid");
    userType = uri.getQueryParameter("user_type");
    }
    }
  2. 在WebViewClient的shouldOverrideUrlLoading方法中作拦截URL判断

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class MyWebChromeClient extends WebViewClient {  
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("mls://")) {
    Intent intent = new Intent();
    intent.setData(Uri.parse(url));
    startActivity(intent);
    Log.v("tag_2", url);
    return true;
    }
    return super.shouldOverrideUrlLoading(view, url);
    }
    }

设置问题

  • 通过WebView的setWebChromeClient方法还可以处理JS的警告、对话框以及输出JS控制台的信息到logcat中;

  • Android 4.2以后(API17+)出于安全因素的考虑,JS只能访问带有@JavascriptInterface注解的函数。

    在此之前,任何public的函数都可以在JS中访问,而Java对象的继承关系会导致很多public函数都可以在JS中访问,其中一个重要的函数就是getClass()。然后JS可以通过反射来访问一些其他内容,就会出现安全问题,加上注解之后,JS就只能访问带有@JavascriptInterface注解的public函数,增强了安全性。