Android原生内嵌H5开发小结

Android原生内嵌H5开发小结自用笔记外包公司,为了节约成本,采用Android内嵌H5模式开发,便于在安卓移动端上直接复用页面,从而提高开发效率。同时改动时候只需改动H5页面,无需改动客户端。实现的原理:本质是:Java代码和Javascript调用H5页面,只是Html的扩展,Javascript用来处理页面的逻辑Android和H5互调案例:一.java调用js1、Java调用js里面的函数、效率并不是很高、估计要200ms左右吧、做交互性很强的事情、这种速度很难让人接受、而js去调Java的方

Android原生内嵌H5开发小结"

自用笔记

外包公司,为了节约成本,采用Android内嵌H5模式开发,便于在安卓移动端上直接复用页面, 从而提高开发效率。同时改动时候只需改动H5页面,无需改动客户端。

实现的原理:

本质是:Java代码和Javascript调用

H5页面,只是Html的扩展,Javascript用来处理页面的逻辑

Android和H5互调案例:

一.java调用js

1、Java 调用 js 里面的函数、效率并不是很高、估计要200ms左右吧、做交互性很强的事情、这种速度很难让人接受、而js去调Java的方法:速度很快、50ms左右、所以尽量用js调用Java方法
2、Java 调用 js 的函数、没有返回值、调用了就控制不到了
3、Js 调用 Java 的方法、返回值如果是字符串、你会发现这个字符串是 native奶踢吾 的、转成 locale老K乐 的才能正常使用、使用 toLocale
String() 函数就可以了、不过这个函数的速度并不快、转化的字符串如果很多、将会很耗费时间
4、网页中尽量不要使用jQuery、执行起来需要5-6秒、最好使用原生的js写业务脚本、以提升加载速度、改善用户体验
交互的话,安卓这边只需要配置webview的jsBridge就可以了
一般接口什么的都是h5那边提供,这边这需要根据提供的接口进行实现就可以了
数据交互也是这样的,还有一种是写cookie
     对于安卓开发有一段时间的人来说,知道安卓4.4以前谷歌的webview存在安全漏洞,网站可以通过js注入就可以随便拿到客户
端的重要信息,甚至轻而易举的调用本地代码进行流氓行为,谷歌后来发现有此漏洞后,增加了防御措施,如果要是js调用本地
代码,开发者必须在代码申明JavascriptInterface,   列如在4.0之前我们要使得webView加载js只需如下代码:  
mWebView.addJavascriptInterface(new JsToJava(), “myjsfunction”); 
     4.4之后调用需要在调用方法加入加入@JavascriptInterface注解,如果代码无此申明,那么也就无法使得js生效,也就是说这
样就可以避免恶意网页利用js对安卓客户端的窃取和攻击。
        但是即使这样,我们很多时候需要在js记载本地代码的时候,要做一些判断和限制,或者有可能也会做些过滤和对用户友好
提示,因此JavascriptInterface也就无法满足我们的需求了,特此有大神就写出了WebViewJavascriptBridge框架。
    通过实例化webView,用法和安卓原生的view没多大区别,设置WebChromClient, 设置加载的html(同样支持网络和本地文件)
,接着我们需要给web注册和html端约定好的js方法名。代码列举的submitFromweb和js的执行的方法名一致,玩过NDK的JNI调
用的朋友也知道必须和c代码之间有个约定,其实js桥和jni有点类似,
通过注册handler来实现回调,Java代码中通过js返回的数据,进行处理后在调用function.onCallback返回给js.这里不做过多解释
//必须和js同名函数,注册具体执行函数,类似java实现类

拦截URL
Android中处理网页时我们必然用到WebView,这里我们有这样一个需求,我们想让WebView在处理网络请求的时候将某
些请求拦截替换成某些特殊的资源。具体一点儿说,在WebView加载 http://m.sogou.com 时,会加载一个logo图片,
我们的需求就是将这个logo图片换成另一张图片。

shouldInterceptRequest
好在Android中的WebView比较强大,从API 11(Android 3.0)开始, shouldInterceptRequest被引入就是为了解决这一类的问题。
shouldInterceptRequest这个回调可以通知主程序WebView处理的资源(css,js,image等)请求,并允许主程序进行处理后返回数据。如果主程序返回的数据为null,WebView会自行请求网络加载资源,否则使用主程序提供的数据。注意这个回调发生在非UI线程中,所以进行UI系统相关的操作是不可以的。shouldInterceptRequest有两种重载。

