html5无法调用Android本地方法的一种情况(因混淆)

来源:互联网 发布:网络预警机制 编辑:程序博客网 时间:2024/05/22 01:29

最近在开发一个模块的时候,有一个Activity嵌套了html5页面,但是发现了一个问题,就是Debug包是可以正常调用Android本地方法的,而Release包则无法调用同一个本地方法。
代码如下:

public class FlaggingActivity extends AppBaseActivity {    @Initialize    NavigateBar navigateBar;    @Initialize    WebView webView;    String url = NetComment.getIns().getH5()+"/html/fedback/index.html?";    String strId;    String strTel;    String strType;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Intent intent=getIntent();        strId = intent.getStringExtra("id");        strTel = intent.getStringExtra("tel");        strType = intent.getStringExtra("type");        url = url +"id="+strId+"&type="+strType+"&tel="+strTel+"&device=2";        setContentView(R.layout.activity_flagging);        findAllViewByRId(R.id.class);        WebSettings webSetting = webView.getSettings();        //设置js可用        webSetting.setJavaScriptEnabled(true);        // 添加js调用接口        webView.addJavascriptInterface(this,"android");        webView.getSettings().setJavaScriptEnabled(true);        webView.setWebViewClient(new WebViewClient() {            public boolean shouldOverrideUrlLoading(WebView view, String url) {                view.loadUrl(url);                return true;            }        });        webView.loadUrl(url);    }    @JavascriptInterface    public void close(String token) {        //关闭当前activity        this.finish();    }}

从上面的代码可以看出,我这里就是在Activity里嵌套了一个webview,webview的内容指向一个html页面。然后在html页面通过Js再去反向调用Android本地的close方法。
然而,在这里出现了上文的问题:就是Debug包是可以正常调用Android本地方法的,而Release包则无法调用同一个本地方法。
经过排查,我发现了:在我的Android项目里,Debug包是未混淆的,而Release包是经过混淆的,问题也的确就出现在混淆上。混淆的作用是:为了防止自己的劳动成果被别人窃取,混淆代码能有效防止被反编译。那么同样地,因为混淆功能的开启,导致本地的close()方法,在经过混淆之后可能并不再是close()这个函数名称了,那就导致我们的js无法找到这个方法,也就无法调用close()方法了。
相应的解决方式也就是让close()方法不参与混淆,我这里的范围稍微大了一些,是直接把当前的类设置成为了不可混淆,如下(添加在proguard-rules.pro文件中):

#html交互本地方法不能被混淆-keepclassmembernames class com.android.app.activity.house.FlaggingActivity {*;}

加上上面的代码块中后,我们的release包也可以找到close()方法了。

其实这个问题很好解决,在这里记录下来的原因就是一般情况下,Debug包是不混淆的,而Release包通常作为上线包是需要混淆的。但是我们在测试的时候通常使用的是Debug包,在Debug包测试无误的时候通常对于Release包的测试就会掉以轻心。当我们使用js调用本地方法或者反射的时候,这是玩玩不可以的。所以也就要求我们在上线的时候最好对于Release包也进行一个相对完整的测试,以减少类似的失误。

1 0
原创粉丝点击