首页前端开发HTML详解android与HTML混合开发总结

详解android与HTML混合开发总结

时间2024-01-24 23:18:28发布访客分类HTML浏览1002
导读:收集整理的这篇文章主要介绍了详解android与HTML混合开发总结,觉得挺不错的,现在分享给大家,也给大家做个参考。 现在很多的 APP中会嵌套HTML5的页面,比如经常变化的等等,有一部分页面需要原生Java与HTML5中的j...
收集整理的这篇文章主要介绍了详解android与HTML混合开发总结,觉得挺不错的,现在分享给大家,也给大家做个参考。

现在很多的 APP中会嵌套HTML5的页面,比如经常变化的等等,有一部分页面需要原生Java与HTML5中的js进行交互操作,下面介绍一下andROId中HTML5的使用:

1、关于HTML5种cookie

网页中可能会用到 用户信息等很多参数,可以提前把这些信息放到cookie中,可以采用以下方法: 

public static void addCookies(Context context, WebView webView, String url) {
        String url=“https://www.xxxx.COM/xx/xx/”          String PRotocol = "";
              String authorITy = "";
          try {
                  URL urlObj = new URL(url);
                  protocol = urlObj.getProtocol();
                  authority = urlObj.getAuthority();
         }
 catch (Exception e) {
                 e.printStackTrace();
         }
              String ua = webView.getSettings().getUserAgentString();
             webView.getSettings().setUserAgentString(Constant.PROJECT_NamE + "/" + ParAMHandler.getVersion(context) + "(" + ua + ";
     HFWSH)");
              if (!TextUtils.iSEMpty(url) &
    &
     !TextUtils.isEmpty(protocol) &
    &
 !TextUtils.isEmpty(authority)) {
                 if (protocol.equals("https") &
    &
     authority.indexOf("liepin.com") >
 -1) {
                     CookieSyncManager.createinstance(context);
                     CookieManager cookieManager = CookieManager.getInstance();
                     cookieManager.setAcceptCookie(true);
                 try {
                         ListString>
     data = getCookiesString();
                     if (!ListUtils.isEmpty(data)) {
                         for (String value : data) {
                                 cookieManager.setCookie(url, value);
                         }
                     }
                         cookieManager.setCookie(url, "client_id=" + Constant.CLIENT_ID + ";
    path=/;
    domain=.XXXX.com");
                         cookieManager.setCookie(url, "appversion=" + Constant .VERSION + ";
    path=/;
    domain=.XXXX.com");
                  CookieSyncManager.getInstance().sync();
          }
 catch (Exception e) {
                  LOGUtils.e("Exception:" + e.getMessage());
          }
        }
      }
    }
    
public ListString>
 getCookiesString() {
          ArrayList data = new ArrayList();
          this.clearExpired();
          Collection values = this.mCookies.values();
          Iterator VAR3 = values.iterator();
        while(var3.hasNext()) {
              SwiftCookie c = (SwiftCookie)var3.next();
              data.add(c.toCookieString());
     }
          return data;
 }
    

在 mWebView.loadUrl(Url)之前添加cookie,网页就可以通过cookie取到相应的参数值了。

2、关于js的安全问题

js在4.2以前有漏洞

通过JavaScript,可以访问当前设备的SD卡上面的任何东西,甚至是联系人信息,短信等。好,我们一起来看看是怎么出现这样的错误的。

1,WebView添加了JavaScript对象,并且当前应用具有读写SDCard的权限,也就是:android.PErmission.WRITE_EXTERNAL_STORAGE

2,JS中可以遍历window对象,找到存在“getClass”方法的对象的对象,然后再通过反射的机制,得到Runtime对象,然后调用静态方法来执行一些命令,比如访问文件的命令.

3,再从执行命令后返回的输入流中得到字符串,就可以得到文件名的信息了。然后想干什么就干什么,好危险。核心JS代码如下:

 function execute(cmdargs)    {
        for (var obj in window) {
            if ("getClass" in window[obj]) {
                    alert(obj);
                    return  window[obj].getClass().forName("java.lang.Runtime")                     .getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
            }
        }
   }
       

解决方案:

1,Android 4.2以上的系统

在Android 4.2以上的,GOOGLE作了修正,通过在Java的远程方法上面声明一个@JavascriptInterface,如下面代码:

class JsObject {
      @JavascriptInterface      public String toString() {
     return "injectedObject";
 }
   }
       webView.addJavascriptInterface(new JsObject(), "injectedObject");
       webView.loadData("", "text/html", null);
       webView.loadUrl("javascript:alert(injectedObject.toString())");
      

2,Android 4.2以下的系统

这个问题比较难解决,但也不是不能解决。

首先,我们肯定不能再调用addJavascriptInterface方法了。关于这个问题,最核心的就是要知道JS事件这一个动作,JS与Java进行交互我们知道,有以下几种,比prompt, alert等,

这样的动作都会对应到WebChromeClient类中相应的方法,对于prompt,它对应的方法是onJsPrompt方法,这个方法的声明如下:

public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) 

通过这个方法,JS能把信息(文本)传递到Java,而Java也能把信息(文本)传递到JS中,通知这个思路我们能不能找到解决方案呢?

经过一番尝试与分析,找到一种比较可行的方案,请看下面几个小点:

【1】让JS调用一个Javascript方法,这个方法中是调用prompt方法,通过prompt把JS中的信息传递过来,这些信息应该是我们组合成的一段有意义的文本,可能包含:特定标识,方法名称,参数等。

在onJsPrompt方法中,我们去解析传递过来的文本,得到方法名,参数等,再通过反射机制,调用指定的方法,从而调用到Java对象的方法。

【2】关于返回值,可以通过prompt返回回去,这样就可以把Java中方法的处理结果返回到Js中。

【3】我们需要动态生成一段声明Javascript方法的JS脚本,通过loadUrl来加载它,从而注册到html页面中,具体的代码如下:

javascript:(function JsAddJavascriptInterface_(){
        if (typeof(window.jsInterface)!='undefined') {
                    console.log('window.jsInterface_js_interface_name is exist!!');
}
         else {
            window.jsInterface = {
                        onButtonClick:function(arg0) {
                     return prompt('MyApp:'+JSON.stringify({
obj:'jsInterface',func:'onButtonClick',args:[arg0]}
    ));
                }
,                               onImageClick:function(arg0,arg1,arg2) {
                    prompt('MyApp:'+JSON.stringify({
obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}
    ));
               }
,           }
    ;
       }
   }
       )()  

说明:

1,上面代码中的jsInterface就是要注册的对象名,它注册了两个方法,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2),如果有返回值,就添加上return。

