Android可以通过webview来内嵌html页面,从而实现灵活的信息展示;最近客串android开发中,正好遇到了这样的一个小场景,所以简单的记录一下Android与html之间的交互,包含以下内容
webview的基本设置 
Andriod调用js方法 
js调用android方法 
图片长按下载 
 
 
I. 内嵌html 1. 布局 我们这里主要介绍通过原生的WebView来嵌入Html网页,首先是在布局文件中,添加webview控件
1 2 3 4 5 <WebView      android:id ="@+id/wv_detail"      android:layout_width ="match_parent"      android:layout_height ="match_parent"      /> 
 
2. WebView配置 在Activity类中,获取WebView控件
1 2 3 @BindView (R.id.wv_detail)WebView webView; 
 
webview的基本配置参数,比如是否可以缩放,自适应等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true ); webSettings.setPluginsEnabled(true ); webSettings.setUseWideViewPort(true );  webSettings.setLoadWithOverviewMode(true );  webSettings.setSupportZoom(true );  webSettings.setBuiltInZoomControls(true );  webSettings.setDisplayZoomControls(false );  webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  webSettings.setAllowFileAccess(true );  webSettings.setJavaScriptCanOpenWindowsAutomatically(true );  webSettings.setLoadsImagesAutomatically(true );  webSettings.setDefaultTextEncodingName("utf-8" ); webView.setWebViewClient(new  WebViewClient(){      @Override       public  boolean  shouldOverrideUrlLoading (WebView view, String url)   {            view.loadUrl(url);            return  true ;       } }); 
 
3. 回退与销毁 内嵌html,当存在多个html页面跳转时,如果直接后退,可能的结果就是回到上一个activity,而不是我们预期的回到上一个html页面,因此我们需要处理一下回退事件
1 2 3 4 5 6 7 8 9 10 11 @Override public  void  onBackPressed ()   {    if  (webView == null ) {         return ;     }     if  (webView.canGoBack()) {         webView.goBack();         return ;     }     super .onBackPressed(); } 
 
其次在退出activity时,别忘了销毁WebView
1 2 3 4 5 6 7 8 9 10 11 12 @Override protected  void  onDestroy ()   {    if  (webView != null ) {         final  ViewGroup viewGroup = (ViewGroup) webView.getParent();         if  (viewGroup != null ) {             viewGroup.removeView(webView);         }         webView.destroy();     }     super .onDestroy(); } 
 
II. Android与JS交互 1. 加载html 基本配置完毕之后,开始加载html页面,主要是借助loadUrl来实现
1 2 3 4 5 webView.loadUrl("file:///android_asset/bs.html" ); webView.loadUrl("https://mweb.hhui.top/" ) 
 
2. js调用android方法 为了实现js调用android方法,我们新建一个桥接类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public  class  JsBrager   {    private  Activity activity;     public  JsBrager (Activity activity)   {         this .activity = activity;     }          @JavascriptInterface      public  void  toastMessage (String message)   {         Toast.makeText(activity, "通过Natvie传递的Toast:"  + message, Toast.LENGTH_LONG).show();     } } 
 
通过webView.addJavascriptInterface来关联
1 2 webView.addJavascriptInterface(new  JsBrager(this ), "android" ); 
 
一个简单的html页面如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <head >                <meta  http-equiv ="content-type"  content ="text/html;charset=utf-8" >  </head > <body >      <center >           <h2 > 简单的测试</h2 >       </center >       <div >  <span > <img  src ="https://cdn.pixabay.com/photo/2015/05/26/22/33/kindle-785686_960_720.jpg" /> </span >       </div >       <div >          <h3 > Android Html交互:</h3 >          <button  onclick ="show()"  id ='btn' > toast</button >       </div >       <br />       <script  type ="text/javascript" >          function  show ( )  {            android.toastMessage("js 点击" );         }         function  change_theme (bg, txt )  {            var  body =  document .getElementsByTagName('body' )[0 ];            body.style.background = bg;            body.style.color = txt;         }                  function  callJS ( )  {            return  "hello" ;         }      </script >  </body > 
 
3. android 调用js方法 android 调用js方法,也是通过loadUrl来实现的,需要注意的前缀,以及是否需要传参返回结果
1 2 webview.loadUrl("javascript:change_theme('#ffffff','#000000')" ); 
 
