微信开发联合百度地图_微信公众号开发微信调取地图和手机地图 - CSDN
  • 本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与在线...

    本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与在线导航。

    官方文档地址:https://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

    在这粘贴上二篇博文链接,方便大家访问:

    微信公众号开发《一》OAuth2.0网页授权认证获取用户的详细信息,实现自动登陆

    微信公众号开发《二》发送模板消息实现消息业务实时通知

    1.何为JS-SDK:微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。简单来说:就是在自己公众平台后台配置后,可直接调用的功能接口。

    那如何配置呢?下面讲解下配置步骤:示例讲解是基于测试公众号,如何使用测试公众号,可以参考第一篇文章

     

    1.在公众号后台绑定域名:测试公众号登录就可看见如下图。正式公众号配置位置:“公众号设置”的“功能设置”里填写“JS接口安全域名”

    2.页面中引入接口JS文件,下载地址:http://res.wx.qq.com/open/js/jweixin-1.2.0.js

    注意:JS最新版本为1.2.0,为了适配IOS开发,最好使用最新版本号JS,1.1.0版本可能会造成有些功能调用失败,有兴趣的可以看看官方文档:https://mp.weixin.qq.com/advanced/wiki?t=t=resource/res_main&id=mp1483682025_enmey

    3.获取必须参数:

     

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名
        jsApiList: [
    		'openLocation',
    		'getLocation'
    	] // 必填,需要使用的JS接口列表,更多接口可看官方文档
    });

    看调用接口,可知,现在缺timestamp,signature,nonceStr。不用想的太复杂,还是那个原则,没什么获取什么,

    获取signature签名,生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket。

    写个工具类封装获取方法

     

    public class SHA1 { //sha算法
        private final int[] abcde = { 
                0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 
            }; 
        // 摘要数据存储数组 
        private int[] digestInt = new int[5]; 
        // 计算过程中的临时数据存储数组 
        private int[] tmpData = new int[80]; 
        // 计算sha-1摘要 
        private int process_input_bytes(byte[] bytedata) { 
            // 初试化常量 
            System.arraycopy(abcde, 0, digestInt, 0, abcde.length); 
            // 格式化输入字节数组,补10及长度数据 
            byte[] newbyte = byteArrayFormatData(bytedata); 
            // 获取数据摘要计算的数据单元个数 
            int MCount = newbyte.length / 64; 
            // 循环对每个数据单元进行摘要计算 
            for (int pos = 0; pos < MCount; pos++) { 
                // 将每个单元的数据转换成16个整型数据,并保存到tmpData的前16个数组元素中 
                for (int j = 0; j < 16; j++) { 
                    tmpData[j] = byteArrayToInt(newbyte, (pos * 64) + (j * 4)); 
                } 
                // 摘要计算函数 
                encrypt(); 
            } 
            return 20; 
        } 
        // 格式化输入字节数组格式 
        private byte[] byteArrayFormatData(byte[] bytedata) { 
            // 补0数量 
            int zeros = 0; 
            // 补位后总位数 
            int size = 0; 
            // 原始数据长度 
            int n = bytedata.length; 
            // 模64后的剩余位数 
            int m = n % 64; 
            // 计算添加0的个数以及添加10后的总长度 
            if (m < 56) { 
                zeros = 55 - m; 
                size = n - m + 64; 
            } else if (m == 56) { 
                zeros = 63; 
                size = n + 8 + 64; 
            } else { 
                zeros = 63 - m + 56; 
                size = (n + 64) - m + 64; 
            } 
            // 补位后生成的新数组内容 
            byte[] newbyte = new byte[size]; 
            // 复制数组的前面部分 
            System.arraycopy(bytedata, 0, newbyte, 0, n); 
            // 获得数组Append数据元素的位置 
            int l = n; 
            // 补1操作 
            newbyte[l++] = (byte) 0x80; 
            // 补0操作 
            for (int i = 0; i < zeros; i++) { 
                newbyte[l++] = (byte) 0x00; 
            } 
            // 计算数据长度,补数据长度位共8字节,长整型 
            long N = (long) n * 8; 
            byte h8 = (byte) (N & 0xFF); 
            byte h7 = (byte) ((N >> 8) & 0xFF); 
            byte h6 = (byte) ((N >> 16) & 0xFF); 
            byte h5 = (byte) ((N >> 24) & 0xFF); 
            byte h4 = (byte) ((N >> 32) & 0xFF); 
            byte h3 = (byte) ((N >> 40) & 0xFF); 
            byte h2 = (byte) ((N >> 48) & 0xFF); 
            byte h1 = (byte) (N >> 56); 
            newbyte[l++] = h1; 
            newbyte[l++] = h2; 
            newbyte[l++] = h3; 
            newbyte[l++] = h4; 
            newbyte[l++] = h5; 
            newbyte[l++] = h6; 
            newbyte[l++] = h7; 
            newbyte[l++] = h8; 
            return newbyte; 
        } 
        private int f1(int x, int y, int z) { 
            return (x & y) | (~x & z); 
        } 
        private int f2(int x, int y, int z) { 
            return x ^ y ^ z; 
        } 
        private int f3(int x, int y, int z) { 
            return (x & y) | (x & z) | (y & z); 
        } 
        private int f4(int x, int y) { 
            return (x << y) | x >>> (32 - y); 
        } 
        // 单元摘要计算函数 
        private void encrypt() { 
            for (int i = 16; i <= 79; i++) { 
                tmpData[i] = f4(tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14] ^ 
                        tmpData[i - 16], 1); 
            } 
            int[] tmpabcde = new int[5]; 
            for (int i1 = 0; i1 < tmpabcde.length; i1++) { 
                tmpabcde[i1] = digestInt[i1]; 
            } 
            for (int j = 0; j <= 19; j++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[j] + 0x5a827999; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int k = 20; k <= 39; k++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[k] + 0x6ed9eba1; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int l = 40; l <= 59; l++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[l] + 0x8f1bbcdc; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int m = 60; m <= 79; m++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[m] + 0xca62c1d6; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int i2 = 0; i2 < tmpabcde.length; i2++) { 
                digestInt[i2] = digestInt[i2] + tmpabcde[i2]; 
            } 
            for (int n = 0; n < tmpData.length; n++) { 
                tmpData[n] = 0; 
            } 
        } 
        // 4字节数组转换为整数 
        private int byteArrayToInt(byte[] bytedata, int i) { 
            return ((bytedata[i] & 0xff) << 24) | ((bytedata[i + 1] & 0xff) << 16) | 
            ((bytedata[i + 2] & 0xff) << 8) | (bytedata[i + 3] & 0xff); 
        } 
        // 整数转换为4字节数组 
        private void intToByteArray(int intValue, byte[] byteData, int i) { 
            byteData[i] = (byte) (intValue >>> 24); 
            byteData[i + 1] = (byte) (intValue >>> 16); 
            byteData[i + 2] = (byte) (intValue >>> 8); 
            byteData[i + 3] = (byte) intValue; 
        } 
        // 将字节转换为十六进制字符串 
        private static String byteToHexString(byte ib) { 
            char[] Digit = { 
                    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 
                    'D', 'E', 'F' 
                }; 
            char[] ob = new char[2]; 
            ob[0] = Digit[(ib >>> 4) & 0X0F]; 
            ob[1] = Digit[ib & 0X0F]; 
            String s = new String(ob); 
            return s; 
        } 
        // 将字节数组转换为十六进制字符串 
        private static String byteArrayToHexString(byte[] bytearray) { 
            String strDigest = ""; 
            for (int i = 0; i < bytearray.length; i++) { 
                strDigest += byteToHexString(bytearray[i]); 
            } 
            return strDigest; 
        } 
        // 计算sha-1摘要,返回相应的字节数组 
        public byte[] getDigestOfBytes(byte[] byteData) { 
            process_input_bytes(byteData); 
            byte[] digest = new byte[20]; 
            for (int i = 0; i < digestInt.length; i++) { 
                intToByteArray(digestInt[i], digest, i * 4); 
            } 
            return digest; 
        } 
        // 计算sha-1摘要,返回相应的十六进制字符串 
        public String getDigestOfString(byte[] byteData) { 
            return byteArrayToHexString(getDigestOfBytes(byteData)); 
        } 
        public static void main(String[] args) { 
            String data = "123456"; 
            System.out.println(data); 
            String digest = new SHA1().getDigestOfString(data.getBytes()); 
            System.out.println(digest);
           
           // System.out.println( ToMD5.convertSHA1(data).toUpperCase());
        } 
    } 

     通过quartz定时获取AccessToken,AccessToken 2小时内有效,所以2小时内需要更新一次,具体官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

    /**
     * 通过quartz定时获取AccessToken,AccessToken 2小时失效,所以2小时内需要更新一次
     */
    
    public class TimedTask extends QuartzJobBean{
    	private static Logger log = LoggerFactory.getLogger(TimedTask.class);
    	public static String appid = "";//测试微信公众号的openid,切换到正式版时需更新成正式版微信公众号appid
    	public static String appsecret = "";//测试微信公众号的appsecret,切换到正式版时需更新成正式版微信公众号appid
    	public static String MCH_ID = "";//商户ID
    	public static String KEY = "";//key
    	public static String notify_url = "";//支付通知回掉接口
    	public static AccessToken accessToken = null;
    	public static Ticket ticket = null;
    	public static HashMap<String,Weather> weatherMap = new HashMap<String, Weather>();
    	public static HashMap<String,Weather> weatherListMap = new HashMap<String, Weather>();
    	public static double deliveryDistance = 5000;
    	
    
    	public static String websiteAndProject = "http://192.168.1.117/test";
    	
    	@Override
    	protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
    		accessToken = WeixinUtil.getAccessToken(appid, appsecret);
    		ticket = WeixinUtil.getTicket(accessToken.getToken());
    		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		log.info("获取token:"+format.format(new Date())+"=="+accessToken.getToken());
    		log.info("获取ticket:"+format.format(new Date())+"=="+ticket.getTicket());
    	}
    }
    
    
    public class AccessToken {
    	// 获取到的凭证
    	private String token;
    	// 凭证有效时间,单位:秒
    	private int expiresIn;
    
    	public String getToken() {
    		return token;
    	}
    
    	public void setToken(String token) {
    		this.token = token;
    	}
    
    	public int getExpiresIn() {
    		return expiresIn;
    	}
    
    	public void setExpiresIn(int expiresIn) {
    		this.expiresIn = expiresIn;
    	}
    }
    
    
    /**
     * Ticket封装类
     * @author lh
     */
    public class Ticket {
    	private String errcode;
    	private String errmsg;
    	private String ticket;
    	private String expires_in;
    	//省略get,set方法
    }
    /**
     * Signature封装类
     * @author lh
     */
    public class SignatureInfo {
    	private String signature;
    	private String timestamp;
    	private String noncestr;
    	private String url;
    	//省略get,set方法
    }

    获取ticket

    /**
     * 获取ticket
     * @param accessToken
     * @return
     */
    public static Ticket getTicket(String accessToken){
    	Ticket ticket = new Ticket();
    	String getTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
    	String url = getTicket.replace("ACCESS_TOKEN",accessToken);
    	JSONObject jsonObject = httpRequest(url, "POST", null);
    	if (null != jsonObject) {
    		if (0 != jsonObject.getInt("errcode")) {
    			log.error("获取ticket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
    		}else{
    			ticket.setErrcode(jsonObject.getString("errcode"));
    			ticket.setErrmsg(jsonObject.getString("errmsg"));
    			ticket.setExpires_in(jsonObject.getString("expires_in"));
    			ticket.setTicket(jsonObject.getString("ticket"));
    		}
    	}
    	return ticket;
    }

    获取Signature方法

    /**
     * 签名算法
     * @param ticket
     * @return
     */
    public static SignatureInfo getSignature(SignatureInfo sign,Ticket ticket){
    	String data = "jsapi_ticket="+ticket.getTicket()+"&noncestr="+sign.getNoncestr()+"×tamp="+sign.getTimestamp()+"&url="+sign.getUrl();
    	String signature =  new SHA1().getDigestOfString(data.getBytes()); 
    	sign.setSignature(signature);
    	log.info("signature="+sign.getSignature());
    	return sign;
    }

    最后综合上面方法,封装主函数

    public String jssdk_demo(HttpServletRequest request,HttpServletResponse response){
    	String param = request.getQueryString();//获取请求参数
    	String url = request.getServletPath();//获取请求路径(不带参数)
    	if(param!=null){
    		url = url+"?"+param;//组合成完整请求URL
    	}
    	String projectnameP = request.getContextPath();
        String projectName = projectnameP.substring(projectnameP.lastIndexOf('/')+1,projectnameP.length());  //获取工程名,如testW
    	if(!"".equals(projectName)){
    		projectName ="/"+projectName;
    	}
    	String port = String.valueOf(request.getServerPort());//获取端口号
    	if(!"80".equals(port)){//不是80端口时需加端口号
    		port = ":"+port;
    	}else{
    		port = "";
    	}
    	String strBackUrl = "http://" + request.getServerName()+port+projectName+url;//完整的请求路径http://192.168.1.117/test/+路径
    	AccessToken token = null;
    	if(TimedTask.accessToken==null || TimedTask.accessToken.getToken()==""){//token失效,重新获取,获取方法参考第二篇博文,在这由于篇幅问题暂不列出
    		token = WeixinUtil.getAccessToken(TimedTask.appid, TimedTask.appsecret);/
    	}else{
    		token = TimedTask.accessToken;
    	}
    	Ticket ticket = null;
    	if(TimedTask.ticket ==null || TimedTask.ticket.getTicket()==""){
    		ticket = WeixinUtil.getTicket(token.getToken());//获取ticket
    	}else{
    		ticket = TimedTask.ticket;
    	}
    	SignatureInfo siInfo = new SignatureInfo();
    	siInfo.setNoncestr(RandomStringUtils.randomAlphanumeric(20));//随机字符串
    	siInfo.setTimestamp(String.valueOf(System.currentTimeMillis()));//随机时间截
    	siInfo.setUrl(strBackUrl);
    	siInfo = WeixinUtil.getSignature(siInfo, ticket);
    	request.setAttribute("siInfo",siInfo);
    	return "weixin/jssdk_demo";
    }

    到此需要准备的数据就已经全部完成了,现在我们看看前台jssdk_demo.jsp页面是如何调用的

     

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
    <c:set var="BS" value="${pageContext.request.contextPath}"></c:set>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>jssdk_demo</title>
    <script type="text/javascript" src="${BS}/js/jquery-1.7.2.min.js"></script>
    <script type="text/javascript" src="${BS}/js/weixin/jweixin-1.2.0.js"></script>
    <link href="${BS}/css/weixin/weixinStyle.css" type="text/css" rel="stylesheet" />
    <link href="${BS}/css/weixin/weixinmain.css" type="text/css" rel="stylesheet"/>
    //百度地图没有密匙的可以去官网申请
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=密匙"></script>
    <script type="text/javascript" src="http://developer.baidu.com/map/jsdemo/demo/convertor.js"></script> 
    <script type="text/javascript" src="https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js"></script>
    </head>
    <input type="hidden" id="timestamp" value="${siInfo.timestamp}">
    <input type="hidden" id="nonceStr" value="${siInfo.noncestr}">
    <input type="hidden" id="signature" value="${siInfo.signature}">
    <input type="hidden" id="longitude" value="">
    <input type="hidden" id="latitude" value="">
    <input type="hidden" id="weixinOperId" value="微信appid">
    <script type="text/javascript">
    var phoneWidth = parseInt(window.screen.width);
    var phoneScale = phoneWidth/640;
    var ua = navigator.userAgent;
    if (/Android (\d+\.\d+)/.test(ua)){
        var version = parseFloat(RegExp.$1);
        if(version>2.3){
            document.write("<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0, minimum-scale = 1.0, maximum-scale = "+phoneScale+", target-densitydpi=device-dpi\">");
        }else{
            document.write("<meta name=\"viewport\" content=\"width=device-width, target-densitydpi=device-dpi\">");
        }
    }else{
        document.write("<meta name=\"viewport\" content=\"width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,target-densitydpi=device-dpi\">");
    }
    $(function(){
    	$(".nav a").click(function(){
    		$('.nav a').removeClass('active');
    		$(this).addClass('active');
    		var nav = $(this).attr("nav");
    		$("section div[class='desc']").each(function(i,val){
    			if($(this).attr("nav")==nav){
    				$(this).show();
    			}else{
    				$(this).hide();
    			}
    		});
    	});
    });
    var signature = $("#signature").val();
    var nonceStr = $("#nonceStr").val();
    var timestamp = $("#timestamp").val();
    var weixinOperId = $("#weixinOperId").val();
    wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: weixinOperId, // 必填,公众号的唯一标识
        timestamp:timestamp, // 必填,生成签名的时间戳
        nonceStr: nonceStr, // 必填,生成签名的随机串
        signature:signature,// 必填,签名
        jsApiList: [ 
            'openLocation',
    		'getLocation'
        ] // 必填,需要使用的JS接口列表,所有JS接口列表见官方文档附录2
    });
    wx.ready(function(){
    	getLocation();
    });
    wx.error(function(res){
    	//alert("error");
    });
    </script>
    <script type="text/javascript">
    $(function () {
    	$("#wdialogTitle2").text("信息提示");
        $("#wdialogConfirm2").click(function(i,val){
        	$("#wdialog2").hide();
        });
        $(".warn_message").text("");
        //刷新定位
        $(".SelectCityWrap .cityTit .r").click(function () {
            $(this).addClass("hover");
            getLocation();
        });
        $("b.search").click(function () {
            searchMap($("#indexSearchBox").val());
            return false;
        });
    });
    
    var latitude,longitude;
    //获取当前地址
    function getLocation(){
    	wx.getLocation({
    	    type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
    	    success: function (res) {
    	        latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
    	        longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
    	        var speed = res.speed; // 速度,以米/每秒计
    	        var accuracy = res.accuracy; // 位置精度
    	        getAddressInfo2(longitude,latitude);
    	    },cancel: function (res){
    	        $("#wdialogContent2").text("用户拒绝授权获取地理位置");
            	$("#wdialog2").show();
    	    }
    	});
    }
    
    var addId = "choseAdd";
    var longiText = "longitude";
    var latiText = "latitude";
    //打开百度地图并标记当前定位地址
    function showMapArea(){
    	var myGeo = new BMap.Geocoder();
    	var pt = new BMap.Point(longitude,latitude);
     	translateCallback2 = function (point){
     		createBaiduMap(point.lng,point.lat,1);
    	};
        setTimeout(function(){
        	BMap.Convertor.translate(pt,2,translateCallback2);     //火星经纬度转成百度坐标,2变成0时,则是默认的wgs84的gps坐标转换成百度坐标
    	}, 100);
    }
    //调用百度地图API,经纬度转化成实际地址
    function getAddressInfo2(lon,lat) {
    	var myGeo = new BMap.Geocoder();
    	var pt = new BMap.Point(lon,lat);
     	translateCallback2 = function (point){
    		myGeo.getLocation(point, function(rs) {
    			var addComp = rs.addressComponents;
    			var addr = addComp.province+ addComp.city + addComp.district+ addComp.street+ addComp.streetNumber;
    			$("#nowAdd").text(addr);
    		});
    	};
        setTimeout(function(){
        	BMap.Convertor.translate(pt,2,translateCallback2);     //火星经纬度转成百度坐标
    	}, 100);
    }
    function returnAdd(){
    	$("#addressArea").show();
    	$("#mapArea").hide();
    }
    function confirmC(){
    	var address = $("#choseAdd").text();
    	var longiText = $("#longitude").val();
    	var latiText = $("#latitude").val();
    	if(latiText=="" || longitude==""){
    		$("#wdialogContent2").text("请先选择您当前位置");
         	$("#wdialog2").show();
    	}
    }
    function getNavi(){
    	wx.openLocation({
    	    latitude: latitude, // 纬度,浮点数,范围为90 ~ -90
    	    longitude: longitude, // 经度,浮点数,范围为180 ~ -180。
    	    name: '我现在在这里', // 位置名
    	    address: $("#nowAdd").text(), // 地址详情说明
    	    scale: 20, // 地图缩放级别,整形值,范围从1~28。默认为最大
    	    infoUrl: 'https://www.baidu.com/' // 在查看位置界面底部显示的超链接,可点击跳转
    	});
    }
    </script>
    <body>
    	<div  id="addressArea" style="min-height:526px;">
    		<section class="SelectCityWrap" style="width:98%;">
    		    <h3 class="cityTit" style="width:100%;background:#DDDDDD;">
    		        <span class="l left" style="max-width:80%;height:45px;overflow:hidden;">当前地址:<span class="val" style="height:45px;max-height:45px;overflow:hidden;" id="nowAdd">${nowAdd}</span></span>
    		        <span class="r right"></span>
    		    </h3>
    		    <section class="content">
    				<div class="nav">
    			    	<a class=""  nav="nav_1" onclick="getNavi()">当前地址导航</a>
    			    	<a nav="nav_2" onclick="showMapArea()">地图选择</a>
    			    </div>
    				<div class="desc" nav="nav_1">
    			    </div>
    				<div class="desc" nav="nav_2" style="display:none;width:100%;">
    					<section  class="SelectCityWrap" style="width:100%;">
    						<h3 class="cityTit" style="text-align:left;width:100%;background:#DDDDDD;">
    							<span class="" style="padding-left:5px;">已选地址:<span class="val" id="choseAdd">点击地图可选择地址</span></span>
    						</h3>
    						<!-- 搜索 -->
    						<div style="height:auto;" class="indexSearch">
    							<div class="content search">
    								<input type="search" id="indexSearchBox" placeholder="点击地图可选择地址"  style="height: 38px;line-height:35px;width:100%;max-width:570px;padding-left:10px;font-size: 16px;" class="left">
    								<span></span>
    								<b class="search"></b>
    							</div>
    						</div>
    						<!-- 搜索 end-->
    						<div id="container" style="width:100%;height:300px;"></div >
    						<section id="r_content" style="margin-bottom:55px;">
    							<div class="r_shadow">
    								<div class="r_searchlist positiolist" id="search-result"></div>
    							</div>
    						</section>
    					</section> 	          
    			    </div>
    			</section>
    		</section>
    	</div>
    	<div  id="mapArea" style="min-height:526px;display:none;">
    		<header id="r_header" class="r_title">
    		    <a class="r_returnbk" onclick="returnAdd()">
    		        <img src="${BS}/images/weixin/r_icon7.png" alt="">
    		    </a>
    		    <a style="float:right;padding-right:12px;" onclick="confirmC()">确定</a>
    		</header>
    		<section  class="SelectCityWrap">
    			<!-- 搜索 -->
    		    <div style="height:auto;" class="indexSearch">
    		        <div class="content search">
    		        	<input type="search" id="indexSearchBox" placeholder="点击地图可选择地址"  style="height: 38px;line-height:35px;width:100%;max-width:570px;padding-left:10px;font-size: 16px;" class="left">
    		            <span></span>
    		            <b class="search"></b>
    		        </div>
    		    </div>
    		    <!-- 搜索 end-->
    			<div id="container" style="width:100%;height:300px;"></div >
    			<section id="r_content">
    		        <div class="r_shadow">
    		            <div class="r_searchlist positiolist" id="search-result">
    		            </div>
    		        </div>
    		    </section>
    		</section>
    	</div>
    	<script type="text/javascript" src="${BS}/js/weixin/mapLocation.js"></script>
    </body>
    </html>

    mapLocation.js,为封装好的百度地图的方法,具体看各自需求可进行修改:

     

    function getHtml5Location() {
    	if(navigator.geolocation) {
    		// navigator.geolocation.watchPosition(updateLocation, handleLocationError, {
    		navigator.geolocation.getCurrentPosition(updateLocation, handleLocationError,{
    	        // 指示浏览器获取高精度的位置,默认为false
    	        enableHighAcuracy: true,
    	        // 指定获取地理位置的超时时间,默认不限时,单位为毫秒
    	        //timeout: 5000,
    	        // 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。
    	        maximumAge: 20000
       		});
    	}else{
    		$("#wdialogContent2").text("无法获取您当前地理位置");
         	$("#wdialog2").show();
    	}
    }
    function updateLocation(position) {
    	var latitude = position.coords.latitude;
    	var longitude = position.coords.longitude;
    	var accuracy = position.coords.accuracy;
    	// 如果accuracy的值太大,我们认为它不准确,不用它计算距离
    	if (accuracy >= 1000) {
    		return;
    	}
    	var pt = new BMap.Point(longitude,latitude);
    	setTimeout(function(){
    		BMap.Convertor.translate(pt,0,translateCallback);     //真实经纬度转成百度坐标
    	}, 100);
    	translateCallback = function (point){
    		createBaiduMap(point.lat,point.lng,1);
    	};
    }
    
    function handleLocationError(error) {
    	switch (error.code) {
    		case 0:
    			$("#wdialogContent2").text("尝试获取您的位置信息时发生错误:"+ error.message);
         		$("#wdialog2").show();
    			break;
    		case 1:
    			$("#wdialogContent2").text("用户拒绝了获取位置信息请求");
         		$("#wdialog2").show();
    			break;
    		case 2:
    			$("#wdialogContent2").text("浏览器无法获取您的位置信息:"+ error.message);
         		$("#wdialog2").show();
    			break;
    		case 3:
    			$("#wdialogContent2").text("获取您位置信息超时");
         		$("#wdialog2").show();
    			break;
    	}
    }
    /**
     * 传人坐标获得详细地址
     * @param lat
     * @param lon
     */
    function getAddressInfo(lon,lat,type) {
    	var myGeo = new BMap.Geocoder();
    	var pt = new BMap.Point(lon,lat);
     	translateCallback2 = function (point){
    		myGeo.getLocation(point, function(rs) {
    			var addComp = rs.addressComponents;
    			//rs.surroundingPois;//附近地址
    			var addr = addComp.province+ addComp.city + addComp.district+ addComp.street+ addComp.streetNumber;
    			searchMap(addr);
    		});
    	};
        setTimeout(function(){
        	if(type==1){
        		BMap.Convertor.translate(pt,0,translateCallback2);     //真实经纬度转成百度坐标
        	}else{
        		translateCallback2(pt);
        	}
    	}, 100);
    }
    var map = null;
    function setMapEvent(){
        map.enableDragging();//启用地图拖拽事件,默认启用(可不写)
        map.enableScrollWheelZoom();//启用地图滚轮放大缩小
        map.enableDoubleClickZoom();//启用鼠标双击放大,默认启用(可不写)
        map.enableKeyboard();//启用键盘上下左右键移动地图
    }
    var marker = null;
    function createBaiduMap(longitude, latitude,type) { 
    	if(map==null){
    		map =new BMap.Map("container"); 
    	}
    	setMapEvent();
    	mSearchManager.clear();
    	var	pt= new BMap.Point(longitude,latitude);  
    	translateCallback = function (point){
    		var	point= new BMap.Point(point.lng, point.lat);  
    		map.setCenter(point);
    	    map.centerAndZoom(point, 16);  
    	    // 添加带有定位的导航控件
    	    var navigationControl = new BMap.NavigationControl({
    	       // 靠左上角位置
    	       anchor: BMAP_ANCHOR_TOP_LEFT,
    	       // LARGE类型
    	       type: BMAP_NAVIGATION_CONTROL_LARGE,
    	       // 启用显示定位
    	       enableGeolocation: true
    	    });
    	    map.addControl(navigationControl);  
    	    marker = new BMap.Marker(point); //标注  
    	    marker.enableDragging();
    	    marker.addEventListener("dragend",getAttr);
    		function getAttr(){
    			var p = marker.getPosition();       //获取marker的位置
    			getAddressInfo(p.lng,p.lat);
    		}
    	    map.clearOverlays();
    	    map.addOverlay(marker);
    	    map.addEventListener("click", function(e){ 
    	    	var gc = new BMap.Geocoder(); 
    	    	var pt = new BMap.Point(e.point.lng,e.point.lat); 
    	    	document.getElementById(longiText).value = e.point.lng;
    	    	document.getElementById(latiText).value = e.point.lat;
    	    	window.map.removeOverlay(marker);
        	    marker = new BMap.Marker(e.point);//创建一个覆盖物  
    	        map.addOverlay(marker);//增加一个标示到地图上  
    	    	var dress = gc.getLocation(pt, function(rs){
    	    		var addComp = rs.addressComponents;
        			var address = addComp.province+addComp.city+addComp.district+addComp.street+addComp.streetNumber;
        			if(typeof(addId)!="undefined" && addId !=null){
        				$("#"+addId).text(address);
        			}
        			searchMap(address);
        		});
    	    });
    	    // 添加定位控件
    //	    var geolocationControl = new BMap.GeolocationControl();
    //	    geolocationControl.addEventListener("locationSuccess", function(e){
    //	    	  window.map.removeOverlay(marker);
    //	    	  marker = new BMap.Marker(e.point);//创建一个覆盖物  
    //	          map.addOverlay(marker);//增加一个标示到地图上  
    //	          map.panTo(e.point); 
    		      // 定位成功事件
    //		      var address = '';
    //		      address += e.addressComponent.province;
    //		      address += e.addressComponent.city;
    //		      address += e.addressComponent.district;
    //		      address += e.addressComponent.street;
    //		      address += e.addressComponent.streetNumber;
    //		      searchMap(address);
    	    	 //getLocation();
    //	    });
    //	    geolocationControl.addEventListener("locationError",function(e){
    //	        // 定位失败事件
    //	        alert(e.message);
    //	    });
    	    //地图拖动事件
    	    /*map.addEventListener("dragging", function(evt){
    	       var offsetPoint = new BMap.Pixel(evt.offsetX, evt.offsetY); 
    	    });*/
    //	    map.addControl(geolocationControl);
    	    // 添加带有定位的导航控件
    	};
        setTimeout(function(){
        	if(type==1){
        		translateCallback(pt);
        	}else{
        		BMap.Convertor.translate(pt,0,translateCallback);     //真实经纬度转成百度坐标
        	}
    	}, 100);
    } 
    var mSearchManager = new SearchManager();
    var isR = false;
    function SearchManager(){
    	this.SearchResultList = new Array();
    	this.showSearchResult = function(poi){
    		var index = this.SearchResultList.length;
    		var marker = new BMap.Marker(poi.point);
            var a=document.createElement("a");  
            var p=document.createElement("P");
            this.SearchResultList[index] = new KzSearchResult( marker , poi , a , p);
            var address = "";
    		if(this.SearchResultList[index].poi.province!=undefined && this.SearchResultList[index].poi.province!=null
    				&& this.SearchResultList[index].poi.province !=""){
    			address = this.SearchResultList[index].poi.province;
    		}
    		if(this.SearchResultList[index].poi.city!=undefined && this.SearchResultList[index].poi.city!=null
    				&& this.SearchResultList[index].poi.city !=""){
    			address +=this.SearchResultList[index].poi.city;
    		}
        	var div = document.getElementById("search-result");
            a.href="javascript:mSearchManager.zoomto("+index+")";
            var $a = $("<a style=\"padding-left:10px;\" href=\"javascript:mSearchManager.zoomto("+index+")\"></a>");
            var section = $("<section class=\"listbox nobg list\" style=\"height:60px;\"></section>");
            var div1 = $("<div class=\"jobname\" style=\"height:25px;line-height:25px;\">"+poi.title+"</div>");
            var div2 = $("<div class=\"time\" style=\"height:25px;line-height:25px;color:#026AFF;\"></div>");
            var div3 = $("<div class=\"box1\" style=\"height:35px;line-height:35px;\">"+address+poi.address+"</div>");
            $a.append(div1).append(div2).append(div3);
            section.append($a);
            $("#search-result").append(section);
    	};
    	this.clear = function(){
    		var div = $("#search-result section");
    		div.remove();
    		window.map.removeOverlay(marker);
    		this.SearchResultList.length = 0;
    	};
    	this.clear2 = function(){
    		var div = $("#search-result section");
    		div.remove();
    		this.SearchResultList.length = 0;
    	};
    	this.zoomto = function (index){
    		$(".time").each(function(i,val){
    			if(i==index){
    				$(this).text("当前位置");
    			}else{
    				$(this).text("");
    			}
    		});
    		window.map.removeOverlay(marker);
    		marker = new BMap.Marker(this.SearchResultList[index].poi.point);
    		window.map.addOverlay(marker);
    		window.map.centerAndZoom(this.SearchResultList[index].poi.point, 16);
    		document.getElementById(longiText).value = this.SearchResultList[index].poi.point.lng;
    		document.getElementById(latiText).value = this.SearchResultList[index].poi.point.lat;
    		if(typeof(addId)!="undefined" && addId !=null){
    			document.getElementById(addId).innerHTML = this.SearchResultList[index].poi.title;
    		}
    	};	
    }
    function KzSearchResult(m , b ,a , p){
    	this.marker = m;
    	this.poi = b;
    	this.a = a;
    	this.p = p;
    }
    function searchMap(area) {
       if(map==null){
    		map =new BMap.Map("container"); 
       }
       var ls = new BMap.LocalSearch(map);
       ls.setSearchCompleteCallback(function(rs) {
    	  mSearchManager.clear2();
          if(ls.getStatus() == BMAP_STATUS_SUCCESS) {
        	for(var index=0;index<rs.getCurrentNumPois();index++){
    	        var poi = rs.getPoi(index);
    	        if (poi) {
    	        	mSearchManager.showSearchResult(poi);
    	        }
          	}
          }
       });
       ls.search(area);
    }
    

    到此该篇博文已经讲解完毕,如有问题,欢迎大家指出,一起探讨

    展开全文
  • 微信小程序开发【初级篇 / 附案例】 北风网讲师!瓢城Web俱乐部创始人,教...

    订阅后:请点击此处观看视频课程

     

    视频教程-微信小程序开发【初级篇 / 附案例】-微信开发

    学习有效期:永久观看

    学习时长:773分钟

    学习计划:13天

    难度:

     

    口碑讲师带队学习,让你的问题不过夜」

    讲师姓名:李炎恢

    高校教师 / 培训机构讲师

    讲师介绍:北风网讲师!瓢城Web俱乐部创始人,教学总监!

    ☛点击立即跟老师学习☚

     

    「你将学到什么?」

     

    「课程学习目录」

    第1章:语法基础部分
    1.微信小程序概述
    2.小程序结构分析
    3.配置分析
    4.工具栏配置
    5.逻辑层注册
    6.模块与调用
    7.组件和页面事件
    8.WXML详解
    9.WXSS详解
    10.JS逻辑交互
    11.视图容器组件view
    12.视图容器组件scroll-view
    13.视图容器组件swiper
    14.基础内容组件icon
    15.基础内容组件text
    16.基础内容组件progress
    17.表单组件radio
    18.表单组件checkbox
    19.表单组件switch
    20.表单组件label
    21.表单组件input
    22.表单组件button
    23.表单组件form
    24.表单组件textarea
    25.表单组件slider
    26.表单组件picker[普通]
    27.表单组件picker[多列]
    28.表单组件picker[日期时间]
    29.表单组件picker[省市区]
    30.表单组件picker-view
    31.导航组件navigator
    32.媒体组件image
    第2章:项目演练
    1.项目一:健身预约需求分析和构建
    2.项目一:轮播展示制作
    3.项目一:导航和地图
    4.map地图组件
    5.项目一:三张内页
    6.项目一:栏位和预约页
    7.项目二:百度天气环境配置
    8.项目二:获取当前天气
    9.项目二:贴士和未来几天
    10.项目二:切换城市
    11.项目三:手机归属地查询API
    12.wx.request发送HTTPS请求
    13.项目三:完成手机归属地查询
    14.项目四:历史上的今天【上】
    15.项目四:历史上的今天【下】
    16.图片API【上】
    17.图片API【下】
    18.上传下载API
    19.项目五:简易相册搭建
    20.项目五:批量上次图片
    21.项目五:渲染相册列表
    22.项目五:预览图片
    23.项目五:长按选定【上】
    24.项目五:长按选定【中】
    25.项目五:长按选定【下】
    26.项目五:保存和删除图片

     

    7项超值权益,保障学习质量」

    • 大咖讲解

    技术专家系统讲解传授编程思路与实战。

    • 答疑服务

    专属社群随时沟通与讲师答疑,扫清学习障碍,自学编程不再难。

    • 课程资料+课件

    超实用资料,覆盖核心知识,关键编程技能,方便练习巩固。(部分讲师考虑到版权问题,暂未上传附件,敬请谅解)

    • 常用开发实战

    企业常见开发实战案例,带你掌握Python在工作中的不同运用场景。

    • 大牛技术大会视频

    2019Python开发者大会视频免费观看,送你一个近距离感受互联网大佬的机会。

    • APP+PC随时随地学习

    满足不同场景,开发编程语言系统学习需求,不受空间、地域限制。

     

    「什么样的技术人适合学习?」

    • 想进入互联网技术行业,但是面对多门编程语言不知如何选择,0基础的你
    • 掌握开发、编程技术单一、冷门,迫切希望能够转型的你
    • 想进入大厂,但是编程经验不够丰富,没有竞争力,程序员找工作难。

     

    「悉心打造精品好课,13天学到大牛3年项目经验」

    【完善的技术体系】

    技术成长循序渐进,帮助用户轻松掌握

    掌握微信开发知识,扎实编码能力

    【清晰的课程脉络】

    浓缩大牛多年经验,全方位构建出系统化的技术知识脉络,同时注重实战操作。

    【仿佛在大厂实习般的课程设计】

    课程内容全面提升技术能力,系统学习大厂技术方法论,可复用在日后工作中。

     

    「你可以收获什么?」

    逐步掌握微信小程序的开发流程

    为进一步深入学习打好基础

     

    展开全文
  • 2020最新微信小程序基础+实战精讲视频 负责过多个软件项目的研发、设计和管...

    订阅后:请点击此处观看视频课程

     

    视频教程-2020最新微信小程序基础+实战精讲视频-微信开发

    学习有效期:永久观看

    学习时长:887分钟

    学习计划:15天

    难度:

     

    口碑讲师带队学习,让你的问题不过夜」

    讲师姓名:刘刚

    技术经理

    讲师介绍:负责过多个软件项目的研发、设计和管理工作,拥有项目管理师认证、项目监理师中级认证、出版过的图书有《微信小程序开发图解案例教程》《Axure RP8原型设计图解视频教程》,曾在中国擎天公司、神州软件子公司任职,在项目管理和项目实践、软件设计等方面经验丰富,曾负责纪检监察廉政监督监管平台产品的设计与开发、国家邮政局项目的设计与开发、政务大数据项目的设计与开发等。同时在教育教学方面有丰富的授课经验,教授Axure、用户体验、软件重构、项目经理等等方面的课程;

    ☛点击立即跟老师学习☚

     

    「你将学到什么?」

    (1)本套视频教程属于微信小程序最新内容精讲视频,没有废话;由《微信小程序简明开发教程 第二版》作者 小刚老师亲自录制;

    (2)本套课程视频后续会出配套书籍《微信小程序简明开发教程 第三版》;

    (3)本套课程设计方式:基础内容讲解+实战演练+综合案例完整训练,基础内容由浅入深讲解,案例代码逐行讲解;

    (4)本套课程提供60个精讲视频、877分钟讲解、5个实战、3个综合案例,提供云开发和非云开发两种模式;

    (5)提供完整教程素材、完整源代码、完整课件操作;

    (6)提供学习过程中答疑,辅助可以快速学习;

     

    「课程学习目录」

    第1章:认识微信小程序
    1.微信小程序介绍和开发准备
    2.微信小程序开发工具的使用
    3.实战:Hello World的创建
    第2章:微信小程序框架分析
    1.微信小程序目录结构介绍
    2.微信小程序注册程序和注册页面使用
    3.微信小程序如何绑定数据
    4.实战:天气微信小程序
    5.微信小程序条件渲染和列表渲染
    6.微信小程序定义模板和引用功能
    7.WXS小程序脚本语言
    8.实战:仿香哈菜谱微信小程序
    第3章:用微信小程序组件构建UI界面
    1.视图容器组件
    2.基础内容组件
    3.表单组件
    4.导航链接
    5.媒体组件
    6.地图组件
    7.画布组件
    8.实战:表单登录注册微信小程序
    第4章:必备的微信小程序API
    1.请求服务器数据API
    2.文件上传与下载API
    3.WebSoket会话API
    4.图片处理API
    5.文件操作API
    6.数据缓存API
    7.位置信息API
    8.设备应用API
    9.交互反馈API
    10.用户及授权设置API
    11.微信支付API
    12.分享API
    13.实战:仿豆瓣电影微信小程序
    第5章:微信小程序云开发
    1.认识小程序云开发
    2.云开发控制台使用
    3.云函数
    4.云开发文件存储
    5.云开发数据库
    6.实战:地址管理云开发
    第6章:综合案例:仿中国婚博会微信小程序
    1.准备工作
    2.设计流程-底部标签导航设计
    3.设计流程-海报轮播效果设计
    4.设计流程-宫格导航设计
    5.设计流程-全部分类导航设计
    6.设计流程-现金券下拉菜单筛选条件设计
    7.设计流程-现金券列表页设计
    8.设计流程-婚博会索票设计
    9.设计流程-获知渠道弹出层设计
    第7章:综合案例:仿华为商城微信小程序
    1.准备工作
    2.设计流程-我的界面列表导航设计
    3.设计流程-账号登录
    4.设计流程-用户注册
    5.设计流程-首页布局设计及动态获取数据
    6.设计流程-分类导航设计及动态获取数据
    第8章:综合案例:记账本微信小程序云开发
    1.准备工作
    2.设计流程-账户列表
    3.设计流程-创建账户
    4.设计流程-账户明细列表
    5.设计流程-记一笔账户明细
    6.设计流程-分页获取账本列表
    7.设计流程-创建记账本

     

    7项超值权益,保障学习质量」

    • 大咖讲解

    技术专家系统讲解传授编程思路与实战。

    • 答疑服务

    专属社群随时沟通与讲师答疑,扫清学习障碍,自学编程不再难。

    • 课程资料+课件

    超实用资料,覆盖核心知识,关键编程技能,方便练习巩固。(部分讲师考虑到版权问题,暂未上传附件,敬请谅解)

    • 常用开发实战

    企业常见开发实战案例,带你掌握Python在工作中的不同运用场景。

    • 大牛技术大会视频

    2019Python开发者大会视频免费观看,送你一个近距离感受互联网大佬的机会。

    • APP+PC随时随地学习

    满足不同场景,开发编程语言系统学习需求,不受空间、地域限制。

     

    「什么样的技术人适合学习?」

    • 想进入互联网技术行业,但是面对多门编程语言不知如何选择,0基础的你
    • 掌握开发、编程技术单一、冷门,迫切希望能够转型的你
    • 想进入大厂,但是编程经验不够丰富,没有竞争力,程序员找工作难。

     

    「悉心打造精品好课,15天学到大牛3年项目经验」

    【完善的技术体系】

    技术成长循序渐进,帮助用户轻松掌握

    掌握微信开发知识,扎实编码能力

    【清晰的课程脉络】

    浓缩大牛多年经验,全方位构建出系统化的技术知识脉络,同时注重实战操作。

    【仿佛在大厂实习般的课程设计】

    课程内容全面提升技术能力,系统学习大厂技术方法论,可复用在日后工作中。

     

    「你可以收获什么?」

    快速入门微信小程序开发,学会微信小程序常用的组件, 学会微信小程序常用的API接口

    完善微信小程序整体知识体系

    通过项目实战和综合案例深入学习商业项目开发

    学会微信小程序云开发和非云开发两种模式

     

    展开全文
  • ·上一篇android项目案例1- 基于Android studio的仿微信底部导航栏实现·中分享了项目中的底部导航栏模块,有不懂的地方可以回到上一篇文章再看看,今天我要介绍一下我项目中的另一个百度地图模块。接下来进入主题!...

    ·上一篇android项目案例1- 基于Android studio的仿微信底部导航栏实现·中分享了项目中的底部导航栏模块,有不懂的地方可以回到上一篇文章再看看,今天我要介绍一下我项目中的另一个百度地图模块。接下来进入主题!!!!

    百度地图有以下功能:

    1. 定位

    2. 选择不同的地图类型后显示不同的地图

     

    一.在百度地图开发者平台上申请API Key

    百度地图开发者平台地址:http://lbsyun.baidu.com/index.php?title=androidsdk。点击界面的“获取密钥”,进入界面之后,点击“创建应用”按钮。将应用类型选择为“Android SDK”,填写你的项目应用名称即在Android studio中创建的项目名称、查看发布版本SHA1开发版本SHA1,填写项目包名。完成后点击提交即可成为百度开发者,获得密钥即应用AK

     

    1.获取开发版SHA1:

    输入命令:keytool -list -v -keystore debug.keystore,回车
    输入密钥库口令:android(系统默认)回车。

    方法1:

    打开你的安卓ADB目录,一般在C盘的用户目录中以.android为文件名。

    这个debug文件就是获取SHA1值的文件。接下来WIN+R,输入cmd。来到命令窗口界面:先输入cd .android来到这个文件夹中之后输入keytool -list -v -keystore debug.keystore

    方法2:

    在android studio的项目中查找开发版SHA1。

     

    2.获取发布版SHA1:

    要想获取发布版的SHA1的值,必须先对项目进行签名,如何对项目进行签名的,详情请看本人觉得不错,转载的博客:Android移动开发-如何在AndroidStudio里进行对应用程序进行签名,项目签名后可以直接用Android Studio提供的命令控制台Terminal输入命令时输入“cd 自己应用签名的jks文件保存的文件目录”然后接着回车,比如:cd D:\AndroidStudio\AndroidKey\BaiduMapTest1,接着在命令行里输入keytool -list -v -keystore jks文件名,比如:keytool -list -v -keystore BaiduMapTest.jks,接着按回车,然后输入秘钥,回车(秘钥库口令是看不到的)。如下图所示:

    3.申请百度地图的API Key

    得到发布版本SHA1、开发版本SHA1后,在百度地图开发者中心的创建应用里分别输入应用名称,应用类型,开发版和发布版的SHA1的值,包名  后点击提交,就能申请到了百度地图的API Key了。如下图所示

    获取密钥成功(API key)

     

    二.集成百度地图

    1.上百度地图开发者网站下载百度地图SDK

    2.将BaiduLBS_Android.jarr文件复制到libs目录中。

    3.在main文件下新建JniLibs文件夹,将剩下的文件拷贝到里面。

    4.在build.gradle文件中设置

    工程配置还需要把jar包集成到自己的工程中,如图上图所示,放入libs目录下。将每个jar文件导入到工程中。对应在build.gradle生成工程所依赖的jar文件说明,如下所示:

      ndk {
                abiFilters "armeabi","armeabi-v7a","x86"
            }
    
            packagingOptions {
                exclude "lib/libssl.so"
            }
    
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    
        sourceSets {
            main {
                jniLibs.srcDir 'libs'
                //说明so的路径为该libs路径,关联所有地图SDK的so文件
            }
        }

     

    5.在项目中的AndroidManifest.xm文件中配置相关数据 

     <!-- 百度API所需权限 -->
        <uses-permission android:name="android.permission.GET_ACCOUNTS" />
        <uses-permission android:name="android.permission.USE_CREDENTIALS" />
        <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
        <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.BROADCAST_STICKY" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
    <!-- 百度地图API KEY -->
            <meta-data
                android:name="com.baidu.lbsapi.API_KEY"
                android:value="Ee5xOWrrxfNSkBqmLNAYdxr9ij2roADX" />
     <!-- 百度定位服务 -->
            <service
                android:name="com.baidu.location.f"
                android:enabled="true"
                android:process=":remote" />
    
    <uses-sdk
            android:minSdkVersion="14"
            android:targetSdkVersion="21" />

    6.在布局xml文件中添加地图控件

    <?xml version="1.0" encoding="utf-8"?>
    <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">
    
        <com.baidu.mapapi.map.MapView
            android:id="@+id/id_bmapView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:clickable="true" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true">
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="2dp"
                android:orientation="horizontal">
    
                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="50dp"
                    android:gravity="center_vertical"
                    android:orientation="horizontal">
    
                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:gravity="center_vertical"
                        android:paddingLeft="3dp"
                        android:text="百度地图"
                        android:textColor="#FF4500"
                        android:textSize="20sp" />
                </LinearLayout>
    
            </RelativeLayout>
    
        </LinearLayout>
    
    </RelativeLayout>

    7.创建Activity,实现地图功能。

    package com.CWT.navigation.fragment.TabMapFragment;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.app.Fragment;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.PopupMenu;
    import android.widget.Toast;
    
    
    import com.CWT.navigation.R;
    import com.baidu.location.BDLocation;
    import com.baidu.location.BDLocationListener;
    import com.baidu.location.LocationClient;
    import com.baidu.location.LocationClientOption;
    import com.baidu.mapapi.SDKInitializer;
    import com.baidu.mapapi.map.BaiduMap;
    import com.baidu.mapapi.map.BitmapDescriptor;
    import com.baidu.mapapi.map.BitmapDescriptorFactory;
    import com.baidu.mapapi.map.MapStatus;
    import com.baidu.mapapi.map.MapStatusUpdate;
    import com.baidu.mapapi.map.MapStatusUpdateFactory;
    import com.baidu.mapapi.map.MapView;
    import com.baidu.mapapi.map.MyLocationConfiguration;
    import com.baidu.mapapi.map.MyLocationData;
    import com.baidu.mapapi.model.LatLng;
    
    public class TabMapFragment extends Fragment{
        private static final int BAIDU_READ_PHONE_STATE = 100;
    
        private MapView mMapView = null;
        private BaiduMap mBaiduMap;
        private LocationClient mlocationClient;
        private MylocationListener mlistener;
        private Context context;
    
        private double mLatitude;
        private double mLongitude;
        private float mCurrentX;
    
        private Button mGetMylocationBN;
    
        PopupMenu popup = null;
    
        private Activity mParentActivity = null;
    
        //自定义图标
        private BitmapDescriptor mIconLocation;
    
        private MyOrientationListener myOrientationListener;
        //定位图层显示方式
        private MyLocationConfiguration.LocationMode locationMode;
    
    //    public TabMapFragment(Context c){
    //        this.context = c;
    //    }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
    
            //引入我们的布局
            return inflater.inflate(R.layout.fragment_tab_map, container, false);
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mParentActivity = this .getActivity();
            Log.d("-----------------------", mParentActivity.getApplicationContext().toString());
    
            SDKInitializer.initialize(mParentActivity.getApplicationContext()); //这里可以了
            //剩下是baidu初始化找不到库的问题,去看例子
    
            //mParentActivity.setContentView(R.layout.fragment_tab_map);
    
            this.context =mParentActivity.getApplicationContext();
    
    
        }
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
    
            initView();
            //判断是否为Android 6.0 以上的系统版本,如果是,需要动态添加权限
            if (Build.VERSION.SDK_INT >= 23) {
                showLocMap();
            } else {
                initLocation();//initLocation为定位方法
            }
            setHasOptionsMenu(true);
        }
    
        private void initView() {
            mMapView = (MapView) mParentActivity.findViewById(R.id.id_bmapView);
    
            mBaiduMap = mMapView.getMap();
            //根据给定增量缩放地图级别
            MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(18.0f);
            mBaiduMap.setMapStatus(msu);
            MapStatus mMapStatus;//地图当前状态
            MapStatusUpdate mMapStatusUpdate;//地图将要变化成的状态
            mMapStatus = new MapStatus.Builder().overlook(-45).build();
            mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
            mBaiduMap.setMapStatus(mMapStatusUpdate);
        }
    
        /**
         * 定位方法
         */
        private void initLocation() {
            locationMode = MyLocationConfiguration.LocationMode.NORMAL;
    
            //定位服务的客户端。宿主程序在客户端声明此类,并调用,目前只支持在主线程中启动
            mlocationClient = new LocationClient(context);
            mlistener = new MylocationListener();
    
            //注册监听器
            mlocationClient.registerLocationListener(mlistener);
            //配置定位SDK各配置参数,比如定位模式、定位时间间隔、坐标系类型等
            LocationClientOption mOption = new LocationClientOption();
            //设置坐标类型
            mOption.setCoorType("bd09ll");
            //设置是否需要地址信息,默认为无地址
            mOption.setIsNeedAddress(true);
            //设置是否打开gps进行定位
            mOption.setOpenGps(true);
            //设置扫描间隔,单位是毫秒,当<1000(1s)时,定时定位无效
            int span = 1000;
            mOption.setScanSpan(span);
            //设置 LocationClientOption
            mlocationClient.setLocOption(mOption);
    
            //初始化图标,BitmapDescriptorFactory是bitmap 描述信息工厂类.
            mIconLocation = BitmapDescriptorFactory
                    .fromResource(R.drawable.icon_geo);
    
            myOrientationListener = new MyOrientationListener(context);
            //通过接口回调来实现实时方向的改变
            myOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
                @Override
                public void onOrientationChanged(float x) {
                    mCurrentX = x;
                }
            });
    
        }
    
        @Override
        public void onStart() {
            super.onStart();
            //开启定位
            mBaiduMap.setMyLocationEnabled(true);
            if (!mlocationClient.isStarted()) {
                mlocationClient.start();
            }
            myOrientationListener.start();
        }
    
        @Override
        public void onStop() {
            super.onStop();
            //停止定位
            mBaiduMap.setMyLocationEnabled(false);
            mlocationClient.stop();
            myOrientationListener.stop();
        }
    
        @Override
        public void onResume() {
            super.onResume();
            mMapView.onResume();
        }
    
        @Override
        public void onPause() {
            super.onPause();
            mMapView.onPause();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            mMapView.onDestroy();
        }
    
        /**
         * 获取我的定位
         */
        public void getMyLocation() {
            LatLng latLng = new LatLng(mLatitude, mLongitude);
            MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
            mBaiduMap.setMapStatus(msu);
        }
    
        /**
         * 菜单栏
         * @param menu
         * @param inflater
         */
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            super.onCreateOptionsMenu(menu, inflater);
            inflater.inflate(R.menu.menu_main, menu);
        }
    
        /**
         * 菜单项的选择
         * @param item
         * @return
         */
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                                case R.id.id_map_common:
                                    mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
                                    break;
                                case R.id.id_map_site:
                                    mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
                                    break;
                                case R.id.id_map_traffic:
                                    if (mBaiduMap.isTrafficEnabled()) {
                                        mBaiduMap.setTrafficEnabled(false);
                                        item.setTitle("实时交通(off)");
                                    } else {
                                        mBaiduMap.setTrafficEnabled(true);
                                        item.setTitle("实时交通(on)");
                                    }
                                    break;
                                case R.id.id_map_mlocation:
                                    getMyLocation();
                                    break;
                                case R.id.id_map_model_common:
                                    //热力图
                                    mBaiduMap.setBaiduHeatMapEnabled(true);
                                    break;
                            }
                            return true;
        }
    
    
        /**
         * 所有的定位信息都通过接口回调来实现
         */
        public class MylocationListener implements BDLocationListener {
            //定位请求回调接口
            private boolean isFirstIn = true;
    
            //定位请求回调函数,这里面会得到定位信息
            @Override
            public void onReceiveLocation(BDLocation bdLocation) {
                //BDLocation 回调的百度坐标类,内部封装了如经纬度、半径等属性信息
                //MyLocationData 定位数据,定位数据建造器
                /**
                 * 可以通过BDLocation配置如下参数
                 * 1.accuracy 定位精度
                 * 2.latitude 百度纬度坐标
                 * 3.longitude 百度经度坐标
                 * 4.satellitesNum GPS定位时卫星数目 getSatelliteNumber() gps定位结果时,获取gps锁定用的卫星数
                 * 5.speed GPS定位时速度 getSpeed()获取速度,仅gps定位结果时有速度信息,单位公里/小时,默认值0.0f
                 * 6.direction GPS定位时方向角度
                 * */
                mLatitude = bdLocation.getLatitude();
                mLongitude = bdLocation.getLongitude();
                MyLocationData data = new MyLocationData.Builder()
                        .direction(mCurrentX)//设定图标方向
                        .accuracy(bdLocation.getRadius())//getRadius 获取定位精度,默认值0.0f
                        .latitude(mLatitude)//百度纬度坐标
                        .longitude(mLongitude)//百度经度坐标
                        .build();
                //设置定位数据, 只有先允许定位图层后设置数据才会生效,参见 setMyLocationEnabled(boolean)
                mBaiduMap.setMyLocationData(data);
                //配置定位图层显示方式,三个参数的构造器
                /**
                 * 1.定位图层显示模式
                 * 2.是否允许显示方向信息
                 * 3.用户自定义定位图标
                 * */
                MyLocationConfiguration configuration
                        = new MyLocationConfiguration(locationMode, true, mIconLocation);
                //设置定位图层配置信息,只有先允许定位图层后设置定位图层配置信息才会生效,参见 setMyLocationEnabled(boolean)
                mBaiduMap.setMyLocationConfigeration(configuration);
                //判断是否为第一次定位,是的话需要定位到用户当前位置
                if (isFirstIn) {
                    //地理坐标基本数据结构
                    LatLng latLng = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
                    //描述地图状态将要发生的变化,通过当前经纬度来使地图显示到该位置
                    MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
                    //改变地图状态
                    mBaiduMap.setMapStatus(msu);
                    isFirstIn = false;
                    Toast.makeText(context, "您当前的位置为:" + bdLocation.getAddrStr(),Toast.LENGTH_LONG).show();
                }
            }
        }
    
        /**
         * Android 6.0 以上的版本的定位方法
         */
        public void showLocMap() {
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
                    != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(getContext(), "没有权限,请手动开启定位权限", Toast.LENGTH_SHORT).show();
                // 申请一个(或多个)权限,并提供用于回调返回的获取码(用户定义)
                ActivityCompat.requestPermissions(mParentActivity,new String[]{
                        Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE
                }, BAIDU_READ_PHONE_STATE);
          }
               else {
                initLocation();
            }
        }
    
        //Android 6.0 以上的版本申请权限的回调方法
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            switch (requestCode) {
                // requestCode即所声明的权限获取码,在checkSelfPermission时传入
                case BAIDU_READ_PHONE_STATE:
                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        // 获取到权限,作相应处理(调用定位SDK应当确保相关权限均被授权,否则可能引起定位失败)
                        initLocation();
                    } else {
                        // 没有获取到权限,做特殊处理
                        Toast.makeText(getContext(), "获取位置权限失败,请手动开启", Toast.LENGTH_SHORT).show();
                    }
                    break;
                default:
                    break;
            }
        }
    
    }
    
    
    
    
    

    完成以上全部步骤,即可运行项目,

    效果图如下:

    请各位大神指教,本博文内容可能写的有错误,但程序没错误,程序是我调了很久,请教了老师后才完成的,期间跳了很多坑,也填了很多坑,希望本博文能够帮到大家。

    展开全文
  • 微信公众号开发 云知梦创始人,国际架构师,11年互联网培训和开发经验,曾在港...
  • 作为一线微信开发商云集、专注在开发实践方面的顶级技术活动,演讲话题极为丰富,涵盖了微信开发不同维度的多个层内容 (首批议程发布),包括:企业服务号开发和高级应用、企业号开发、如何与业务系统对接、各种...
  • 微信公众账号开发

    2014-02-27 15:00:52
    微信开发 微信公众平台开发(82) 天气预报 摘要: 在这篇教程中,我们将介绍如何在微信公众平台上开发天气预报功能。我们将使用中国天气网的气象数据接口来获取天气信息。这篇教程将介绍以下内容:获取...
  • 微信公众平台开发

    2014-01-18 11:18:26
    微信公众平台开发(80) 上传下载多媒体文件 摘要: 微信公众账号在回复图片、语音、视频的时候,将使用media_id来调用相关文件,很多朋友咨询这个如何开发实现。本文将介绍在微信公众平台开发过程中,如何上传...
  • 作为一线微信开发商云集、专注在开发实践方面的顶级技术活动,演讲话题极为丰富,涵盖了微信开发不同维度的多个层内容 (首批议程发布),包括:企业服务号开发和高级应用、企业号开发、如何与业务系统对接、...
  • 微信小程序开发实战 张容铭:爱创课堂创始人,前百度前端工程师。曾主导百度新首...
  • 作为微信小程序的开发工程师,我接手了“开荒”百度智能小程序(以下简称百度小程序)的任务,自5月初开发,一个多月就完成了苏宁易购百度小程序的开发工作,并在7月初的“百度开发者大会”上作为首批小程序对外提供...
  • 异常火爆的微信公众平台大会,传达出哪些信息? A-A+ 罗超 2013-11-19 07:07 57 微信腾讯投稿头条 5000人报名,400人参加的微信公众平台合作伙伴大会,异常火爆,连主办方在场外设置的视频直播...
  • 小程序云开发出坑系列(一)—初识小程序开发 一、什么是小程序? 1.1 小程序简介 是一种不需要下载安装即可使用的应用,实现应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。 1.2 小程序和APP、H5之间的...
  • 摘要: 微信小程序能让创业变简单吗? 微信小程序能改变移动...从内测信息来看,小程序能够借助微信联合登录,和开发者已有的 App 后台的用户数据进行打通。   微信小程序能让创业变简单吗? 微信小程序能改变移动
  • 前几天我在天气小程序的过程中,上网找了一些天气的api 服务商,顺便点评一下;发现高德和百度都有提供相关的接口。 No1、高德地图 ...百度地图也是和高德地图一样时间上线小程序服务的,果然是ba...
1 2 3 4 5 ... 20
收藏数 1,347
精华内容 538
关键字:

微信开发联合百度地图