Android中js呼叫java本地方法的三種方式
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>
執行結果如圖:
相關文章
- a 標籤中呼叫js的幾種方法JS
- shell中呼叫shell的三種方式&並行shell並行
- uni-app&H5&Android混合開發三 || uni-app呼叫Android原生方法的三種方式APPH5Android
- 如何在java中呼叫js方法JavaJS
- JS的五種函式呼叫方式JS函式
- Android本地儲存的幾種方式Android
- Java中獲取Class物件的三種方式Java物件
- Java中Elasticsearch 實現分頁方式(三種方式)JavaElasticsearch
- jmeter學習指南之Beanshell 呼叫 java 程式碼的三種方式JMeterBeanJava
- 三種方式本地執行Knative
- 在Java中呼叫Groovy方法的又一種方法:使用介面Java
- Java中Singleton的三種實現方式解析Java
- Java中list顯示的三種方法Java
- 函式呼叫的三種方式 __cdecl、__stdcall、__fastcall函式AST
- Android 使用js呼叫JavaAndroidJSJava
- 說說Java非同步呼叫的幾種方式Java非同步
- Java 反射機制的三種方式Java反射
- Android 三種播放視訊的方式Android
- Flutter 三種JSON解析方式FlutterJSON
- Flutter 解析JSON 三種方式FlutterJSON
- Linux中執行Shell指令碼的方式(三種方法)Linux指令碼
- js實現繼承的三種方式JS繼承
- 在Java中本地進行執行緒間資料傳輸的三種方式和原始碼展示Java執行緒原始碼
- JS讀取本地TXT文字的兩種方法JS
- js解析url的三種方法JS
- PHP呼叫java類的兩種方法(轉)PHPJava
- Vue元件開發實錄:元件的三種呼叫方式Vue元件
- JS中的多種繼承方式JS繼承
- js中建立物件的幾種方式JS物件
- 一種WebService的呼叫方式Web
- Linux 下系統呼叫的三種方法Linux
- js呼叫後臺程式碼的幾種方法JS
- java高階用法之:呼叫本地方法的利器JNAJava
- java程式碼中init method和destroy method的三種使用方式Java
- 【JS】JS陣列新增元素的三種方法JS陣列
- 外部js呼叫vue的methods中的方法JSVue
- 解析Json字串的三種方法JSON字串
- Java中建立物件的5種方式Java物件