Android中js调用java本地方法的三种方式 太过爱你忘了你带给我的痛 2021-06-26 16:06 972阅读 0赞 ## MainActivity.java ## package com.fedming.webtonativedemo; import android.app.Activity; import android.os.Bundle; import android.webkit.JavascriptInterface; import android.webkit.JsPromptResult; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import java.util.HashMap; /** * <pre> * author : fdm * time : 2018/03/08 * desc : WebView与本地方法交互的三种方法Demo * version: 1.0 * </pre> */ public class MainActivity extends Activity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = (WebView) findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setAllowFileAccess(false); webSettings.setSupportZoom(false); webSettings.setUseWideViewPort(true); webSettings.setJavaScriptEnabled(true); webSettings.setDatabaseEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setLoadWithOverviewMode(true); webSettings.setLoadsImagesAutomatically(true); webSettings.setDefaultTextEncodingName("UTF-8"); webView.setWebChromeClient(new WebChromeClient()); /** * 第一种 * 原理:直接构造本地化对象,映射到js页面中访问,底层原理借助了V8引擎(Android4.2 以下系统有WebView漏洞) */ webView.addJavascriptInterface(new JSInterface(), "MyObj"); /** * 第二种 * 回调方法中(shouldOverrideUrlLoading)拦截请求url,分析url格式以及自定义协议、参数名称可得到具体参数 * tips:需要再次调用页面js方法获取返回值 */ webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("http:") || url.startsWith("https:")) { return false; } //协议url:"js://demo?arg=111" try { String protocol = Utils.getUrlScheme(url); if ("js".equals(protocol)) { HashMap<String, String> map = Utils.getUrlParams(url); String arg = map.get("arg"); String res = getLocalString(arg); //再次调用web中js方法,将参数传回web去 webView.loadUrl("javascript:click_result(" + res + ")"); } } catch (Exception e) { e.printStackTrace(); } return true; } }); /** * 第三种 * 借助WebChromeClient的回调方法(共三个),拦截JS中的三个方法:alert,confirm,prompt,解析参数,得到指定格式数据 * tips:需要页面和本地解析格式做一个约束 */ webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); } @Override public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { return super.onJsConfirm(view, url, message, result); } @Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) { if (url.startsWith("http:") || url.startsWith("https:")) { return false; } //协议url:"js://demo?arg=111" try { String protocol = Utils.getUrlScheme(message); if ("js".equals(protocol)) { HashMap<String, String> map = Utils.getUrlParams(message); String arg = map.get("arg"); String res = getLocalString(arg); result.confirm(res); } } catch (Exception e) { e.printStackTrace(); } return true; } }); //加载asset中的网页 webView.loadUrl("file:///android_asset/js_demo.html"); } /** * 本地化JS对象,供web调用 * sdk17版本以上需要加上注解 */ class JSInterface { @JavascriptInterface public String getPwd(String pwd) { //执行本地方法,返回结果到web return getLocalString(pwd); } } /** * 本地方法 * * @param txt txt * @return txt */ public String getLocalString(String txt) { return txt; } } ## Utils.java ## package com.fedming.webtonativedemo; import java.util.HashMap; /** * <pre> * author : fdm * time : 2018/03/08 * desc : Utils * version: 1.0 * </pre> */ public class Utils { public Utils() { } /** * 获取url中的协议 * * @param url url * @return protocol */ public static String getUrlScheme(String url) { int index = url.indexOf(":"); return url.substring(0, index); } /** * 获取url中的参数 * * @param url url * @return args */ public static HashMap<String, String> getUrlParams(String url) { int index = url.indexOf("?"); String argStr = url.substring(index + 1); String[] argAry = argStr.split("&"); HashMap<String, String> argMap = new HashMap<String, String>(argAry.length); for (String arg : argAry) { System.out.println("arg:" + arg); String[] argAryT = arg.split("="); argMap.put(argAryT[0], argAryT[1]); } return argMap; } } ## `main`文件夹下 `assets`文件夹 ## js\_demo.html <!DOCTYPE html> <html> <head> <title>WebToNativeDemo</title> <script> function click_one(){ var result = window.MyObj.getPwd("111"); alert("第一个按钮结果:"+result); } function click_two(){ document.location = "js://demo?arg=222"; } function click_result(result){ alert("第二个按钮结果:"+result); } function click_three(){ var result=prompt("js://demo?arg=333",""); alert("第三个按钮结果:"+result); } </script> <style type="text/css"> input{ width: 800px; height: 180px; margin: 50px auto; text-align:center; font-size:50px; } </style> </head> <body> <p style=" margin:0 auto; text-align:center;"><input id="one" class="submit" name="submit" type="submit" onclick="click_one()"/></p> <p style=" margin:0 auto; text-align:center;"><input id="two" class="submit" name="submit" type="submit" onclick="click_two()"/></p> <p style=" margin:0 auto; text-align:center;"><input id="three" class="submit" name="submit" type="submit" onclick="click_three()"/></p> </body> </html> ## layout文件夹 ## activity\_main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/linear_layout" android:layout_width="match_parent" android:layout_height="54dp" android:background="@color/colorPrimary" android:gravity="center" android:text="WebToNative" android:textColor="@android:color/white" android:textSize="18sp" /> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/linear_layout" /> </RelativeLayout> ## app文件夹下build.gradle ## apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion '27.0.3' defaultConfig { applicationId "com.fedming.webtonativedemo" minSdkVersion 19 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.0.1' testCompile 'junit:junit:4.12' } ## 项目根目录下build.gradle ## // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() google() } dependencies { classpath 'com.android.tools.build:gradle:3.1.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() google() } } task clean(type: Delete) { delete rootProject.buildDir } ## gradle-wrapper.properties ## #Tue Oct 30 12:36:36 CST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip ## AndroidManifest.xml ## <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.fedming.webtonativedemo"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ## 运行结果如图: ## ![在这里插入图片描述][20181030172345542.png] ![在这里插入图片描述][20181030172407636.png] [20181030172345542.png]: /images/20210626/d1d68736391d4beaa215fd4b42282bd6.png [20181030172407636.png]: /images/20210626/57a1fb51fec34757bc305295414dad14.png
还没有评论,来说两句吧...