不会原生开发使用百度地图SDK开发APP

众所周知,一般大的互联网平台都会提供官方 SDK 或者 API 提供给开发者使用。这里介绍自己在移动 APP 中使用百度地图 SDK 和 API 的方式查询信息的一次过程。

本人使用 react-native 开发安卓和 iOS 跨端应用,没有原生开发的经验,所以在开发中遇到使用原生功能的库时有时会难以解决,需要踩各种坑,幸好基本能够出坑。

集成第三方库

闲话少说,开始入坑。项目中采用的是 react-native-baidu-map 的库,不出意外,在能够正常使用前需要费一下气力,官方文档描述的对不懂原生开发的人会有些懵。

安卓上碰到的坑:
1.js/MapView.js 中 react 已移除 PropTypes,需引入 prop-types
import PropTypes from 'prop-types';
2.android/.../BaiduMapPackage.java 文件移除(注释) createJSModules 方法

// @Override
// public List<Class<? extends JavaScriptModule>> createJSModules() {
//     return Collections.emptyList();
// }

3.权限声明不对(官方文档未提供详细说明,需要结合百度地图文档说明等)

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<!-- react-native 获取网络状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 这个权限用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 这个权限用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<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.WRITE_SETTINGS" />
<!-- 读取设备硬件信息,统计数据 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.GET_TASKS" />

iOS 编译问题:这里不做过多说明,这篇文章介绍等比较详细,如果编译还有问题,不妨在 issue 和简书上搜索看看。

申请 KEY

百度地图开发平台申请,因为我需要 iOS 和安卓上都使用,所以我需要创建浏览器端,Android SDK 和 iOS SDK 三种应用。把 iOS 和安卓的 KEY 按文档填在代码中,浏览器端申请的我需要在模拟请求 API 的时候使用(IP 白名单填写“*”)。

简单使用

// ...
import { MapView, MapTypes, MapModule, Geolocation } from "react-native-baidu-map";
import * as _ from 'lodash';

const MAP_HEIGHT = {
  Folded: 135,
  Nomal: size.width
};
class BaiduMap extends React.Component<IBaiduMapProps, any> {
  static navigationOptions = ({ navigation }: any) => ({
    title: "百度地图"
  });

  constructor(props: IBaiduMapProps) {
    super(props);
    this.state = {
      mapType: MapTypes.NORMAL,
      zoom: 10,
      center: {
        longitude: 116.46,
        latitude: 39.92
      },
      mapHeight: MAP_HEIGHT.Nomal, // 地图高度
      searchValue: ""
    };
  }

  async componentDidMount() {
    this.getLocation();
  }

  // 判断是否国内。我国纬度3.86~53.55,经度73.66~135.05;北京:纬度39.92,经度为116.46
  getLocation = async () => {
    try {
      const locationData = await Geolocation.getCurrentPosition();
      console.log("locationData: ", locationData);
      const longitude = _.get(locationData, "longitude");
      const latitude = _.get(locationData, "latitude");
      if (!_.isNumber(longitude) || !_.isNumber(latitude)) {
        const msg = _.get(locationData, "errmsg", "获取定位错误");
        return Toast.info(msg, 2);
      }

      if (latitude > 53.55 || latitude < 3.86 || longitude > 135.05 || longitude < 73.66){
        Toast.info('您的定位好像有问题', 2);
      } else {
        await this.setState({
          zoom: 15,
          center: {
            longitude: longitude || 116.46,
            latitude: latitude || 39.92
          }
        });
      }
    } catch (e) {
      console.log("get location error: ", e);
    }
  };

  render() {
    return (
      <View>
        {/** 其他代码 **/}
        <MapView
          style={{ width: "100%", height: "100%" }}
          zoom={this.state.zoom}
          mapType={mapType}
          center={this.state.center}
          onMarkerClick={(e: any) => {
            console.log("onMarkerClick: 自定义标记点点击时");
          }}
          onMapStatusChangeFinish={(e: any) => {
            // Android only
            console.log("onMapStatusChangeFinish: 地图变化完成时");
            const longitude = _.get(e, "target.longitude");
            const latitude = _.get(e, "target.latitude");
            this.setState({
              center: {
                longitude: _.isNumber(longitude) ? longitude : 116.46,
                latitude: _.isNumber(latitude) ? latitude : 39.92
              }
            });
          }}
          onMapLoaded={() => {
            console.log("onMapLoaded: 地图加载完成");
          }}
          onMapPoiClick={(e: any) => {
            console.log("onMapPoiClick: 地图上文字标记等点击时");
          }}
          onMapClick={(e: any) => {
            console.log("onMapClick: 地图上文字标记以外的点击时");
          }}
          onMapDoubleClick={(e: any) => {
            console.log("onMapDoubleClick: 双击");
          }}
        />
      </View>
    );
  }
}

搜索关键字

react-native-baidu-map 没有提供搜索的方法,而我不会原生开发,所以使用浏览器端的方式调用百度提供的 API,具体可查询官方文档

// GET 请求的参数如下:
params = {
  query: '水果',
  output: 'json',
  page_size: 20,
  page_num: 1,
  scope: 2, // 取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息
  region: '上海市南京路',
  ak: '你申请的浏览器ak'
}