2,prompt中是我们约定的字符串,它包含特定的标识符MyApp:,后面包含了一串JSON字符串,它包含了方法名,参数,对象名等。

3,当JS调用OnButtonClick或onImageClick时,就会回调到Java层中的onJsPrompt方法,我们再解析出方法名,参数,对象名,再反射调用方法。

4,window.jsInterface这表示在window上声明了一个Js对象,声明方法的形式是:方法名:function(参数1,参数2)

3、在html5中进行java和js的交互

1)、方法一:

mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.addJavascriptInterface(this, "xxx");
    

然后在当前类中实现以下方法:

@JavascriptInterface  public void callbackFromH5(final String j) {
    //TODO  }
    

callbackFromH5的名字必须和网页中的js方法名一样

Java调用js方法:

mWebView.loadUrl(String.format("javascript:java2js(0)"));
    //这里是java端调用webview的JS 

js方法名需要和网页端一直

2)方法二: 

jsbridge方法(https://github.com/lzyzsd/JsBridge)

Android JsBridge 就是用来在 Android app的原生 java 代码与 javascript 代码中架设通信(调用)桥梁的辅助工具

1 将jsBridge.jar引入到我们的工程 

Android Studio:

  repositories {
  // ...  maven {
 url "https://JITpack.io" }
  }
  dependencies {
   compile 'com.github.lzyzsd:jsbridge:1.0.4'  }
    

2、布局文件

?XMl version="1.0" encoding="utf-8"?>
        LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical" >
                !-- button 演示Java调用web -->
            Button             android:id="@+id/button"           android:layout_width="match_parent"           android:text="@string/button_name"           android:layout_height="dp"           />
                  !-- webview 演示web调用Java -->
           com.github.lzyzsd.jsbridge.BridgeWebView           android:id="@+id/webView"           android:layout_width="match_parent"           android:layout_height="match_parent" >
            /com.github.lzyzsd.jsbridge.BridgeWebView>
          /LinearLayout>
      

3、java代码

//加载服务器网页            webView.loadUrl("https://www.baidu.com");
                //必须和js同名函数。            webView.registerHandler("submitFromWeb", new BridgeHandler() {
                    @override                public void handler(String data, CallBackFunction function) {
                           String str ="html返回给java的数据:" + data;
                                      makeText(MainActivity.this, str, LENGTH_SHORT).show();
                          Log.i(TAG, "handler = submitFromWeb, data from web = " + data);
                       function.onCallBack( str + ",Java经过处理后:"+ str.substring(,));
               }
              }
    );
               //模拟用户获取本地位置           User user = new User();
               Location location = new Location();
               location.address = "xxx";
               user.location = location;
               user.name = "Bruce";
              webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() {
               @Override               public void onCallBack(String data) {
                       makeText(MainActivity.this, "网页在获取你的信息", LENGTH_SHORT).show();
                  }
           }
    );
                  webView.send("hello");
      
webView.callHandler("functionInJs", "data from Java", new CallBackFunction() {
                      @Override                   public void onCallBack(String data) {
                           // TODO Auto-generated method stub                       Log.i(TAG, "reponse data from js " + data);
                   }
                  }
    );
      

