最近在慕课网学习了关于高德地图组件的课程(其实就是一个广告,内容和官网的API完全一样),发现这个JavaScript API比Android API简单方便多了,于是就打算放在Android APP上来实现,花了一点小功夫,但是最终还是实现了,后来打算扩展的时候遇到个问题:就是高德官网有一个坐标拾取点(高德的坐标和我们平时取的坐标不一样,可以将高德坐标理解为中国的国标,直接获取的坐标是国际标准的坐标),后来发现有html文件直接实现了这个功能,于是就把这个html扒出来了,但是重点问题来了:如何将目标地点传进来,如何将获取到的坐标传出来?最后Android APP不用SDK就实现了位置标注、周边搜索、路线规划等,具体如何实现呢?本文打算将我的思路分为四步给大家娓娓道来:
一、地图组件API;
二、Android布局代码;
三、java代码以及思路;
四、html代码以及思路
五、重头戏——Android与JavaScript交互的实现。
首先来讲第一个,地图组件的API,其实这个非常简单好用,原因就是只要一个key值(大家可以直接去高德地图上申请一个JavaScript的key值,这里就不讲key值了),你就可以按照他定义的规则拼写出URL,然后就可以实现位置标注、路线规划、周边搜索、选址组件(官网的称呼),这里我就简单的说一下这个URL拼写结果,具体的大家可以到官网看一看,因为确实是口水话,简单又费时,所以就不复制过来了,大家可以直接看链接:
http://lbs.amap.com/api/lightmap/guide/picker/
位置标注使用方法:http://m.amap.com/navi/?dest=116.470098,39.992838&destName=阜通西&hideRouteIcon=1&key=(您申请的key)
PC端效果如图:
扫描二维码,看看移动端运行效果:
路线规划使用方法一:
http://m.amap.com/navi/?start=116.403124,39.940693&dest=116.481488,39.990464&destName=一条驾车路线&key=(您的KEY)
PC端效果如图:
扫描二维码,看看移动端运行效果:
路线规划使用方法二:
http://m.amap.com/navi/?start=116.403124,39.940693&dest=116.481488,39.990464&destName=阜通西&naviBy=car&key=(您的KEY)
PC端效果如图:
扫描二维码,看看移动端运行效果:
周边搜索使用方法:
http://m.amap.com/around/?locations=116.470098,39.992838&keywords=美食,KTV,地铁站,公交站&defaultIndex=3&defaultView=&searchRadius=5000&key=(您的KEY)
PC端效果如图:
扫描二维码,看看移动端运行效果:
最后一种选址组件的使用方法:
http://m.amap.com/picker/?keywords=酒店,超市,医院&key=您申请的key值
这个稍微复杂一点,反正我也没有弄清楚,欢迎大家留言讨论,最后PC端实现的效果如图:
今天暂时写到这里,明天将其余几条一下写出来,欢迎大家留言评论,谢谢!
其余的几节暂时先欠着,把我写的一个自定义TopBar的引用写出来,大家先看看,明天不讲(只贴代码)
先看自定义属性文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name = "TopBar">
<attr name = "title" format = "string" />
<attr name = "titleTextSize" format = "dimension" />
<attr name = "titleTextColor" format = "color" />
<attr name = "leftColor" format = "color" />
<attr name = "leftBackGround" format = "reference|color" />
<attr name = "leftText" format = "string" />
<attr name = "rightColor" format = "color" />
<attr name = "rightBackGround" format = "reference|color" />
<attr name = "rightText" format = "string" />
</declare-styleable>
</resources>
再看看java代码实现如何自定义:
package com.weixing.topbarlibrary;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class TopBarView extends RelativeLayout{
private Button leftButton,rightButton;
private TextView tvTitle;
private int leftColor;
private Drawable leftBackGround;
private String leftText;
private int rightColor;
private Drawable rightBackGround;
private String rightText;
private String title;
private float titleTextSize;
private int titleTextColor;
private TopBarViewClickListener listener;
public interface TopBarViewClickListener{
public void leftButtonClickListener();
public void rightButtonClickListener();
}
public TopBarView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TopBar);
leftColor = ta.getColor(R.styleable.TopBar_leftColor, 0);
leftBackGround = ta.getDrawable(R.styleable.TopBar_rightBackGround);
leftText = ta.getString(R.styleable.TopBar_leftText);
rightColor = ta.getColor(R.styleable.TopBar_rightColor, 0);
rightBackGround = ta.getDrawable(R.styleable.TopBar_rightBackGround);
rightText = ta.getString(R.styleable.TopBar_rightText);
title = ta.getString(R.styleable.TopBar_title);
// titleTextSize = ta.getDimensionPixelSize(R.styleable.TopBar_titleTextSize, (int) TypedValue.applyDimension(
// TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
titleTextSize = ta.getDimension(R.styleable.TopBar_titleTextSize, 0);
titleTextColor = ta.getColor(R.styleable.TopBar_titleTextColor, 0);
ta.recycle();
leftButton = new Button(context);
leftButton.setText(leftText);
leftButton.setBackground(leftBackGround);
leftButton.setTextColor(leftColor);
RelativeLayout.LayoutParams leftparams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
leftparams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
addView(leftButton, leftparams);
rightButton = new Button(context);
rightButton.setText(rightText);
rightButton.setBackground(rightBackGround);
rightButton.setTextColor(rightColor);
RelativeLayout.LayoutParams rightparams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
rightparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(rightButton, rightparams);
tvTitle = new TextView(context);
tvTitle.setText(title);
tvTitle.setTextSize(titleTextSize);
tvTitle.setTextColor(titleTextColor);
RelativeLayout.LayoutParams titleparams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
titleparams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
titleparams.addRule(Gravity.CENTER);
addView(tvTitle, titleparams);
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftButtonClickListener();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightButtonClickListener();
}
});
}
public void setTopBarViewClickListener(TopBarViewClickListener listener){
this.listener = listener;
}
}
这个代码还可以继续延伸,我这个人比较懒,知道了这个思路就没有动了,大家可以自行脑补,最后写出xml布局的引用代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.weixing.topbarlibrary"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.weixing.topbarlibrary.MainActivity"
android:orientation="vertical">
<com.weixing.topbarlibrary.TopBarView
android:id="@+id/TopBarView"
android:layout_width="match_parent"
android:layout_height="40dp"
custom:title="我的高德地图"
custom:titleTextSize="10sp"
custom:titleTextColor="#ffffff"
custom:leftColor="#ffffff"
custom:leftBackGround="#3579bd"
custom:leftText="搜索位置"
custom:rightColor="#ffffff"
custom:rightBackGround="#3579bd"
custom:rightText="加载地图"/>
</LinearLayout>
如果实在不能理解的话可以花半个来小时进行系统的了解:
http://www.imooc.com/learn/247
续:
昨天讲的是高德地图组件API,今天继续讲第二节Android APP实现高德地图组件的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.weixing.topbarlibrary"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.weixing.topbarlibrary.MainActivity"
android:orientation="vertical">
<com.weixing.topbarlibrary.TopBarView
android:id="@+id/TopBarView"
android:layout_width="match_parent"
android:layout_height="40dp"
custom:title="我的高德地图"
custom:titleTextSize="10sp"
custom:titleTextColor="#ffffff"
custom:leftColor="#ffffff"
custom:leftBackGround="#3579bd"
custom:leftText="搜索位置"
custom:rightColor="#ffffff"
custom:rightBackGround="#3579bd"
custom:rightText="加载地图"/>
<WebView
android:id="@+id/wenbiew"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
上面对于布局就不再讲了,接着我们看看第三节webview实现加载URL的java代码以及实现思路,
package com.weixing.topbarlibrary;
import com.weixing.topbarlibrary.TopBarView.TopBarViewClickListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity{
private static WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TopBarView topbar = (TopBarView) findViewById(R.id.TopBarView);
webView = (WebView) findViewById(R.id.wenbiew);
WebSettings webseting = webView.getSettings();
topbar.setTopBarViewClickListener(new TopBarViewClickListener() {
@Override
public void rightButtonClickListener() {
String url = "http://m.amap.com/navi/?start=116.403124,39.940693&dest=116.481488,39.990464&destName=阜通西&naviBy=car&key=035a7298cddc6488961e9cba167c71c3";
webView.loadUrl(url);
}
@Override
public void leftButtonClickListener() {
}
});
}
}
代码的思路非常简单,就是在onCreate()方法中给webview和TopBarView初始化,然后给TopBarView的左右按钮注册监听事件,并让其在点击右键时加载我们的URL,运行效果如图:
但是这里是直接跳到浏览器里面去了,并没有在webview里实现加载我们的目标URL,这里加两句代码就行了,如下:
@Override
public void rightButtonClickListener() {
WebSettings webseting = webView.getSettings();
//非常重要,支持JavaScript
webseting.setJavaScriptEnabled(true);
String url = "http://m.amap.com/navi/?start=116.403124,39.940693&dest=116.481488,39.990464&destName=阜通西&naviBy=car&key=035a7298cddc6488961e9cba167c71c3";
webView.loadUrl(url);在
//设置在webview里加载,不跳转到浏览器
webView.setWebViewClient(new WebViewClient());
}
再次运行,效果如下图:
OK,现在我们对于地图组件在Android APP上面能应用了,但是问题又来了,如何实现实现和客户的交互呢?比如客户要做位置标注,给你一个地址,你应该怎么做呢?想一想?
这里我直接说了,Android里实现交互很容易,增加一个EditText控件用户就可以输入目标位置,但是这个位置的经纬度怎么获取呢?高德官网有一个网页叫“高德坐标拾取工具”(上面讲了,我们不用SDK,而且GPS获取的经纬度也是谷歌提供的,不是高德的国标,所以这里直接忽略了),我们怎么拾取这个坐标呢?或许我们可以将高德官网的这个坐标拾取工具扒出来,然后扒出JavaScript并做修改,这里不用了,因为网上已经有实现的这种类似高德坐标拾取工具的网页,代码如下(源码出处)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>高德坐标拾取工具</title>
<link rel="stylesheet" type="text/css"
href="css/demo.Default.css" />
<script type="text/javascript"
src="http://webapi.amap.com/maps?v=1.3&key=035a7298cddc6488961e9cba167c71c3"></script>
<script language="javascript">
var mapObj;
var marker = new Array();
var windowsArr = new Array();
//基本地图加载
function mapInit() {
// mapObj = new AMap.Map("iCenter");
mapObj = new AMap.Map("iCenter",{
view: new AMap.View2D({//创建地图二维视口
center: new AMap.LngLat(116.397428,39.90923),
zoom:14,
rotation:0
}),
lang:"zh_cn"//设置地图语言类型,默认:中文简体
});
var edit = document.getElementById("edit")
//AMap.event.addListener(mapObj,'click',getLnglat);
}
function placeSearch() {
var MSearch;
mapObj.plugin(["AMap.PlaceSearch"], function() {
MSearch = new AMap.PlaceSearch({ //构造地点查询类
pageSize:10,
pageIndex:1,
city:"021" //城市
});
AMap.event.addListener(MSearch, "complete", keywordSearch_CallBack);//返回地点查询结果
var searchName = document.all.searchText.value;//查询关键字
MSearch.search(searchName); //关键字查询
});
}
//添加marker&infowindow
function addmarker(i, d) {
var lngX = d.location.getLng();
var latY = d.location.getLat();
var markerOption = {
map:mapObj,
icon:"http://webapi.amap.com/images/" + (i + 1) + ".png",
position:new AMap.LngLat(lngX, latY)
};
var mar = new AMap.Marker(markerOption);
marker.push(new AMap.LngLat(lngX, latY));
var infoWindow = new AMap.InfoWindow({
content:"<h3><font color=\"#00a6ac\"> " + (i + 1) + ". " + d.name + "</font></h3>" + TipContents(d.type, d.address, d.tel),
size:new AMap.Size(300, 0),
autoMove:true,
offset:new AMap.Pixel(0,-30)
});
windowsArr.push(infoWindow);
var aa = function (e) {infoWindow.open(mapObj, mar.getPosition());};
AMap.event.addListener(mar, "click", aa);
AMap.event.addListener(mar,'click',getLnglat);
}
//回调函数
function keywordSearch_CallBack(data) {
var resultStr = "";
var poiArr = data.poiList.pois;
var resultCount = poiArr.length;
for (var i = 0; i < resultCount; i++) {
resultStr += "<div id='divid" + (i + 1) + "' onclick='openMarkerTipById1(" + i + ",this)' onmouseout='onmouseout_MarkerStyle(" + (i + 1) + ",this)' style=\"font-size: 12px;cursor:pointer;padding:0px 0 4px 2px; border-bottom:1px solid #C1FFC1;\"><table><tr><td><img src=\"http://webapi.amap.com/images/" + (i + 1) + ".png\"></td>" + "<td><h3><font color=\"#00a6ac\">名称: " + poiArr[i].name + "</font></h3>";
resultStr += TipContents(poiArr[i].type, poiArr[i].address, poiArr[i].tel) + "</td></tr></table></div>";
addmarker(i, poiArr[i]);
}
mapObj.setFitView();
document.getElementById("result").innerHTML = resultStr;
openMarkerTipById1(0,document.getElementById("divid1"));
}
function TipContents(type, address, tel) { //窗体内容
if (type == "" || type == "undefined" || type == null || type == " undefined" || typeof type == "undefined") {
type = "暂无";
}
if (address == "" || address == "undefined" || address == null || address == " undefined" || typeof address == "undefined") {
address = "暂无";
}
if (tel == "" || tel == "undefined" || tel == null || tel == " undefined" || typeof address == "tel") {
tel = "暂无";
}
var str = " 地址:" + address + "<br /> 电话:" + tel + " <br /> 类型:" + type;
return str;
}
function openMarkerTipById1(pointid, thiss) { //根据id 打开搜索结果点tip
thiss.style.background = '#CAE1FF';
windowsArr[pointid].open(mapObj, marker[pointid]);
//result中每个div触发的事件
document.getElementById("lngX").value = marker[pointid].getLng();
document.getElementById("latY").value = marker[pointid].getLat();
}
function onmouseout_MarkerStyle(pointid, thiss) { //鼠标移开后点样式恢复
thiss.style.background = "";
}
//鼠标在地图上点击,获取经纬度坐标
function getLnglat(e) {
document.getElementById("lngX").value = e.lnglat.getLng();
document.getElementById("latY").value = e.lnglat.getLat();
}
//关闭页面
function CloseWind(){
var lat = document.getElementById("lngX").value;
var lon = document.getElementById("latY").value;
opener.setValue(lat+","+lon);
window.close();
}
</script>
<style type="text/css">
<!--
table{height:100%}
html,body{height:100%;margin:0px;padding:0px}
.STYLE1 {color: #F3F3F3}
-->
</style>
</head>
<body onLoad="mapInit()">
<table width="100%" border="0" cellspacing="0" cellpadding="0" >
<tr>
<td colspan="2" height="50"><br>
高德地图:<input type="text" name="searchText" id="edit">
<input type="button" value="查询" onClick="placeSearch()" href=\"javascript:myjavascript.call('"+jsonObj.phone + "')\> 输入位置信息
<br><br>地图经纬度坐标: X:<input type="text" id="lngX" name="lngX"/> Y:<input type="text" id="latY" name="latY"/>
<input type="button" name="btn_Close" id="btn_Close" value="确定,并关闭页面" onClick="CloseWind();" /> *选择正确地点之后,请点击该按钮
</td>
</tr>
<tr>
<td width="70%" height="500"> <div style="height:100%" id="iCenter"></div></td>
<td valign="top" ><div class="demo_box">
<div id="r_title" ><b>关键字查询结果:</b></div>
<div id="result" > </div>
</div>
<span class="STYLE1"></span></td>
</tr>
</table>
</body>
</html>
运行效果如图:
这里还是讲一下具体的实现逻辑,首先html如同java的main()方法一样,他首先需要执行onLoad方法,文中代码onLoad=”mapInit()”,意思是将mapInit()定义为onLoad方法,这个方法里做了唯一的一件事,就是将地图实例化。
然后我们在点击查询按钮后执行了placeSearch()方法,文中代码onClick=”placeSearch()” 这个方法里重点执行三件事:1是构造地点查询类,2是将地点查询结果加一个接口,三是将我们输入的“天府广场”作为关键字交给地点查询类来查询,然后查询的结果我们到回调函数来看看。
keywordSearch_CallBack(data),这里重点是两件事var resultCount = poiArr.length;
for (var i = 0; i < resultCount; i++) {
resultStr += "<div id='divid" + (i + 1) + "' onclick='openMarkerTipById1(" + i + ",this)' onmouseout='onmouseout_MarkerStyle(" + (i + 1) + ",this)' style=\"font-size: 12px;cursor:pointer;padding:0px 0 4px 2px; border-bottom:1px solid #C1FFC1;\"><table><tr><td><img src=\"http://webapi.amap.com/images/" + (i + 1) + ".png\"></td>" + "<td><h3><font color=\"#00a6ac\">名称: " + poiArr[i].name + "</font></h3>";
resultStr += TipContents(poiArr[i].type, poiArr[i].address, poiArr[i].tel) + "</td></tr></table></div>";
addmarker(i, poiArr[i]);
}
第一步是如上文将得到的查询结果转换成html格式的内容,然后第二步由这句代码document.getElementById(“result”).innerHTML = resultStr;将原来的内容替换了,这里我们就看到了返回的文本列表了
接下来我们就来讲一讲最为困难,最为复杂的第五节,这里有两个难题:
一、我们如何将自己的目标地点传递给html网页?
二、html网页里得到了经纬度,怎么传递给Android?
这里我需要先把Android的布局做一个修改,让客户输入目的地,代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.weixing.topbarlibrary"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.weixing.topbarlibrary.MainActivity"
android:orientation="vertical">
<!-- 标题栏 -->
<com.weixing.topbarlibrary.TopBarView
android:id="@+id/TopBarView"
android:layout_width="match_parent"
android:layout_height="40dp"
custom:title="我的高德地图"
custom:titleTextSize="10sp"
custom:titleTextColor="#ffffff"
custom:leftColor="#ffffff"
custom:leftBackGround="#3579bd"
custom:leftText="搜索位置"
custom:rightColor="#ffffff"
custom:rightBackGround="#3579bd"
custom:rightText="加载地图"/>
<!-- 客户输入控件,布局是隐藏的,点击搜索位置时打开, -->
<LinearLayout
android:id="@+id/SearchPoint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#135791"
android:orientation="horizontal"
android:visibility="gone">
<!-- 输入控件 -->
<EditText
android:id="@+id/SearchEdit"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="3"
android:hint="如(沈阳故宫)"
/>
<!-- 确认输入的控件 确认输入将父类LinerLayout关闭-->
<Button
android:id="@+id/SearchSure"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="搜索"/>
</LinearLayout>
<!-- 加载位置标注、路线规划等URL的webview -->
<WebView
android:id="@+id/wenbiew"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<!-- 加载坐标拾取工具URL的webview 可以用上面的webview,
但是为了不让客户看见我们拾取坐标的过程,所以单独增加一个webview隐藏进行 -->
<WebView
android:id="@+id/WebViewPoint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
</LinearLayout>
接下来我们需要实现的是让html加载的时候把我们的目的地文本传给它,它直接进行搜索,这里我们将加载这个html的webview多写一行代码:
webviewPoint.addJavascriptInterface(new MyJavaScript(this, handler), “myjavascript”);
这里有两个参数,一个是构造了一个MyJavaScript类,这个类是负责与JavaScript交互的,然后我们命名了一个”myjavascript”,这个名称是JavaScript调Android的用的名称,后文会用到,这里我们看看这个MyJavaScript类的java代码:
package com.weixing.topbarlibrary;
import java.util.MissingFormatArgumentException;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
public class MyJavaScript {
private WebView webview;
//使用一个handler来处理加载事件
private Handler handler;
private String PlaceName;
public MyJavaScript(Context context,Handler handler){
this.handler = handler;
webview = (WebView) ((Activity)context).findViewById(R.id.WebViewPoint);
}
/*
* java调用显示网页,异步
* 传递目标点 PlaceName
*/
@JavascriptInterface
public void show(){
handler.post(new Runnable() {
public void run() {
//重要:url的生成,传递数据给网页
PlaceName = MainActivity.str;
String url = "javascript:mapInit('" + PlaceName + "')";
webview.loadUrl(url);
Log.e("hhqy", "javascript:mapInit('" + PlaceName + "')");
}
});
}
/**
* JS调用Android,传回坐标点
* @param point
*/
@JavascriptInterface
public void call(final String point){
handler.post(new Runnable() {
public void run() {
MainActivity.StartSearch(point);
Log.e("hhqy", point);
}
});
}
}
Android段准备好了之后我们就去JavaScript里修改,让他实现Android与JavaScript的交互,首先思路是这样:
1、加载html,然后调用Android的方法,实现目的地的传递;
2、地图实例化,开始搜索目的地;
3、将目的地搜索结果第一条的数据传递给Android,
4、Android按照高德地图组件的要求拼写URL,再次加载,实现整个webview的自定义位置标注
首先来讲加载html,非常简单,一句代码:
webviewPoint.loadUrl(“file:///android_asset/index.html”);然后html执行的方法不是自身的,这里需要调Android提供的目的地,于是它的onLoad方法需要做一个更改: onLoad=”javascript:myjavascript.show()”意思就是JavaScript执行myjavascript.show()方法,
/*
* java调用显示网页,异步
* 传递目标点 PlaceName
*/
@JavascriptInterface
public void show(){
handler.post(new Runnable() {
public void run() {
//重要:url的生成,传递数据给网页
PlaceName = MainActivity.str;
String url = "javascript:mapInit('" + PlaceName + "')";
webview.loadUrl(url);
Log.e("hhqy", "javascript:mapInit('" + PlaceName + "')");
}
});
}
这个方法里将目的地作为参数传递给javascript:mapInit(),看清楚这里是用主线程传过来的handler来加载的,如果不用handler根本就加载不起来,会报一个异常,如图:真机日志较多,不确定这个异常,大神希望可以从源码角度来分享一下为什么只有主线程才能加载这个webview
然后我们接下来看看mapInit()里得到这个参数怎么做呢?增加三行代码:var edit = document.getElementById(“edit”)
edit.value = PlaceName;
placeSearch();
我们将传过来的参数给那个输入框赋值,然后直接调用搜索按钮的方法,就完成了第二步,接下来我们继续实施第三步。
在html访问网络拿到数据进行处理时,我们给他调一个监听事件,因为返回结果的列表需要我们点击他才会把相应结果经纬度呈现在X、Y后面的输入框,openMarkerTipById1(0,document.getElementById(“divid1”));这里我们返回的是列表的第一个数据,既然调了这个事件,那么我们到这个事件里面去观察一下它在做什么?这里做了三件事:把选择项的背景色做了更改;将目标地点做了一个标记,然后将经纬度的值分别赋给对应的控件(或许控件这个称呼不专业,但是用Android习惯了,大家也可以更好的理解),然后我们给它增加一个方法:myjavascript.call(‘”+marker[pointid].getLng()+”,”+marker[pointid].getLat() + “’);
这里的myjavascript是我们之前的命名,后面的call方法就是将目标地的经度+”,”+维度作为一个参数传给了Android,完成了第三步,最后我们来看看第四步是怎么实现的?
/**
* JS调用Android,传回坐标点
* @param point
*/
@JavascriptInterface
public void call(final String point){
handler.post(new Runnable() {
public void run() {
MainActivity.StartSearch(point);
Log.e("hhqy", point);
}
});
}
我们把这个参数在主线程传给了里的一个方法,这个方法又做了什么啊?
public static void StartSearch(String PlacePoint){
// webView.setVisibility(View.VISIBLE);
// webviewPoint.setVisibility(View.GONE);
String url = "http://m.amap.com/around/?locations="+PlacePoint+"&keywords=美食,KTV,地铁站,公交站&defaultIndex=3&defaultView=&searchRadius=5000&key=035a7298cddc6488961e9cba167c71c3";
// String url = "http://m.amap.com/around/?locations=121.429489,31.153304&keywords=美食,KTV,地铁站,公交站&defaultIndex=3&defaultView=&searchRadius=5000&key=035a7298cddc6488961e9cba167c71c3";
webView.loadUrl(url);
webView.setWebViewClient(new WebViewClient());
}
OK,大功告成了,不过网上也有很多关于Android与JavaScript的交互,大部分是JavaScript传数据给Android基本上都是通过超链接,或者Android直接获取某个内容控件的具体文本,但是我们这里不触摸html网页(其实它一直是隐藏的)也没有用死循环一直等得到赋值了再拿回来,因为就我要的效果来看,它目前是最佳的!
大家可以继续扩展,比如用TabHost绑定四个Activity实现地图组件的四个用法,然后如法炮制的将关键字等元素添加进来,这里只是抛砖引玉,大家可以做几个尝试!
最后请各位大神多多点评,如有缪处,请与斧正,谢谢!
源码点击这里
最后,经过对地图组件API的深入研究,发现”bug”:
地图组件的位置标注功能生成的URL在webview加载显示不完整,返回结果是key值不合法,但是用浏览器加载没有任何问题该问题预计5月24日解决,详情见博客高德地图组件在Android的应用以及Android与JavaScript的交互(二),敬请斧正!