高德地图组件在Android的应用以及Android与JavaScript的交互(一)

2023-11-02

最近在慕课网学习了关于高德地图组件的课程(其实就是一个广告,内容和官网的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的交互(二),敬请斧正!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高德地图组件在Android的应用以及Android与JavaScript的交互(一) 的相关文章

随机推荐

  • AJAX & Axios 总结

    AJAX Axios 1 AJAX 1 1 作用 与服务器进行数据交换 异步交互 异步和同步 1 2 基本使用 1 3 案例 SelectUserServlet register html register html中的
  • 层层逼近,了解Norm系需要解决的问题及其衍生变体

    引自 https zhuanlan zhihu com p 33173246 https blog csdn net xiao lxl article details 72730000 https github com switchable
  • linux audit日志通过syslog转发到远端

    流程 开启audit 配置rsyslog读audit log文件 转发到远端 1 开启audit 重启audit service auditd restart 确认audit log产生日志 cat var log audit audit
  • filebeat-sidecar模式采集pod应用日志

    文章目录 1 将镜像上传服务器 2 新增sidecar yml文件 3 kubectl部署应用 部署应用 查看应用部署情况 查看pod运行情况 查看容器 应用服务 运行情况 查看容器 filebeat 运行情况 查看pod日志 4 kafk
  • Linux内核设计与实现(五)

    文章目录 什么是内核同步 1 临界区和竞争条件 2 加锁 2 1 造成并发执行的原因 2 2 了解需要保护什么 3 死锁 4 争用和扩展性 内核同步方法 1 原子操作 1 1 原子整数操作 1 2 原子位操作 2 自旋锁 2 1 自旋锁方法
  • 时序预测

    时序预测 MATLAB实现基于TSO XGBoost金枪鱼算法优化XGBoost的时间序列预测 多指标评价 目录 时序预测 MATLAB实现基于TSO XGBoost金枪鱼算法优化XGBoost的时间序列预测 多指标评价 预测效果 基本介绍
  • java+selenium环境搭建

    目录 1 写在前面的话 2 下载谷歌驱动 3 添加Selenium依赖 我这里添加的是4 0 0版本的 4 在操作过程中可能出现的问题 解决办法 目录 1 写在前面的话 2 下载谷歌驱动 3 添加Selenium依赖 我这里添加的是4 0
  • MTK 平台Camera 驱动架构

    记录下 Mtk的Hal3架构笔记 正在进行学习 后续仍会更新 一 MtkCam3的代码结构及学习资料 mtk online里搜Camera 可以搜到很全面的Mtk Hal3的学习文档 Mtk整理的文档很棒 简单到位 https online
  • 嵌入式(线程的取消和互斥)

    线程的取消 意义 随时杀掉一个线程 int pthread cancel pthread t thread 注意 线程的取消要有取消点才可以 不是说取消就取消 线程的取消点主要是阻塞的系统调用 运行段错误调试 可以使用gdb调试 使用gdb
  • Linux之进程组、守护进程

    转自 https blog csdn net happiness llz article details 82749105 进程组 概念和特性 进程组 也称之为作业 BSD于1980年前后向Unix中增加的一个新特性 代表一个或多个进程的集
  • 序列密码,最安全的密码体制

    序列密码体制是理论上最安全的密码体制 因为Shannon证明了一次一密密码体制是绝对安全的 每个字节明文都对应这一个字节的密钥 而序列密码的设计就是基于此而设计 序列密码 明 文 密 文 密
  • Mysql可变长度列VARCHAR、BLOB和TEXT问题

    在对这些可变长度类型的列进行大量的增删后可能会出现碎片 建议定期执行 OPTIMIZE TABLE 表名 以优化性能 但以上命令只对MyISAM BDB和InnoDB存储引擎的表生效 以下方式也可以优化innodb存储引擎的表中的碎片 al
  • oc swift 混编

    oc 和 swift 互调 swift 中使用 oc swift 中调用 oc 的类 创建一个oc的项目 在项目里创建swift文件的话 Xcode会自动提示 要不要创建桥接文件 如下图所示 选择Create Bridging Header
  • Python大数据-对淘宝用户的行为数据分析

    目录 一 项目背景 二 项目目标 三 分析思路 四 数据清洗 1 读取查看数据的基本信息和数据的完整性 2 一致化处理 3 查看是否有缺失值 五 数据分析 1 不同时间下PV UV的流量变化情况 2 不同购物行为在不同时间维度下的变化情况
  • 可惜了,昔日硬核神器已停止服务……幸亏还有这款开源工具撑着

    大家好 我是小莫理 不知道有多少朋友还记得一个叫Magi的搜索引擎 它比传统的搜索引擎更智能 但是很遗憾 服务已经暂停了 无论是比较知名的F搜 密搜还是多吉搜 服务模式都因为各种原因发生了变化 第三方的搜索引擎似乎是被某种神秘力量所牵绊着
  • 统计学习方法学习1.0

    决策树 决策树是一种分类和回归方法 优点 模型可读性 分类速度快 过程 特征选择 决策树的生成 决策树的剪枝 损失函数 正则化的极大似然函数 特征选择 多个特征时 如何选择某个特征作为判断的依据 信息增益 熵定义 熵越大 随机变量的不确定性
  • Java中calendar类常用方法介绍 (获取年月日星期)

    概述 Calendar 类是一个抽象类 它为特定瞬间与一组诸如 YEAR MONTH DAY OF MONTH HOUR 等日历字段之间的转换提供了一些方法 并为操作日历字段 例如获得下星期的日期 提供了一些方法 构造 父类引用指向子类对象
  • BDS - Chapter - 3 - Remedial Unix Shell

    This book assumes you re familiar with basic topics such as what a terminal is what the shell is the Unix filesystem hie
  • 自动化测试很容易学,是你的方法用错了

    目录 一 初识自动化测试 二 自动化测试和手工测试有什么不同 三 什么是自动化测试 四 自动化测试和手工测试应用范围的对比 五 区别对待不同的测试阶段 六 如何评估测试工具 七 如何选择合适的测试工具 八 如何学习自动化测试 一 初识自动化
  • 高德地图组件在Android的应用以及Android与JavaScript的交互(一)

    最近在慕课网学习了关于高德地图组件的课程 其实就是一个广告 内容和官网的API完全一样 发现这个JavaScript API比Android API简单方便多了 于是就打算放在Android APP上来实现 花了一点小功夫 但是最终还是实现