下面是:

WebView的基本设置:

private void initWebView() {

        webView = new WebView(this);

        WebSettings webSettings = webView.getSettings();

        //设置支持javaScript脚步语言

        webSettings.setJavaScriptEnabled(true);

        //支持双击-前提是页面要支持才显示

           //webSettings.setUseWideViewPort(true);

        //支持缩放按钮-前提是页面要支持才显示

        webSettings.setBuiltInZoomControls(true);

        //设置客户端-不跳转到默认浏览器中

        webView.setWebViewClient(new WebViewClient());

        //设置支持js调用java

        webView.addJavascriptInterface(new  AndroidAndJSInterface(),”Android”);

 //加载本地资源       

 webView.loadUrl(“file:///android_asset/JavaAndJavaScriptCall.html”);

        //显示页面

//        setContentView(webView);

}

java调用js原理就是Java代码调用了Js里面的函数。

核心Java代码段:

//登录功能里,java代码调用了js里面的JavaCallJs函数实现将name传到JS中,这样JS页面可以显示该用户名了。

   private void login(String name) {

        webView.loadUrl(“javascript:javaCallJs(” + “‘” + name + “‘” + “)”);

        setContentView(webView);

}

核心js代码段:

//上面Java核心代码执行将调用下面JS代码

 <script type=”text/javascript”>

    function javaCallJs(arg){

         document.getElementById(“content”).innerHTML =

             (“欢迎:”+arg );

    }

    </script>

 不过要实现H5在APP上进行操作,我们就需要重写WebChromeClient中的openFileChooser方法才行,顺便百度了下WebView中 WebViewClient与WebChromeClient的区别

WebViewClient主要帮助WebView处理各种通知、请求事件的,比如:

onLoadResource
onPageStart
onPageFinish
onReceiveError
onReceivedHttpAuthRequest

 WebChromeClient主要辅助WebView处理JavaScript的对话框、网站图标、网站title、加载进度等比如

onCloseWindow(关闭WebView)
onCreateWindow()
onJsAlert (WebView上alert无效,需要定制WebChromeClient处理弹出)
onJsPrompt
onJsConfirm
onProgressChanged
onReceivedIcon
onReceivedTitle

看上去他们有很多不同,实际使用的话,如果你的WebView只是用来处理一些html的页面内容,只用WebViewClient就行了,如果需要更丰富的处理效果,比如JS、进度条等,就要用到WebChromeClient,所以我们用到了WebChromeClient。

举个上传的例子 得益于这两篇文章的帮助 :android使用webview上传文件(支持相册和拍照)_千里之外-CSDN博客_webview上传文件Android 如何選取圖片或是檔案? | MagicLen,后来通过一些处理 ,最终我们的代码如下:

mWebView.setWebChromeClient(new WebChromeClient() {

@Override
public void onReceivedTitle(WebView view, String mTitle) {

super.onReceivedTitle(view, mTitle);

                                   //这里可以用来处理我们的页面标题

}
@Override
public void onProgressChanged(WebView view, int newProgress) {

//处理网页面加载进度
}


// For Android < 3.0

public void openFileChooser(ValueCallback<Uri> filePathCallback) {

mFilePathCallback4 = filePathCallback;
IntentUtils.jumpToSelectPics(aty, false, 1, MultiImageSelectorActivity.MODE_SINGLE);
}
 

                  // For Android  > 4.1.1

public void openFileChooser(ValueCallback filePathCallback, String acceptType) {

mFilePathCallback4 = filePathCallback;
IntentUtils.jumpToSelectPics(aty, false, 1, MultiImageSelectorActivity.MODE_MULTI);
}
 

                     // For Android 3.0+

public void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture) {

mFilePathCallback4 = filePathCallback;
IntentUtils.jumpToSelectPics(aty, false, 1, MultiImageSelectorActivity.MODE_MULTI);
}

public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {

mFilePathCallback5 = filePathCallback;
IntentUtils.jumpToSelectPics(aty, false, 1, MultiImageSelectorActivity.MODE_MULTI);
return true;
}
});
我们这里选择好图片后,还要进行处理:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {

  

     if (requestCode == IntentUtils.REQUEST_IMAGE) {

     if (mFilePathCallback4 != null) {

     if (null != intent) {

     ArrayList<String> resultList = intent.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
     if (resultList.size() > 0) {

           String path = MediaUtility.getPath(BaseWebViewAct.this,
           Uri.parse(“file://” + resultList.get(0)));//
           Uri uri = Uri.fromFile(new File(path));
           mFilePathCallback4.onReceiveValue(uri);
          }
    }else {

mFilePathCallback4.onReceiveValue(null);
          }
    }
     if (mFilePathCallback5 != null) {

          if (null != intent) {

             ArrayList<String> resultList =intent.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
             if (resultList.size() > 0) {

                 String path = MediaUtility.getPath(BaseWebViewAct.this,
                 Uri.parse(“file://” + resultList.get(0)));//
                 Uri uri = Uri.fromFile(new File(path));
                 mFilePathCallback5.onReceiveValue(new Uri[]{uri});
           }
     }else {

       mFilePathCallback5.onReceiveValue(null);
           }
   }
       mFilePathCallback4 = null;
       mFilePathCallback5 = null;
   }
}

二.JavaScript调java

1.在初始化webview代码中配置Javascript接口:

        //设置支持js调用java,调用时候将执行第一个参数的接口类

        webView.addJavascriptInterface(new AndroidAndJSInterface(),”Android”);

//第二个参数为执行接口类方法的标示,与js相呼应

1

2

3

2.在该Activity中实现Javascript接口类:

  /**

     * js可以调用该类的方法

     */

    class AndroidAndJSInterface{

        @JavascriptInterface

        public void showToast(){

            Toast.makeText(JavaAndJSActivity.this, “我被js调用了”, Toast.LENGTH_SHORT).show();

        }

    }

3_JavaScript中调用java代码的核心代码段:

<input type=”button” value=”点击Android被调用” οnclick=”window.Android.showToast()” />

1

2

执行流程:

点击js页面的button,将执行js的onclick方法(οnclick=”window.Android.showToast()”),根据该Android标示与webview配置接口方法的第二个参数相匹配,然后执行js接口实现类的showToast()方法。从而实现js代码调用java代码。

H5页面调用Android播放视频

基本思路和上面的例子(执行流程)一样,业务逻辑层面来说播放视频主要是从H5页面点击播放跳转(把视频播放的url传递给Java层)并触发Java实现播放视频的代码即可。

1. webview中的核心配置:

   //设置支持js调用java

        webView.addJavascriptInterface(new AndroidAndJSInterface(),”android”);

2.在该Activity中实现Javascript接口类:

 class AndroidAndJSInterface {

        /**

         * 该方法将被js调用

         * @param id

         * @param videoUrl

         * @param tile

         */

        @JavascriptInterface

        public void playVideo(int id,String videoUrl,String tile){

            //调起系统所有播放器

            Intent intent = new Intent();

            intent.setDataAndType(Uri.parse(videoUrl),”video/*”);

            startActivity(intent);

        }

}

3.JavaScript中调用java代码的核心代码段:

  javascript:android.playVideo(itemid, videourl, itemtitle);

1

H5页面调用Android拨打电话

思路都是一样的,点击H5页面把电话号码传到java层并调用拨号核心代码即可。

在该Activity中实现Javascript接口类:

 @JavascriptInterface

        public void call(String phone) {

            Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(“tel:” + phone));

            if (ActivityCompat.checkSelfPermission(JsCallJavaCallPhoneActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {

                return;

            }

            startActivity(intent);

        }

重点内容

1.如果调用如下方法时候报错,那么可以在Javascript接口类的具体实现方法上面加注解:@JavascriptInterface,或者把targetSdkVersion 改为 16(一般不适用)

 //设置支持js调用java

        webView.addJavascriptInterface(new AndroidAndJSInterface(), “Android”);

1

2

2.该申请的权限不要忘了在AndroidManifest.xml中加上。

今天的文章Android原生内嵌H5开发小结分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/32881.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注