// 反向地理编码
reverseGeoCode = async (latitude: number, longitude: number) => {
  try {
    return await Geolocation.reverseGeoCode(latitude, longitude);
  } catch (e) {
    console.log('get reverseGeoCode error: ', e);
  }
};
onQuery = async (page_num = 1) => {
  // const addrResult = await this.reverseGeoCode(this.state.center.latitude, this.state.center.longitude);
  const result = await this.props.dispatch({
    type: 'baidu_map/query',
    payload: {
      query: '水果', // 要查询的关键字
      output: 'json',
      page_size: 20,
      page_num,
      scope: 2, // 取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息
      region: '上海市南京路', // 这里 region 可以用 reverseGeoCode 方法获得的地理信息
    },
  });
  // result 即为查询到的数据,可以显示给用户
};

最后请求的 URL 形如:http://api.map.baidu.com/place/v2/search?ak=你申请的浏览器ak&query=%E6%B0%B4%E6%9E%9C&output=json&page_size=20&page_num=1&scope=2&region=%E5%8C%97%E4%BA%AC%E5%B8%82%E6%9C%9D%E9%98%B3%E5%8C%BA

最终代码如下:

// ...
import { MapView, MapTypes, MapModule, Geolocation } from "react-native-baidu-map";
import * as _ from 'lodash';

const MAP_HEIGHT = {
  Folded: 135,
  Nomal: size.width
};
class BaiduMap extends React.Component<IBaiduMapProps, any> {
  static navigationOptions = ({ navigation }: any) => ({
    title: "百度地图"
  });

  constructor(props: IBaiduMapProps) {
    super(props);
    this.state = {
      mapType: MapTypes.NORMAL,
      zoom: 10,
      center: {
        longitude: 116.46,
        latitude: 39.92
      },
      mapHeight: MAP_HEIGHT.Nomal, // 地图高度
      searchValue: ""
    };
  }

  async componentDidMount() {
    this.getLocation();
  }

  // 判断是否国内。我国纬度3.86~53.55,经度73.66~135.05;北京:纬度39.92,经度为116.46
  getLocation = async () => {
    try {
      const locationData = await Geolocation.getCurrentPosition();
      console.log("locationData: ", locationData);
      const longitude = _.get(locationData, "longitude");
      const latitude = _.get(locationData, "latitude");
      if (!_.isNumber(longitude) || !_.isNumber(latitude)) {
        const msg = _.get(locationData, "errmsg", "获取定位错误");
        return Toast.info(msg, 2);
      }

      if (latitude > 53.55 || latitude < 3.86 || longitude > 135.05 || longitude < 73.66){
        Toast.info('您的定位好像有问题', 2);
      } else {
        await this.setState({
          zoom: 15,
          center: {
            longitude: longitude || 116.46,
            latitude: latitude || 39.92
          }
        });
      }
    } catch (e) {
      console.log("get location error: ", e);
    }
  };

  // 反向地理编码
  reverseGeoCode = async (latitude: number, longitude: number) => {
    try {
      return await Geolocation.reverseGeoCode(latitude, longitude);
    } catch (e) {
      console.log("get reverseGeoCode error: ", e);
    }
  };

  onQuery = async (page_num = 1) => {
    if (!this.state.searchValue) {
      return Toast.info('请输入查询关键字', 1);
    }

    const addrResult = await this.reverseGeoCode(this.state.center.latitude, this.state.center.longitude);
    console.log('addrResult: ', addrResult);
    const fullSite = `${_.get(addrResult, 'city', '')}${_.get(addrResult, 'district', '')}`;
    const result = await this.props.dispatch({
      type: 'baidu_map/query',
      payload: {
        query: this.state.searchValue,
        output: 'json',
        page_size: 20,
        page_num,
        scope: 2, // 取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息
        region: fullSite,
      },
    });
    const searchData = _.get(result, 'results');
    // ...
  };

  render() {
    return (
      <View>
        {/** 其他代码 **/}
        <MapView
          style={{ width: "100%", height: "100%" }}
          zoom={this.state.zoom}
          mapType={mapType}
          center={this.state.center}
          onMarkerClick={(e: any) => {
            console.log("onMarkerClick: 自定义标记点点击时");
          }}
          onMapStatusChangeFinish={(e: any) => {
            // Android only
            console.log("onMapStatusChangeFinish: 地图变化完成时");
            const longitude = _.get(e, "target.longitude");
            const latitude = _.get(e, "target.latitude");
            this.setState({
              center: {
                longitude: _.isNumber(longitude) ? longitude : 116.46,
                latitude: _.isNumber(latitude) ? latitude : 39.92
              }
            });
          }}
          onMapLoaded={() => {
            console.log("onMapLoaded: 地图加载完成");
          }}
          onMapPoiClick={(e: any) => {
            console.log("onMapPoiClick: 地图上文字标记等点击时");
          }}
          onMapClick={(e: any) => {
            console.log("onMapClick: 地图上文字标记以外的点击时");
          }}
          onMapDoubleClick={(e: any) => {
            console.log("onMapDoubleClick: 双击");
          }}
        />
      </View>
    );
  }
}

最后上图


baidu_map1.jpeg
baidu_map2.jpeg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,691评论 2 59
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,465评论 25 707
  • 我在这里先跟大家说声对不起,上周的分享没有准备好,突然有事就中断了。 这周我分享的是,古典老师的拆掉思维的墙。 古...
    秀佩阅读 190评论 0 0
  • 听说第一个最简单的发音是“妈妈”,是婴儿张嘴吐气的自然结果;第二个最简单的发音就是“爸爸”一种尽责的职称,同时也是...
    amira_D阅读 1,094评论 0 0
  • 天蝎座和上升天蝎座,随着10月11日,第一大吉星木星来到天蝎座,天蝎座的坏运气也就算到头了,好运正式开始。在过去的...
    星座论讯阅读 363评论 0 1