如果有返回结果,则可以考虑下面的写法
1 2 3 4 5 6 7 8 mWebView.evaluateJavascript("javascript:callJS()" , new  ValueCallback<String>() {     @Override      public  void  onReceiveValue (String value)   {                  Toast.makeText(activity, "js回调:"  + message, Toast.LENGTH_LONG).show();     } }); 
 
III. 长按图片下载 
下面实现来自于搜索,忘了具体的来源了(主要还是习惯不好,拷代码,没有拷出处,我的锅)… 
 
一种常见的case,长按图片下载,下面给出基本的额使用套路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 handler = new  Handler() {     @Override      public  void  handleMessage (Message msg)   {         super .handleMessage(msg);         String picFile = (String) msg.obj;         String[] split = picFile.split("/" );         String fileName = split[split.length - 1 ];         try  {             MediaStore.Images.Media.insertImage(getApplicationContext().getContentResolver(), picFile, fileName, null );         } catch  (FileNotFoundException e) {             e.printStackTrace();         }                  getApplicationContext().sendBroadcast(new  Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"  + picFile)));         Toast.makeText(SquareDetailActivity.this , showContent("图片保存图库成功" ), Toast.LENGTH_LONG).show();     } }; webView.setOnLongClickListener(new  View.OnLongClickListener() {     @Override      public  boolean  onLongClick (View view)   {         final  WebView.HitTestResult hitTestResult = webView.getHitTestResult();                  if  (hitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE ||                 hitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {                          AlertDialog.Builder builder = new  AlertDialog.Builder(getContext());             builder.setTitle("提示" );             builder.setMessage("保存图片到本地" );             builder.setPositiveButton(LanguageFormatHelper.formatContent("确认" ), new  DialogInterface.OnClickListener() {                 @Override                  public  void  onClick (DialogInterface dialogInterface, int  i)   {                     String url = hitTestResult.getExtra();                                          DownPicUtil.downPic(url, new  DownPicUtil.DownFinishListener() {                         @Override                          public  void  getDownPath (String s)   {                             Message msg = Message.obtain();                             msg.obj = s;                             handler.sendMessage(msg);                         }                     });                 }             });             builder.setNegativeButton(LanguageFormatHelper.formatContent("取消" ), new  DialogInterface.OnClickListener() {                                  @Override                  public  void  onClick (DialogInterface dialogInterface, int  i)   {                 }             });             AlertDialog dialog = builder.create();             dialog.show();         }         return  true ;     } }); 
 
图片下载类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 public  class  DownPicUtil   {         public  static  void  downPic (String url, DownFinishListener downFinishListener)   {                  String filePath = Environment.getExternalStorageDirectory().getPath();         File file = new  File(filePath + File.separator + "webViewCache" );         if  (!file.exists()) {             file.mkdir();         }         loadPic(file.getPath(), url, downFinishListener);     }     private  static  void  loadPic (final  String filePath, final  String url, final  DownFinishListener downFinishListener)   {         Log.e("下载图片的url" , url);         new  AsyncTask<Void, Void, String>() {             String fileName;             InputStream is;             OutputStream out;             @Override              protected  String doInBackground (Void... voids)   {                                  String[] split = url.split("/" );                 String newString = split[split.length - 1 ];                 if  (newString.length() >= 20 ) {                     fileName = newString.substring(newString.length() - 20 , newString.length() - 1 );                 } else  {                     fileName = newString;                 }                                  File picFile = new  File(filePath + File.separator + fileName);                 if  (picFile.exists()) {                     return  picFile.getPath();                 }                 try  {                     URL picUrl = new  URL(url);                                          is = picUrl.openStream();                     if  (is == null ) {                         return  null ;                     }                     out = new  FileOutputStream(picFile);                     byte [] b = new  byte [1024 ];                     int  end;                     while  ((end = is.read(b)) != -1 ) {                         out.write(b, 0 , end);                     }                     Log.e("OK??" , "----------" );                     if  (is != null ) {                         is.close();                     }                     if  (out != null ) {                         out.close();                     }                 } catch  (FileNotFoundException e) {                     e.printStackTrace();                 } catch  (IOException e) {                     e.printStackTrace();                 }                 return  picFile.getPath();             }             @Override              protected  void  onPostExecute (String s)   {                 super .onPostExecute(s);                 if  (s != null ) {                     downFinishListener.getDownPath(s);                 }             }         }.execute();     }          public  interface  DownFinishListener   {         void  getDownPath (String s)  ;     } } 
 
II. 其他 一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明 尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
3. 扫描关注 一灰灰blog