WebView使用
Android混合开发之Activity类与html页面之间的相互跳转(并解决黑屏问题)
android studio创建assets目录并且利用webView加载其html
Android WebView使用全面解析(加载网络资源、本地HTML,JS交互)
“热更新”、“热部署”相信对于混合式开发的童鞋一定不陌生,那么APP怎么避免每次升级都要在APP应用商店发布呢?这里就用到了混合式开发的概念,对于电商网站尤其显得重要,不可能每次发布一个活动,都要发布一个现版本,当然这样对于Android还算可以,但是对于Ios呢?苹果应用商店每次审核的时间基本都在1~2周,这对于一个促销活动来说审核时间实在太长。而混合式开发正好可以解决这个问题,基本的原理时,通过原生控件实现APP的主体结构,借助H5开发对应的页面,这样每次发布活动,只需要在服务器端,将活动发布,便可以达到所有安装用户不升级便可查阅最新活动的效果。今天就为大家分享一下,如何实现JavaScript与APP原生控件交互。
一、首先为大家介绍的是JS与Android交互,首先让大家看一下Android工程的目录结构:
JSObject.java文件封装了JS调用Android原生控件的方法;JsActivity.java是调用WebView控件实现网页页面加载,以及进行控件调用JS方法的封装;test.html是我们加载的HTML页面。接下来我们具体看一下实现:
JsActivity.java
package com.example.administrator.helloworld;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;
/**
* SuppressLint一定要加上去!!!
* 低版本可能没问题,高版本JS铁定调不了Android里面的方法
*/
@SuppressLint("SetJavaScriptEnabled")
public class JsActivity extends Activity {
private Button button1,button2;
private WebView mWebView;
private MyWebViewClient WVClient;
private WebSettings webSettings;
private MyWebChromeClient chromeClient;
//封装接收js调用Android的方法类
private JSObject jsobject;
//异步请求
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_js);
init();
initView();
setButton();
}
private void setButton() {
//无参调用
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
/*mHandler.post(new Runnable() {
@Override
public void run() {
mWebView.loadUrl("javascript:showNoMessage()");
}
});*/
mWebView.loadUrl("javascript:showNoMessage()");
}
});
//有参调用
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mHandler.post(new Runnable() {
@Override
public void run() {
mWebView.loadUrl("javascript:showMessage('顺带给JS传个参数')");
}
});
}
});
}
private void init() {
mWebView = (WebView) findViewById(R.id.webview);
button1 = (Button)findViewById(R.id.button1);
button2 = (Button)findViewById(R.id.button2);
WVClient = new MyWebViewClient();
chromeClient = new MyWebChromeClient();
jsobject = new JSObject(JsActivity.this);
}
private void initView() {
webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setSavePassword(false);
//支持多种分辨率,需要js网页支持
webSettings.setUserAgentString("mac os");
webSettings.setDefaultTextEncodingName("utf-8");
//显示本地js网页
//mWebView.setBackgroundResource(R.drawable.myload);//设置背景图片
//mWebView.setBackgroundColor(android.R.color.black);
mWebView.setBackgroundColor(0);//先设置背景色为transparent
mWebView.setBackgroundResource(R.drawable.loading);//然后设置背景图片
mWebView.loadUrl("file:///android_asset/test.html");
mWebView.setWebViewClient(WVClient);
mWebView.setWebChromeClient(chromeClient);
//注意第二个参数android,这个是JS网页调用Android方法的一个类似ID的东西
mWebView.addJavascriptInterface(jsobject, "android");
//第一个参数为this,则为当前活动
//mWebView.addJavascriptInterface(this, "android");
}
@JavascriptInterface
public void mymethod(String str,String str1) {
Toast.makeText(this, (str + "_" + str1), Toast.LENGTH_SHORT).show();
/* Intent intent = new Intent();
intent.putExtra("name", str);
intent.putExtra("pass", str);
intent.setClass(PhoneGap2Activity.this, TestActivity.class);
startActivity(intent);*/
}
}
页面的配置文件(activity_js.xml)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.helloworld.JsActivity" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:text="无参" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="有参" /> <WebView android:id="@+id/webview" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_below="@+id/button2" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/button1" android:layout_alignBottom="@+id/button1" android:layout_centerHorizontal="true" android:text="js与android交互" /> </RelativeLayout>
JSObject.java
package com.example.administrator.helloworld;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
/**
* JS调用android的方法
* @JavascriptInterface仍然必不可少
*/
public class JSObject {
private Context context;
public JSObject(Context context){
this.context = context;
}
//js调用无参方法
@JavascriptInterface
public void callNull(){
Toast.makeText(context, "JsCallAndroid", Toast.LENGTH_SHORT).show();
}
//js调用有参方法
@JavascriptInterface
public void callMessage(String data){
Toast.makeText(context, data, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra("param1", data);
intent.putExtra("param2", "World!");
context.startActivity(intent);
}
//js调用有参方法,参数类型:JSON
@JavascriptInterface
public void callJson(String data) throws JSONException{
JSONArray jsonArray = new JSONArray(data);
Toast.makeText(context, jsonArray.toString(), Toast.LENGTH_SHORT).show();
}
//js调用有参方法,参数类型:JSON,获取电话号码拨打
@JavascriptInterface
public void callPhone(String data){
context.startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + data)));
}
@JavascriptInterface
public void mymethod(String str,String str1) {
Toast.makeText(context, str + "_" + str1, Toast.LENGTH_SHORT).show();
/* Intent intent = new Intent();
intent.putExtra("name", str);
intent.putExtra("pass", str);
intent.setClass(PhoneGap2Activity.this, TestActivity.class);
startActivity(intent);*/
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra("param1", str);
intent.putExtra("param2", "World!");
context.startActivity(intent);
}
}
加载的HTML页面:
<style>
.main-wrap ul {
width: 100%;
display: inline-block;
padding-top: 20px;
}
.main-wrap ul li {
float: left;
width: 100%;
height: 40px;
line-height: 40px;
font-size: 14px;
margin-bottom: 20px;
background-color: #00D000;
color: #fff;
text-align: center;
cursor: pointer;
}
.main-wrap ul li:active {
opacity: 0.8;
}
</style>
<script type="text/javascript" src="js/jquery-1.7.1.min.js"></script>
<div class="main-wrap">
<ul class="postAndroid">
<li onclick="jsCallAndroid('1')">No Paramer调用原始控件</li>
<li onclick="jsCallAndroid('2')">传Paramer调用原始控件</li>
<li onclick="jsCallAndroid('3')">以JSON格式传Paramer调用原始控件</li>
<li onclick="jsCallAndroid('4')">调用TEL服务</li>
</ul>
<a data-role="button" >跳转到activity</a>
<input id="b" type="button" value="跳转" onclick="testClick()"/>
用户名:<input type="text" id="text1" placeholder="输入内容" />
密 码:<input type="text" id="text2" placeholder="输入内容" />
</div>
<script>
$(function(){
//$("#b").click(function() {
//alert(1111);
// android.method($("#text1").val(),$("#text2").val());
// });
})
function testClick(){
android.mymethod($("#text1").val(),$("#text2").val());
}
function jsCallAndroid(rel) {
switch(rel){
case "1":
android.callNull();
break;
case "2":
android.callMessage("javaScript操作Android原生");
break;
case "3":
var json = "[{\"name\":\"网\", \"phone\":\"4006069\"}]";
android.callJson(json);
break;
case "4":
android.callPhone("4006069");
break;
}
}
function showNoMessage() {
alert("Android无参调用");
}
function showMessage(data) {
alert("Android有*参调用-data:" + data);
}
</script>
这里因为需要实现一个拨打电话的功能,所以需要在AndroidManifest.xml文件中添加拨打电话的权限:
<uses-permission android:name="android.permission.CALL_PHONE" />
当然这里加载的页面是本地页面,当加载网络页面时需要添加请求网络权限:
<uses-permission android:name="android.permission.INTERNET" />
好了关于JS与Android原生的控件进行相互调用的知识就介绍完了,最后附上DEML下载地址:http://pan.baidu.com/s/1eSza8Pc