js调用

 var str1 = document.getElementById("text1").value;
                 var str2 = document.getElementById("text2").value;
                   //调用本地java方法               window.WebViewJavascriptBridge.callHandler(                   'submitFromWeb'                   , {
'param': str}
                   , function(responseData) {
                       document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData                  }
                  );
    //注册事件监听   document.addEventListener(                      'WebViewJavascriptBridgeReady'                      , function() {
                          callback(WebViewJavascriptBridge)                      }
    ,                      false                  );
    //注册回调函数,第一次连接时调用 初始化函数  connectWebViewJavascriptBridge(function(bridge) {
              bridge.init(function(message, responseCallback) {
                      console.log('JS got a message', message);
                  var data = {
                      'Javascript Responds': 'Wee!'                  }
    ;
                      console.log('JS responding with', data);
                      responseCallback(data);
              }
    );
                 bridge.registerHandler("functionInJs", function(data, responseCallback) {
                      document.getElementById("show").innerHTML = ("data from Java: = " + data);
                      var responseData = "Javascript Says Right back aka!";
                      responseCallback(responseData);
              }
    );
          }
    )  

4、关于webView的优化

1、设置WebView 缓存模式

private void initWebView() {
                                    mWebView.getSettings().setJavaScriptEnabled(true);
                    mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
                    mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
      //设置 缓存模式                // 开启 DOM storage API 功能                mWebView.getSettings().setDomStorageEnabled(true);
                    //开启 database storage API 功能                mWebView.getSettings().setDatabaseEnabled(true);
                    String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME;
           //      String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME;
                   Log.i(TAG, "cacheDirPath="+cacheDirPath);
                   //设置数据库缓存路径               mWebView.getSettings().setDatabasePath(cacheDirPath);
                   //设置  Application Caches 缓存目录               mWebView.getSettings().setAppCachePath(cacheDirPath);
                   //开启 Application Caches 功能               mWebView.getSettings().setAppCacheEnabled(true);
     

2、清除缓存

/**            * 清除WebView缓存            */            public void clearWebViewCache(){
                                //清理Webview缓存数据库                try {
                        deleteDatabase("webview.db");
                         deleteDatabase("webviewCache.db");
               }
 catch (Exception e) {
                       e.printStackTrace();
               }
                                  //WebView 缓存文件               File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME);
                   Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath());
                                  File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache");
                   Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath());
                              //删除webview 缓存目录               if(webviewCacheDir.exists()){
                       deleteFile(webviewCacheDir);
               }
               //删除webview 缓存 缓存目录               if(appCacheDir.exists()){
                       deleteFile(appCacheDir);
               }
           }
      

3、在使用WebView加载网页的时候,有一些固定的资源文件如js/css/图片等资源会比较大,如果直接从网络加载会导致页面加载的比较慢,而且会消耗比较多的流量。所以这些文件应该放在assets里面同app打包。

解决这个问题用到API 11(HONEYCOMB)提供的shouldInterceptRequest(WebView view, String url) 函数来加载本地资源。

API 21又将这个方法弃用了,是重载一个新的shouldInterceptRequest,需要的参数中将url替换成了成了request。

比如有一个图片xxxxx.png,这个图片已经放在了assets中,现在加载了一个外部html,就需要直接把assets里面的图片拿出来加载而不需要重新从网络获取。当然可以在html里面将图片链接换成file:///android_asset/xxxxx.png,

但是这样这个html就不能在Android ,ios,WAP中公用了。

webView.setWebViewClient(new WebViewClient() {
                    @Override                public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                        WebResourceResponse response = null;
                        if (Build.VERSION.SDK_INT >
= Build.VERSION_CODES.HONEYCOMB){
                            response = super.shouldInterceptRequest(view,url);
                        if (url.contains("xxxxx.png")){
                            try {
                                   response = new WebResourceResponse("image/png","UTF-8",getAssets().open("xxxxx.png"));
                           }
 catch (IOException e) {
                                   e.printStackTrace();
                           }
                       }
                   }
       //                return super.shouldInterceptRequest(view, url);
                       return  response;
               }
                  @TargetApi(Build.VERSION_CODES.LOLLIPOP)               @Override               public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
                       WebResourceResponse response = null;
                       response =  super.shouldInterceptRequest(view, request);
                   if (url.contains("xxxxx.png")){
                       try {
                               response = new WebResourceResponse("image/png","UTF-",getAssets().open("xxxxx.png"));
                       }
 catch (IOException e) {
                               e.printStackTrace();
                       }
                   }
                       return response;
               }
   }
      

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

androidHTML

若转载请注明出处: 详解android与HTML混合开发总结
本文地址: https://pptw.com/jishu/585863.html
canvas里面如何基于随机点绘制一个多边形的方法 canvas环形倒计时组件的示例代码

游客 回复需填写必要信息