韩伟佳 2018-05-17
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