nsm 1 жил өмнө
commit
4ee6f81a9a
100 өөрчлөгдсөн 4302 нэмэгдсэн , 0 устгасан
  1. 13 0
      .gitignore
  2. 12 0
      .npmignore
  3. 289 0
      AMap-android.js
  4. 218 0
      AMap-ios.js
  5. 31 0
      AMap.js
  6. 21 0
      LICENSE
  7. 488 0
      README.md
  8. BIN
      android/AMapResources/gpsStat1@2x.png
  9. BIN
      android/AMapResources/gps_stat1.png
  10. BIN
      android/AMapResources/icon_location.png
  11. BIN
      android/AMapResources/icon_location@2x.png
  12. BIN
      android/AMapResources/icon_location@3x.png
  13. BIN
      android/AMapResources/poi_marker.png
  14. 30 0
      android/build.gradle
  15. 17 0
      android/proguard-rules.pro
  16. 3 0
      android/src/main/AndroidManifest.xml
  17. 22 0
      android/src/main/java/com/reactnativecomponent/amap/AMAPInfoWindowAdapter.java
  18. 14 0
      android/src/main/java/com/reactnativecomponent/amap/BaseCustomView.java
  19. 5 0
      android/src/main/java/com/reactnativecomponent/amap/CustomViewMarkerInterface.java
  20. 83 0
      android/src/main/java/com/reactnativecomponent/amap/HaversineAlgorithm.java
  21. 211 0
      android/src/main/java/com/reactnativecomponent/amap/RCTAMapManager.java
  22. 1037 0
      android/src/main/java/com/reactnativecomponent/amap/RCTAMapModule.java
  23. 33 0
      android/src/main/java/com/reactnativecomponent/amap/RCTAMapPackage.java
  24. 1117 0
      android/src/main/java/com/reactnativecomponent/amap/RCTAMapView.java
  25. 44 0
      android/src/main/java/com/reactnativecomponent/amap/RCTInfoWindow.java
  26. 138 0
      android/src/main/java/com/reactnativecomponent/amap/Utils.java
  27. 98 0
      android/src/main/java/com/reactnativecomponent/amap/util/SensorEventHelper.java
  28. 172 0
      android/src/main/java/com/reactnativecomponent/amap/util/ShapeHelper.java
  29. BIN
      android/src/main/res/drawable/gps_point.png
  30. 3 0
      android/src/main/res/values/strings.xml
  31. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/3d_sky_day.data
  32. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/3d_sky_night.data
  33. 101 0
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/3dlandscape.xml
  34. 101 0
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/3dportrait.xml
  35. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/cross_bg.png
  36. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/cross_bg_day.png
  37. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/cross_bg_night.png
  38. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/d_yellow.png
  39. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/d_yellow_day.png
  40. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/d_yellow_night.png
  41. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/grass_day.png
  42. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/grass_night.png
  43. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/road_bottom.png
  44. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/road_bottom_day.png
  45. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/road_bottom_night.png
  46. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/roadbk_main.png
  47. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/roadbk_main_day.png
  48. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/roadbk_main_night.png
  49. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/bktile.data
  50. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/bktile_n.data
  51. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/building.data
  52. 0 0
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/config_1_1_1470722888.data
  53. 1 0
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/config_2_1_1470363686.data
  54. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/dash.data
  55. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/dash_cd.data
  56. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/dash_tq.data
  57. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_11_12_1488521704.data
  58. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_1_12_1498048291.data
  59. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_26_10_1476066932.data
  60. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_27_10_1475031813.data
  61. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_2_12_1498048312.data
  62. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_3_12_1498048330.data
  63. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_4_12_1488521409.data
  64. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_50_10_1470645645.data
  65. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_5_12_1488354051.data
  66. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_6_12_1497253591.data
  67. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_7_12_1497253551.data
  68. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_8_12_1498048348.data
  69. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_9_10_1476066932.data
  70. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/lineround.data
  71. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/roadarrow.data
  72. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/search_scenic_icon.data
  73. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_100_10_1497254453.data
  74. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_10_10_1472718686.data
  75. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_12_10_1467006104.data
  76. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_13_10_1497252546.data
  77. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_14_10_1497252572.data
  78. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_15_10_1497583771.data
  79. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_17_10_1488360312.data
  80. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_1_10_1498047646.data
  81. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_30_10_1498047712.data
  82. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_31_10_1498047749.data
  83. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_32_10_1498047781.data
  84. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_33_10_1498047815.data
  85. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_3_10_1497252336.data
  86. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_4_10_1498463093.data
  87. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_50_10_1470645645.data
  88. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_5_10_1498463124.data
  89. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_6_10_1497252523.data
  90. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_8_10_1497252659.data
  91. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tbl.data
  92. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tbl_l.data
  93. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tbl_n.data
  94. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tgl.data
  95. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tgl_l.data
  96. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tgl_n.data
  97. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_amble.data
  98. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_congestion.data
  99. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_null.data
  100. BIN
      ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_severe_congestion.data

+ 13 - 0
.gitignore

@@ -0,0 +1,13 @@
+*.[aod]
+*.DS_Store
+.DS_Store
+*Thumbs.db
+*.iml
+.gradle
+.idea
+node_modules
+npm-debug.log
+/android/build
+/ios/**/*xcuserdata*
+/ios/**/*xcshareddata*
+.tern-*

+ 12 - 0
.npmignore

@@ -0,0 +1,12 @@
+*.[aod]
+*.DS_Store
+.DS_Store
+*Thumbs.db
+*.iml
+.gradle
+.idea
+node_modules
+npm-debug.log
+/android/build
+/ios/**/*xcuserdata*
+/ios/**/*xcshareddata*

+ 289 - 0
AMap-android.js

@@ -0,0 +1,289 @@
+/*
+ * A smart AMap Library for react-native apps
+ * https://github.com/react-native-component/react-native-smart-amap/
+ * Released under the MIT license
+ * Copyright (c) 2016 react-native-component <moonsunfall@aliyun.com>
+ */
+
+import React, {
+    Component,
+} from 'react'
+import {
+    View,
+    requireNativeComponent,
+    NativeModules,
+    findNodeHandle,
+    Platform
+} from 'react-native';
+
+import PropTypes from 'prop-types';
+
+const AMapManager = Platform.OS == 'ios' ? null : NativeModules.AMapModule;
+
+function isFunction(fn) {
+    return typeof fn === 'function';
+}
+
+function safeCallback(callback) {
+    return isFunction(callback) ? callback : function() {};
+}
+
+export default class AMap extends Component {
+    static propTypes = {
+        ...View.propTypes,
+
+        frame: PropTypes.shape({
+            width: PropTypes.number.isRequired,
+            height: PropTypes.number.isRequired,
+        }),
+
+        mapViewType: PropTypes.number,
+        customMapStyleFileName: PropTypes.string,
+        showsUserLocation: PropTypes.bool,
+        mapType: PropTypes.number,
+        zoomLevel: PropTypes.number,
+        centerCoordinate: PropTypes.shape({
+            latitude: PropTypes.number.isRequired,
+            longitude: PropTypes.number.isRequired,
+        }),
+        scaleControls: PropTypes.bool,
+        tiltGestures: PropTypes.bool,
+        rotateGestures: PropTypes.bool,
+
+        infoWindowClass: PropTypes.string,
+        onDidMoveByUser: PropTypes.func,
+        onSingleTapped: PropTypes.func,
+        onLongTapped: PropTypes.func,
+        onMapZoomChange: PropTypes.func,
+        onAnnotationDragChange: PropTypes.func,
+        onAttachedToWindow: PropTypes.func,
+        onAnnotationClick: PropTypes.func,
+        onInfoWindowClick: PropTypes.func,
+        circles: PropTypes.array,
+        markers: PropTypes.array,
+        polygons: PropTypes.array,
+        polylines: PropTypes.array,
+        region: PropTypes.object,
+        bearing: PropTypes.number,
+        tilt: PropTypes.number
+    }
+
+    constructor(props) {
+        super(props)
+        this.state = {}
+    }
+
+    render() {
+        return (
+            <NativeAMap
+                {...this.props}
+            />
+        )
+    }
+
+    printCurrentMapShot(){
+        AMapManager.printCurrentMapShot(findNodeHandle(this));
+    }
+
+    setCenterCoordinate(coordinate) {
+        //console.log('findNodeHandle => ')
+        //console.log(findNodeHandle)
+        AMapManager.setCenterCoordinate(findNodeHandle(this), coordinate)
+    }
+
+    setRegion(region) {
+        AMapManager.setRegion(findNodeHandle(this), region)
+    }
+
+    setRegionByLatLngs(region) {
+        AMapManager.setRegionByLatLngs(findNodeHandle(this), region)
+    }
+
+    setLatLngZoom(config) {
+        AMapManager.setLatLngZoom(findNodeHandle(this), config)
+    }
+
+    setMapType(mapType) {
+        AMapManager.setMapType(findNodeHandle(this), mapType)
+    }
+
+    movieToUserLocation() {
+        AMapManager.movieToUserLocation(findNodeHandle(this))
+    }
+
+    setZoomLevel(zoomLevel) {
+        AMapManager.setZoomLevel(findNodeHandle(this), zoomLevel)
+    }
+
+    zoomLevel(callback) {
+        AMapManager.zoomLevel(findNodeHandle(this), safeCallback(callback))
+    }
+
+    minZoomLevel(callback) {
+        AMapManager.minZoomLevel(findNodeHandle(this), safeCallback(callback))
+    }
+
+    maxZoomLevel(callback) {
+        AMapManager.maxZoomLevel(findNodeHandle(this), safeCallback(callback))
+    }
+
+    addAnnotation(annotationConfig, callback) {
+        AMapManager.addAnnotation(findNodeHandle(this), annotationConfig, safeCallback(callback))
+    }
+
+    addAnnotations(annotationConfigs, callback) {
+        AMapManager.addAnnotations(findNodeHandle(this), annotationConfigs, safeCallback(callback))
+    }
+
+    removeAnnotation(key) {
+        AMapManager.removeAnnotation(findNodeHandle(this), key)
+    }
+
+    removeAnnotations(keys) {
+        AMapManager.removeAnnotations(findNodeHandle(this), keys)
+    }
+
+    removeAllAnnotations(callback) {
+        AMapManager.removeAllAnnotations(findNodeHandle(this),callback)
+    }
+
+
+    showInfoWindow(key) {
+        AMapManager.showInfoWindow(findNodeHandle(this), key)
+    }
+
+    hideInfoWindow(key) {
+        AMapManager.hideInfoWindow(findNodeHandle(this), key)
+    }
+
+    showAnnotation(key) {
+        AMapManager.showAnnotation(findNodeHandle(this), key)
+    }
+
+    hideAnnotation(key) {
+        AMapManager.hideAnnotation(findNodeHandle(this), key)
+    }
+
+    showAnnotations(keys) {
+        AMapManager.showAnnotations(findNodeHandle(this), keys)
+    }
+
+    hideAnnotations(keys) {
+        AMapManager.hideAnnotations(findNodeHandle(this), keys)
+    }
+
+    addCircle(circleConfig, callback) {
+        AMapManager.addCircle(findNodeHandle(this), circleConfig, safeCallback(callback))
+    }
+
+    addCircles(circleConfigs, callback) {
+        AMapManager.addCircles(findNodeHandle(this), circleConfigs, safeCallback(callback))
+    }
+
+    removeCircle(key) {
+        AMapManager.removeCircle(findNodeHandle(this), key)
+    }
+
+    removeCircles(keys) {
+        AMapManager.removeCircles(findNodeHandle(this), keys)
+    }
+
+    removeAllCircles(callback) {
+        AMapManager.removeAllCircles(findNodeHandle(this),callback)
+    }
+
+    addPolyline(polylineConfig, callback) {
+        AMapManager.addPolyline(findNodeHandle(this), polylineConfig, safeCallback(callback))
+    }
+
+    addPolylines(polylineConfigs, callback) {
+        AMapManager.addPolylines(findNodeHandle(this), polylineConfigs, safeCallback(callback))
+    }
+
+    removePolyline(key) {
+        AMapManager.removePolyline(findNodeHandle(this), key)
+    }
+
+    removePolylines(keys) {
+        AMapManager.removePolylines(findNodeHandle(this), keys)
+    }
+
+    removeAllPolylines(callback) {
+        AMapManager.removeAllPolylines(findNodeHandle(this),callback)
+    }
+
+    addPolygon(polygonConfig, callback) {
+        AMapManager.addPolygon(findNodeHandle(this), polygonConfig, safeCallback(callback))
+    }
+
+    addPolygons(polygonConfigs, callback) {
+        AMapManager.addPolygons(findNodeHandle(this), polygonConfigs, safeCallback(callback))
+    }
+
+    removePolygon(key) {
+        AMapManager.removePolygon(findNodeHandle(this), key)
+    }
+
+    removePolygons(keys) {
+        AMapManager.removePolygons(findNodeHandle(this), keys)
+    }
+
+    removeAllPolygons(callback) {
+        AMapManager.removeAllPolygons(findNodeHandle(this),callback)
+    }
+
+
+    _Onsingletapped(event) {
+        if (!this.props.onSingleTapped) {
+            return;
+        }
+        this.props.onSingleTapped(event);
+    }
+
+    _onMapZoomChange(event) {
+        if (!this.props.onMapZoomChange) {
+            return;
+        }
+
+        this.props.onMapZoomChange(event);
+    }
+
+    _onAnnotationDragChange(event) {
+        if (!this.props.onAnnotationDragChange) {
+            return;
+        }
+
+        this.props.onAnnotationDragChange(event);
+    }
+
+    setBearing(degree){
+        AMapManager.setBearing(findNodeHandle(this),degree);
+    }
+
+    setTilt(degree){
+        AMapManager.setTilt(findNodeHandle(this),degree);
+    }
+}
+
+export let AMapUtilityAndroid= {
+    isLinesInCircle(center, radius, lines, callback) {
+        AMapManager.isLinesInCircle(center, radius, lines, safeCallback(callback));
+    }
+}
+
+export let AMapSearchAndroid= {
+    searchPoiByCenterCoordinate(params) {
+        AMapManager.searchPoiByCenterCoordinate(params) //传null为默认参数配置
+    },
+    searchPoiByUid(uid, callback) {
+        AMapManager.searchPoiByUid(uid, safeCallback(callback));
+    },
+
+    reGoecodeSearch(params) {
+        AMapManager.reGoecodeSearch(params)
+    },
+    OnPOISearchDoneEvent: AMapManager != null ? AMapManager.OnPOISearchDoneEvent : null,
+    OnReGeocodeSearchDoneEvent: AMapManager != null ? AMapManager.OnReGeocodeSearchDoneEvent : null
+}
+
+const NativeAMap = Platform.OS == 'ios' ? View : requireNativeComponent('RCTAMapView', AMap);

+ 218 - 0
AMap-ios.js

@@ -0,0 +1,218 @@
+/*
+ * A smart AMap Library for react-native apps
+ * https://github.com/react-native-component/react-native-smart-amap/
+ * Released under the MIT license
+ * Copyright (c) 2016 react-native-component <moonsunfall@aliyun.com>
+ */
+
+import React, {
+    Component,
+} from 'react'
+import {
+    View,
+    requireNativeComponent,
+    NativeModules,
+    findNodeHandle,
+    Platform,
+    Event
+} from 'react-native';
+
+import PropTypes from 'prop-types';
+
+const AMapManager = Platform.OS == 'ios' ? NativeModules.AMap : null
+function isFunction(fn) {
+	return typeof fn === 'function';
+}
+
+function safeCallback(callback) {
+	return isFunction(callback) ? callback : function() {};
+}
+
+export default  class AMap extends Component {
+    static propTypes = {
+        mapType: PropTypes.number,
+        showsUserLocation: PropTypes.bool,
+        bearing: PropTypes.number,
+        tilt: PropTypes.number,
+        centerCoordinate: PropTypes.shape({
+            latitude: PropTypes.number,
+            longitude: PropTypes.number
+        }),
+        mapViewType: PropTypes.number,
+        customMapStyleFileName: PropTypes.string,
+        frame: PropTypes.shape({
+            width: PropTypes.number,
+            height: PropTypes.number
+        }).isRequired,
+        zoomLevel: PropTypes.number,
+        onDidMoveByUser: PropTypes.func,
+        onSingleTapped: PropTypes.func,
+        onLongTapped: PropTypes.func,
+        onMapZoomChange: PropTypes.func,
+        onAnnotationDragChange: PropTypes.func,
+        onAnnotationClick: PropTypes.func,
+
+        circles: PropTypes.array,
+        markers: PropTypes.array,
+        polygons: PropTypes.array,
+        polylines: PropTypes.array,
+        region: PropTypes.object
+    }
+
+    constructor(props) {
+        super(props)
+        this.state = {}
+    }
+
+    render() {
+        return (
+            <NativeAMap
+                {...this.props}
+            />
+        )
+    }
+
+    setCenterCoordinate(coordinate) {
+        AMapManager.setCenterCoordinate(findNodeHandle(this), coordinate)
+    }
+
+    setRegion(region) {
+        AMapManager.setRegion(findNodeHandle(this), region)
+    }
+
+    setRegionByLatLngs(region) {
+        AMapManager.setRegionByLatLngs(findNodeHandle(this), region)
+    }
+
+    movieToUserLocation() {
+        AMapManager.movieToUserLocation(findNodeHandle(this))
+    }
+    
+    setBearing(degree) {
+        AMapManager.setBearing(findNodeHandle(this), degree);
+    }
+
+    setTilt(degree) {
+        AMapManager.setTilt(findNodeHandle(this), degree);
+    }
+
+    zoomLevel(callback) {
+        AMapManager.zoomLevel(findNodeHandle(this), safeCallback(callback))
+    }
+
+    minZoomLevel(callback) {
+        AMapManager.minZoomLevel(findNodeHandle(this), safeCallback(callback))
+    }
+
+    maxZoomLevel(callback) {
+        AMapManager.maxZoomLevel(findNodeHandle(this), safeCallback(callback))
+    }
+
+    addAnnotation(annotationConfig, callback) {
+        AMapManager.addAnnotation(findNodeHandle(this), annotationConfig, safeCallback(callback))
+    }
+
+    addAnnotations(annotationConfigs, callback) {
+        AMapManager.addAnnotations(findNodeHandle(this), annotationConfigs, safeCallback(callback))
+    }
+
+    removeAnnotation(key) {
+        AMapManager.removeAnnotation(findNodeHandle(this), key)
+    }
+
+    removeAnnotations(keys) {
+        AMapManager.removeAnnotations(findNodeHandle(this), keys)
+    }
+
+    removeAllAnnotations(callback) {
+        AMapManager.removeAllAnnotations(findNodeHandle(this), safeCallback(callback))
+    }
+
+    addCircle(circleConfig, callback) {
+        AMapManager.addCircle(findNodeHandle(this), circleConfig, safeCallback(callback))
+    }
+
+    addCircles(circleConfigs, callback) {
+        AMapManager.addCircles(findNodeHandle(this), circleConfigs, safeCallback(callback))
+    }
+
+    removeCircle(key) {
+        AMapManager.removeCircle(findNodeHandle(this), key)
+    }
+
+    removeCircles(keys) {
+        AMapManager.removeCircles(findNodeHandle(this), keys)
+    }
+
+    removeAllCircles(callback) {
+        AMapManager.removeAllCircles(findNodeHandle(this), safeCallback(callback))
+    }
+
+    addPolyline(polylineConfig, callback) {
+        AMapManager.addPolyline(findNodeHandle(this), polylineConfig, safeCallback(callback))
+    }
+
+    addPolylines(polylineConfigs, callback) {
+        AMapManager.addPolylines(findNodeHandle(this), polylineConfigs, safeCallback(callback))
+    }
+
+    removePolyline(key) {
+        AMapManager.removePolyline(findNodeHandle(this), key)
+    }
+
+    removePolylines(keys) {
+        AMapManager.removePolylines(findNodeHandle(this), keys)
+    }
+
+    removeAllPolylines(callback) {
+        AMapManager.removeAllPolylines(findNodeHandle(this), safeCallback(callback))
+    }
+
+    addPolygon(polygonConfig, callback) {
+        AMapManager.addPolygon(findNodeHandle(this), polygonConfig, safeCallback(callback))
+    }
+
+    addPolygons(polygonConfigs, callback) {
+        AMapManager.addPolygons(findNodeHandle(this), polygonConfigs, safeCallback(callback))
+    }
+
+    removePolygon(key) {
+        AMapManager.removePolygon(findNodeHandle(this), key)
+    }
+
+    removePolygons(keys) {
+        AMapManager.removePolygons(findNodeHandle(this), keys)
+    }
+
+    removeAllPolygons(callback) {
+        AMapManager.removeAllPolygons(findNodeHandle(this), safeCallback(callback))
+    }
+}
+ 
+
+export  let AMapUtilityIOS  = {
+    isLinesInCircle(center, radius, lines, callback) {
+        AMapManager.isLinesInCircle(center, radius, lines, safeCallback(callback));
+    }
+}
+
+export let AMapSearchIOS = {
+    searchPoiByCenterCoordinate(params) {
+        AMapManager.searchPoiByCenterCoordinate(params) //传null为默认参数配置
+    },
+
+    searchPoiByUid(uid) {
+        AMapManager.searchPoiByUid(uid)
+    },
+
+    reGoecodeSearch(params) {
+        AMapManager.reGoecodeSearch(params)
+    },
+
+    OnPOISearchDoneEvent: AMapManager != null ? AMapManager.OnPOISearchDoneEvent : null,
+    OnReGeocodeSearchDoneEvent: AMapManager != null ? AMapManager.OnReGeocodeSearchDoneEvent : null
+}
+
+
+
+const NativeAMap = Platform.OS == 'ios' ? requireNativeComponent('RCTAMap', AMap) : View

+ 31 - 0
AMap.js

@@ -0,0 +1,31 @@
+/*
+ * A smart AMap Library for react-native apps
+ * https://github.com/react-native-component/react-native-smart-amap/
+ * Released under the MIT license
+ * Copyright (c) 2016 react-native-component <moonsunfall@aliyun.com>
+ */
+
+import {
+    Platform
+} from 'react-native';
+
+import AndroidAMap, {AMapUtilityAndroid, AMapSearchAndroid} from './AMap-android';
+import IOSAMap, {AMapUtilityIOS, AMapSearchIOS} from './AMap-ios';
+
+let AMap;
+let AMapUtility;
+let AMapSearch;
+
+if(Platform.OS == 'ios') {
+    AMap = IOSAMap;
+    AMapUtility = AMapUtilityIOS;
+    AMapSearch = AMapSearchIOS;
+}
+else {
+    AMap = AndroidAMap;
+    AMapUtility = AMapUtilityAndroid;
+    AMapSearch = AMapSearchAndroid;
+}
+
+export default AMap;
+export {AMapUtility, AMapSearch};

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 488 - 0
README.md

@@ -0,0 +1,488 @@
+# react-native-smart-amap
+A AMap Library for React Native apps.
+
+[![npm](https://img.shields.io/npm/v/react-native-smart-amap.svg)](https://www.npmjs.com/package/react-native-smart-amap)
+[![npm](https://img.shields.io/npm/dm/react-native-smart-amap.svg)](https://www.npmjs.com/package/react-native-smart-amap)
+[![npm](https://img.shields.io/npm/dt/react-native-smart-amap.svg)](https://www.npmjs.com/package/react-native-smart-amap)
+[![npm](https://img.shields.io/npm/l/react-native-smart-amap.svg)](https://github.com/react-native-component/react-native-smart-amap/blob/master/LICENSE)
+
+react-native 高德地图SDK 插件, 支持ios与android,
+关于使用高德地图SDK, 申请应用key等详细信息请点击[这里][1]
+
+Mac下Android Studio中获取SHA1和MD5请点击[这里][3]
+
+## 预览
+
+![react-native-smart-amap-preview-ios][2]
+
+## 安装
+
+```
+npm install react-native-smart-amap --save
+```
+
+## Notice
+
+这个版本仅支持react-native 0.40及以上, 如果你想使用旧版本,使用`npm install react-native-smart-amap@untilRN0.40 --save`
+
+
+## 安装 (iOS)
+
+* 将RCTAMap.xcodeproj作为Library拖进你的Xcode里的project中.
+
+* 将RCTAMap目录里Frameworks目录拖进主project目录下, 选择copy items if needed, create groups, 另外add to target不要忘记选择主project.
+
+* 将RCTAMap目录里Frameworks目录里的AMap.bundle拖进主project目录下, 选择copy items if needed, create groups, 另外add to target不要忘记选择主project.
+
+* 点击你的主project, 选择Build Phases -> Link Binary With Libraries, 将RCTAMap.xcodeproj里Product目录下的libRCTAMap.a拖进去.
+
+* 同上位置, 选择Add items, 将系统库libstdc++.6.0.9.tbd加入.
+
+* 同上位置, 选择Add items, 将系统库libc++.tbd加入.
+
+* 同上位置, 选择Add items, 将系统库libz.tbd加入.
+
+* 同上位置, 选择Add items, 将系统库Security.framework加入.
+
+* 同上位置, 选择Add items, 将系统库CoreTelephony.framework加入.
+
+* 同上位置, 选择Add items, 将系统库SystemConfiguration.framework加入.
+
+* 同上位置, 选择Add items, 将系统库JavaScriptCore.framework加入.
+
+* 同上位置, 选择Add items, 将系统库CoreLocation.framework加入.
+
+* 选择Build Settings, 找到Header Search Paths, 确认其中包含$(SRCROOT)/../../../react-native/React, 模式为recursive.
+
+* 同上位置, 找到Framework Search Paths, 加入$(PROJECT_DIR)/Frameworks.
+
+* 点击在Libraries下已拖进来的RCTAMap.xcodeproj, 选择Build Settings, 找到Framework Search Paths, 将$(SRCROOT)/../../../ios/Frameworks替换成$(SRCROOT)/../../../../ios/Frameworks.
+
+* 在`info.plist`中加入`Privacy - Location When In Use Usage Description`属性(ios 10)
+
+* 在`info.plist`中加入`Allow Arbitrary Loads`属性, 并设置值为YES(ios 10)
+
+* 在`AppDelegate.m`中
+
+```
+
+...
+#import <AMapFoundationKit/AMapFoundationKit.h> //引入高德地图核心包
+...
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+
+  [AMapServices sharedServices].apiKey = @"请填写您的key"; //设置高德地图SDK服务key
+  ...
+}
+...
+
+```
+
+## 安装 (Android)
+
+* 在`android/settings.gradle`中
+
+```
+...
+include ':react-native-smart-amap'
+project(':react-native-smart-amap').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-smart-amap/android')
+```
+
+* 在`android/app/build.gradle`中
+
+```
+...
+dependencies {
+    ...
+    // From node_modules
+    compile project(':react-native-smart-amap')
+}
+```
+
+* 在`MainApplication.java`中
+
+```
+...
+import com.reactnativecomponent.amaplocation.RCTAMapPackage;    //import package
+...
+/**
+ * A list of packages used by the app. If the app uses additional views
+ * or modules besides the default ones, add more packages here.
+ */
+@Override
+protected List<ReactPackage> getPackages() {
+    return Arrays.<ReactPackage>asList(
+        new MainReactPackage(),
+        new RCTAMapPackage()  //register Module
+    );
+}
+...
+
+```
+
+* 在`AndroidManifest.xml`中, 加入所需权限
+
+```
+
+...
+ <!--*************************高德地图-定位所需要权限*************************-->
+    <!-- Normal Permissions 不需要运行时注册 -->
+    <!--获取运营商信息,用于支持提供运营商信息相关的接口-->
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <!--这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+
+    <!-- 请求网络 -->
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <!-- 不是SDK需要的权限,是示例中的后台唤醒定位需要的权限 -->
+    <!--<uses-permission android:name="android.permission.WAKE_LOCK" />-->
+
+    <!-- 需要运行时注册的权限 -->
+    <!--用于进行网络定位-->
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <!--用于访问GPS定位-->
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <!--用于提高GPS定位速度-->
+    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
+    <!--写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据-->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <!--读取缓存数据-->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+    <!--用于读取手机当前的状态-->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
+    <!-- 更改设置 -->
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+<!--*************************高德地图-定位所需要权限*************************-->
+...
+
+```
+
+* 在`AndroidManifest.xml`中, application标签内加入
+
+```
+
+...
+    <!--高德地图SDK key设置-->
+    <meta-data
+        android:name="com.amap.api.v2.apikey"
+        android:value="请填写您的key"/>
+    <!--高德地图APS服务设置-->
+    <service android:name="com.amap.api.location.APSService" >
+    </service>
+...
+
+```
+
+## 完整示例
+
+点击这里 [ReactNativeComponentDemos][0]
+
+## 使用简介
+
+Install the package from npm with `npm install react-native-smart-amap --save`.
+Then, require it from your app's JavaScript files with `import Barcode from 'react-native-smart-amap'`.
+
+```js
+import React, {
+    Component,
+} from 'react'
+import {
+    StyleSheet,
+    View,
+    Text,
+    Image,
+    NativeAppEventEmitter,
+    TouchableHighlight,
+    ListView,
+    Dimensions,
+    Alert,
+    Platform,
+} from 'react-native'
+
+import AMapLocation from 'react-native-smart-amap-location'
+import AMap from 'react-native-smart-amap'
+import Button from 'react-native-smart-button'
+import AppEventListenerEnhance from 'react-native-smart-app-event-listener-enhance'
+import PullToRefreshListView from 'react-native-smart-pull-to-refresh-listview'
+import TimerEnhance from 'react-native-smart-timer-enhance'
+import AMapALoneNearByList from './amp-alone-nearby-list'
+import ListViewActivityIndicator from './ListViewActivityIndicator'
+
+const {width: deviceWidth, height: deviceHeight} = Dimensions.get('window')
+
+class AMapDemo extends Component {
+
+    constructor(props) {
+        super(props);
+
+        this._amap = null
+        this._page = 0
+        this._coordinate = this.props.navigator.navigationContext._currentRoute.coordinate
+        console.log(`this._coordinate -> `)
+        console.log(this._coordinate)
+        this._keywords = '商务住宅|学校'
+        this._onDidMoveByUserTimer = null
+    }
+
+    componentDidMount() {
+        this.addAppEventListener(
+            NativeAppEventEmitter.addListener('amap.location.onLocationResult', this._onLocationResult),
+            NativeAppEventEmitter.addListener('amap.onPOISearchDone', this._onPOISearchDone)
+            //NativeAppEventEmitter.addListener('amap.onPOISearchFailed', this._onPOISearchFailed)
+        )
+    }
+
+    render () {
+        //console.log(`amap-alone render...`)
+        return (
+                <View style={{marginTop: (Platform.OS == 'ios' ? 20 + 44 : 56), flex: 1, }}>
+                    <View style={{position: 'relative', height: (deviceHeight - (Platform.OS == 'ios' ? 64 : 56)) - 50 * 5,}}>
+                        <AMap
+                        ref={ component => this._amap = component }
+                        style={{flex: 1, }}
+                        options={{
+                            frame: {
+                                width: deviceWidth,
+                                height: (deviceHeight - 64) - 50 * 5
+                            },
+                            showsUserLocation: false,
+                            userTrackingMode: Platform.OS == 'ios' ? AMap.constants.userTrackingMode.none : null,
+                            centerCoordinate: {
+                                latitude: this._coordinate.latitude,
+                                longitude: this._coordinate.longitude,
+                            },
+                            zoomLevel: 18.1,
+                            centerMarker: Platform.OS == 'ios' ? 'icon_location' : 'poi_marker',
+                        }}
+                        onLayout={this._onLayout}
+                        onDidMoveByUser={this._onDidMoveByUser}
+                        />
+                        <Button
+                            touchableType={Button.constants.touchableTypes.highlight}
+                            underlayColor={'#ccc'}
+                            style={{padding: 5, position: 'absolute', left: 10, bottom: 20, backgroundColor: '#fff', justifyContent: 'center', borderRadius: 3, borderWidth: StyleSheet.hairlineWidth, borderColor: '#ffffff', justifyContent: 'center', }}
+                            onPress={ () => {
+                                AMapLocation.init(null)
+                                AMapLocation.getLocation()
+                                //this._activityIndicator.setState({ visible: true,})
+                            }}>
+                            <Image source={{uri: Platform.OS == 'ios' ? 'gpsStat1' : 'gps_stat1'}} style={{width: 28, height: 28,}}/>
+                        </Button>
+                   </View>
+                    <View style={{flex: 1, position: 'relative',}}>
+                        <AMapALoneNearByList
+                            ref={ (component) => this._amapALoneNearByList = component }
+                            onRefresh={this._onRefresh}
+                            onLoadMore={this._onLoadMore}
+                        />
+                        <ListViewActivityIndicator
+                            ref={ (component) => this._activityIndicator = component }
+                            style={{marginRight: 10, position:'absolute', left: (deviceWidth - 20) / 2, top: (50 * 5 - 20) / 2, }}
+                            color={'#a9a9a9'}/>
+                    </View>
+                </View>
+        )
+    }
+
+    _onDidMoveByUser = (e) => {
+        //console.log(`_onDidMoveByUser....`)
+        if(this._onDidMoveByUserTimer) {
+            this.clearTimeout(this._onDidMoveByUserTimer)
+            this._onDidMoveByUserTimer = null
+        }
+        let { longitude, latitude, } = e.nativeEvent.data.centerCoordinate
+        this._onDidMoveByUserTimer = this.setTimeout( ()=> {
+            let {refresh_none, refresh_idle, load_more_none, load_more_idle, loaded_all,} = PullToRefreshListView.constants.viewState
+            if((this._amapALoneNearByList._pullToRefreshListView._refreshState == refresh_none || this._amapALoneNearByList._pullToRefreshListView._refreshState == refresh_idle)
+                && (this._amapALoneNearByList._pullToRefreshListView._loadMoreState == load_more_none
+                || this._amapALoneNearByList._pullToRefreshListView._loadMoreState == load_more_idle
+                || this._amapALoneNearByList._pullToRefreshListView._loadMoreState == loaded_all)) {
+                console.log(`beginRefresh(true)....`)
+                this._coordinate = {
+                    longitude,
+                    latitude,
+                }
+                this._activityIndicator.setState({ visible: true,})
+                this._amapALoneNearByList._pullToRefreshListView._scrollView.scrollTo({ y: 0, animated: false, })
+                this._amapALoneNearByList._pullToRefreshListView.beginRefresh(true)
+                //this._amapALoneNearByList._pullToRefreshListView.beginRefresh()
+                this._beginRefresh = true
+            }
+        }, 300)
+    }
+
+    _onLocationResult = (result) => {
+        if(result.error) {
+            console.log(`map-错误代码: ${result.error.code}, map-错误信息: ${result.error.localizedDescription}`)
+        }
+        else {
+            if(result.formattedAddress) {
+                console.log(`map-格式化地址 = ${result.formattedAddress}`)
+            }
+            else {
+                console.log(`map-纬度 = ${result.coordinate.latitude}, map-经度 = ${result.coordinate.longitude}`)
+                this._coordinate = {
+                    latitude: result.coordinate.latitude,
+                    longitude: result.coordinate.longitude,
+                }
+                this._amap.setOptions({
+                    zoomLevel: 18.1,
+                })
+                this._amap.setCenterCoordinate(this._coordinate)
+            }
+        }
+    }
+
+    //_onPOISearchFailed = (e) => {
+    //    //console.log(`_onPOISearchFailed...`)
+    //    //console.log(e)
+    //    //console.log(e.error)
+    //    this._page--;
+    //}
+
+    _onPOISearchDone = (result) => {
+        console.log(`_onPOISearchDone...`)
+
+        if(Platform.OS == 'ios') {
+            this._endSearch(result)
+        }
+        else {
+            this.setTimeout( () => {
+                this._endSearch(result)
+            }, 255)
+        }
+    }
+
+    _endSearch = (result) => {
+        let { searchResultList, error } = result
+
+        console.log(result.error)
+
+        if(error) {
+            if(this._page == 1) {
+                this._page--
+                this._amapALoneNearByList._pullToRefreshListView.endRefresh(this._beginRefresh)
+                //this._amapALoneNearByList._pullToRefreshListView.endRefresh()
+                this._beginRefresh = false
+                this._activityIndicator.setState({ visible: false,})
+            }
+            else {
+                this._amapALoneNearByList._pullToRefreshListView.endLoadMore(false)
+            }
+            return
+        }
+
+        console.log(`this._page = ${this._page}`)
+
+        //onRefresh
+        if(this._page == 1) {
+            this._amapALoneNearByList.setState({
+                dataList: searchResultList,
+                dataSource: this._amapALoneNearByList._dataSource.cloneWithRows(searchResultList),
+            })
+            this._amapALoneNearByList._pullToRefreshListView.endRefresh(this._beginRefresh)
+            //this._amapALoneNearByList._pullToRefreshListView.endRefresh()
+            this._beginRefresh = false
+            this._activityIndicator.setState({ visible: false,})
+        }
+        //onLoadMore
+        else {
+            let newDataList = this._amapALoneNearByList.state.dataList.concat(searchResultList)
+            this._amapALoneNearByList.setState({
+                dataList: newDataList,
+                dataSource: this._amapALoneNearByList._dataSource.cloneWithRows(newDataList),
+            })
+            let loadedAll
+            if(searchResultList.length == 100) {
+                loadedAll = true
+                this._amapALoneNearByList._pullToRefreshListView.endLoadMore(loadedAll)
+            }
+            else {
+                loadedAll = false
+                this._amapALoneNearByList._pullToRefreshListView.endLoadMore(loadedAll)
+            }
+        }
+    }
+
+    _searchNearBy = (searchParams)=> {
+        this._amap.searchPoiByCenterCoordinate(searchParams)
+    }
+
+    _onRefresh = () => {
+        console.log(`outer _onRefresh...`)
+        this._searchNearBy({
+            page: (this._page = 1),
+            coordinate: this._coordinate,
+            keywords: this._keywords,
+        })
+    }
+
+    _onLoadMore = () => {
+        console.log(`outer _onLoadMore...`)
+        this._searchNearBy({
+            page: ++this._page,
+            coordinate: this._coordinate,
+            keywords: this._keywords,
+        })
+    }
+
+}
+
+export default TimerEnhance(AppEventListenerEnhance(AMapDemo))
+```
+
+## 属性
+
+Prop                        | Type   | Optional | Default   | Description
+--------------------------- | ------ | -------- | --------- | -----------
+options                     | object | No       |           | 地图参数对象
+options.frame               | object | No       |           | ios设置地图宽(width), 高(height), 类型是number
+options.showTraffic         | bool   | Yes      |           | ios设置是否显示路况, 默认不显示
+options.showsUserLocation   | bool   | Yes      |           | ios设置是否显示用户位置,默认显示
+options.userTrackingMode    | bool   | Yes      |           | ios设置追踪用户位置更新的模式,默认不追踪
+options.zoomLevel           | number | Yes      |           | 指定缩放级别, 默认为最大级别
+options.centerCoordinate    | object | Yes      |           | 根据经度(latitude)纬度(longitude)指定地图的中心点, 类型是number
+options.centerMarker        | string | Yes      |           | 设置中心点自定义图标的项目资源名称, 如为空则不显示中心点图标
+
+## 方法
+
+* setOptions
+  * 描述: 更改地图参数
+  * 参数: reactTag 类型: number, 地图的native view id, 根据这个id可以获取到地图的实例
+  * 参数: options  类型: object, 地图参数, 数据结构同上Props中的options
+
+* setCenterCoordinate
+  * 描述: 根据经纬度在地图中心位置显示
+  * 参数: reactTag 类型: number, 地图的native view id, 根据这个id可以获取到地图的实例
+  * 参数: coordinate  类型: object, 经纬度坐标参数, 数据结构同上Props中的options.centerCoordinate
+
+* searchPoiByCenterCoordinate
+  * 描述: 根据经纬度坐标来搜索周边的POI
+  * 参数: params  类型: object, 搜索参数, 数据结构如下:
+        * types 类型: string 表示搜索类型,多个类型用“|”分割 可选值:文本分类、分类代码
+        * sortrule 类型: number 表示排序规则, 0-距离排序;1-综合排序, 默认1
+        * offset 类型: number 表示每页记录数, 范围1-50, 默认20
+        * page 类型: number 表示当前页数, 范围1-100, 默认1
+        * keywords 类型: string 表示查询关键字,多个关键字用“|”分割
+        * coordinate 类型: object 表示中心点经纬度, 数据结构同上Props中的options.centerCoordinate
+        * radius 类型: int 表示辐射半径, 默认3000米
+
+## 事件监听
+
+* 地图事件: onDidMoveByUser
+    * 描述: 监听用户动作, 返回当前地图中心点的经纬度信息
+
+* 全局事件: amap.onPOISearchDone
+    * 描述: 监听POI搜索回调, 返回周边的POI信息
+
+[0]: https://github.com/cyqresig/ReactNativeComponentDemos
+[1]: http://lbs.amap.com/api/
+[2]: http://cyqresig.github.io/img/react-native-smart-amap-preview-ios-v1.0.0.gif
+[3]: http://blog.csdn.net/jackymvc/article/details/50222503

BIN
android/AMapResources/gpsStat1@2x.png


BIN
android/AMapResources/gps_stat1.png


BIN
android/AMapResources/icon_location.png


BIN
android/AMapResources/icon_location@2x.png


BIN
android/AMapResources/icon_location@3x.png


BIN
android/AMapResources/poi_marker.png


+ 30 - 0
android/build.gradle

@@ -0,0 +1,30 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 23
+    buildToolsVersion "23.0.3"
+
+    defaultConfig {
+        minSdkVersion 16
+        targetSdkVersion 23
+        versionCode 1
+        versionName "1.0"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(include: ['*.jar'], dir: 'libs')
+    compile 'com.android.support:appcompat-v7:23.4.0'
+    compile 'com.facebook.react:react-native:+'
+
+    // version from maven https://search.maven.org/#search%7Cga%7C1%7Ccom.amap.api
+    compile 'com.amap.api:3dmap:5.7.0' //3d 地图
+    compile 'com.amap.api:location:3.5.0' //定位
+    compile 'com.amap.api:search:5.3.1' //搜索
+}

+ 17 - 0
android/proguard-rules.pro

@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/cyqresig/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

+ 3 - 0
android/src/main/AndroidManifest.xml

@@ -0,0 +1,3 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.reactnativecomponent.amap">
+</manifest>

+ 22 - 0
android/src/main/java/com/reactnativecomponent/amap/AMAPInfoWindowAdapter.java

@@ -0,0 +1,22 @@
+package com.reactnativecomponent.amap;
+
+import android.view.View;
+
+import com.amap.api.maps.model.Marker;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReadableMap;
+
+/**
+ * Created by wd on 13/09/2017.
+ */
+
+public abstract class AMAPInfoWindowAdapter {
+    public final ReactContext mContext;
+
+    public AMAPInfoWindowAdapter(ReactContext context) {
+        this.mContext = context;
+    }
+
+    abstract public View getInfoWindow(Marker marker, ReadableMap config);
+    abstract public void removeInfoWindow(String key);
+}

+ 14 - 0
android/src/main/java/com/reactnativecomponent/amap/BaseCustomView.java

@@ -0,0 +1,14 @@
+package com.reactnativecomponent.amap;
+
+
+import android.content.Context;
+import android.widget.LinearLayout;
+
+import java.util.HashMap;
+
+public abstract class BaseCustomView extends LinearLayout {
+    public BaseCustomView(Context context) {
+        super(context);
+    }
+    public abstract HashMap<String,Float> getOffset();
+}

+ 5 - 0
android/src/main/java/com/reactnativecomponent/amap/CustomViewMarkerInterface.java

@@ -0,0 +1,5 @@
+package com.reactnativecomponent.amap;
+
+
+public interface CustomViewMarkerInterface {
+}

+ 83 - 0
android/src/main/java/com/reactnativecomponent/amap/HaversineAlgorithm.java

@@ -0,0 +1,83 @@
+package com.reactnativecomponent.amap;
+
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.bridge.WritableMap;
+
+/**
+ * Created by wd on 10/08/2017.
+ * code from: https://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates
+ * and https://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates
+ */
+
+public class HaversineAlgorithm {
+
+    private static final double _eQuatorialEarthRadius = 6378.1370D;
+    private static final double _d2r = (Math.PI / 180D);
+
+    public static int HaversineInM(double lat1, double long1, double lat2, double long2) {
+        return (int) (1000D * HaversineInKM(lat1, long1, lat2, long2));
+    }
+
+    public static double HaversineInKM(double lat1, double long1, double lat2, double long2) {
+        double dlong = (long2 - long1) * _d2r;
+        double dlat = (lat2 - lat1) * _d2r;
+        double a = Math.pow(Math.sin(dlat / 2D), 2D) + Math.cos(lat1 * _d2r) * Math.cos(lat2 * _d2r)
+                * Math.pow(Math.sin(dlong / 2D), 2D);
+        double c = 2D * Math.atan2(Math.sqrt(a), Math.sqrt(1D - a));
+        double d = _eQuatorialEarthRadius * c;
+
+        return d;
+    }
+
+    public static WritableMap gpsToCartesian(double lat, double lng) {
+        double x = _eQuatorialEarthRadius * Math.cos(lat * _d2r) * Math.cos(lng * _d2r);
+        double y = _eQuatorialEarthRadius * Math.cos(lat * _d2r) * Math.sin(lng * _d2r);
+        double z = _eQuatorialEarthRadius * Math.sin(lat * _d2r);
+
+        WritableMap ret = Arguments.createMap();
+        ret.putDouble("x", x);
+        ret.putDouble("y", y);
+        ret.putDouble("z", z);
+        return ret;
+    }
+
+    public static WritableMap cartesianToGPS(double x, double y, double z) {
+        double lat = Math.asin(z/_eQuatorialEarthRadius)/_d2r;
+        double lng= Math.atan2(y, x)/_d2r;
+
+        WritableMap ret = Arguments.createMap();
+        ret.putDouble("latitude", lat);
+        ret.putDouble("longitude", lng);
+        return ret;
+    }
+
+    public static ReadableMap WGS84toGoogleBing(double lat, double lng) {
+        double x = lng * 20037508.34 / 180;
+        double y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
+        y = y * 20037508.34 / 180;
+
+        WritableMap ret = Arguments.createMap();
+        ret.putDouble("x", x);
+        ret.putDouble("y", y);
+        return ret;
+    }
+
+    public static ReadableMap GoogleBingtoWGS84Mercator (double x, double y) {
+        double lng = (x / 20037508.34) * 180;
+        double lat = (y / 20037508.34) * 180;
+
+        lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
+        WritableMap ret = Arguments.createMap();
+        ret.putDouble("latitude", lat);
+        ret.putDouble("longitude", lng);
+        return ret;
+    }
+
+    public static ReadableMap addDistanceToGPS(double lat, double lng, double xSpan, double ySpan) {
+        ReadableMap xy = WGS84toGoogleBing(lat, lng);
+        ReadableMap gps = GoogleBingtoWGS84Mercator(xy.getDouble("x") + xSpan, xy.getDouble("y") + ySpan);
+        return gps;
+    }
+
+}

+ 211 - 0
android/src/main/java/com/reactnativecomponent/amap/RCTAMapManager.java

@@ -0,0 +1,211 @@
+package com.reactnativecomponent.amap;
+
+
+import android.util.Log;
+import com.amap.api.maps.CameraUpdateFactory;
+import com.amap.api.maps.model.Circle;
+import com.amap.api.maps.model.Marker;
+import com.amap.api.maps.model.Polygon;
+import com.amap.api.maps.model.Polyline;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.common.MapBuilder;
+import com.facebook.react.uimanager.ThemedReactContext;
+import com.facebook.react.uimanager.ViewGroupManager;
+import com.facebook.react.uimanager.annotations.ReactProp;
+import com.reactnativecomponent.amap.util.ShapeHelper;
+import java.util.Map;
+
+
+public class RCTAMapManager extends ViewGroupManager<RCTAMapView> {
+    //    public static final LatLng SHANGHAI = new LatLng(31.238068, 121.501654);// 上海市经纬度
+
+    @Override
+    public String getName() {
+        return "RCTAMapView";
+    }
+
+
+    @Override
+    protected RCTAMapView createViewInstance(ThemedReactContext reactContext) {
+        RCTAMapView mapView = new RCTAMapView(reactContext);
+        Log.d("AMAP", "createViewInstance: new inst");
+        return mapView;
+    }
+
+    // 是否显示用户当前所在位置的蓝点
+    @ReactProp(name="showsUserLocation")
+    public void setShowsUserLocation(RCTAMapView mapView, final boolean showsUserLocation) {
+        if (mapView.isReady()){
+            mapView.setUserLocationMarker(showsUserLocation);
+        }else {
+            mapView.setShowUserLocation(showsUserLocation);
+        }
+    }
+
+    // 设置地图类型
+    @ReactProp(name="mapType")
+    public void setMapType(RCTAMapView mapView, final int mapType) {
+        mapView.setMapType(mapType);
+    }
+
+    // 设置地图视图类型 0 是 MapView 1 是 TextureMapView,默认是 0
+    @ReactProp(name="mapViewType")
+    public void setMapViewType(RCTAMapView mapView, final int mapViewType) {
+        mapView.setMapViewType(mapViewType);
+    }
+
+    // 设置缩放等级
+    @ReactProp(name="zoomLevel")
+    public void setZoomLevel(RCTAMapView mapView, final float zoomLevel) {
+        mapView.setZoomLevel(zoomLevel);
+    }
+
+    // 设置中心点
+    @ReactProp(name="centerCoordinate")
+    public void setCenterCoordinate(RCTAMapView mapView, final ReadableMap centerCoordinate) {
+        Double lat = centerCoordinate.getDouble("latitude");
+        Double lng = centerCoordinate.getDouble("longitude");
+        if ((lat >= -90 && lat <= 90) && (lng >= -180 && lng <= 180))
+            mapView.setCenterLocation(lat, lng);
+    }
+
+    // frame,暂时没用,ios 那边有用,兼容一下
+    @ReactProp(name="frame")
+    public void setFrame(RCTAMapView mapView, ReadableMap frame) {
+    }
+
+    // customMapStylePath
+    @ReactProp(name="customMapStyleFileName")
+    public void setCustomMapStyleFileName(RCTAMapView mapView, String customMapStyleFileName) {
+        mapView.setCustomMapStylePath(customMapStyleFileName);
+    }
+
+    // 设置需要特殊 infoWindow 处理的 class,会通过反射来使用
+    @ReactProp(name="infoWindowClass")
+    public void setInfoWindowClass(RCTAMapView mapView, final String className) {
+        mapView.setInfoWindowClass(className);
+    }
+
+    // 是否允许旋转地图
+    @ReactProp(name="rotateGestures")
+    public void setRotateGestures(RCTAMapView mapView, final boolean rotateGestures) {
+        mapView.setRotateGestures(rotateGestures);
+    }
+
+    // 是否允许倾斜地图
+    @ReactProp(name="tiltGestures")
+    public void setTiltGestures(RCTAMapView mapView, final boolean tiltGestures) {
+        mapView.setTiltGestures(tiltGestures);
+    }
+
+    // 是否显示比例尺
+    @ReactProp(name="scaleControls")
+    public void setScaleControls(RCTAMapView mapView, final boolean scaleControls) {
+        mapView.setScaleControls(scaleControls);
+    }
+
+    @ReactProp(name="circles")
+    public void setCircles(RCTAMapView mapView, ReadableArray circles){
+        if (circles==null)
+            return;
+        ShapeHelper<Circle> circleHelper = mapView.getCircleHelper();
+        if (mapView.isReady()){
+            circleHelper.drawShapes(circles);
+        }else {
+            circleHelper.setDataFromJS(circles);
+        }
+    }
+
+    @ReactProp(name="polygons")
+    public void setPolygons(RCTAMapView mapView, ReadableArray polygons){
+        if (polygons==null)
+            return;
+        ShapeHelper<Polygon> polygonHelper = mapView.getPolygonHelper();
+        if (mapView.isReady()){
+            polygonHelper.drawShapes(polygons);
+        }else {
+           polygonHelper.setDataFromJS(polygons);
+        }
+    }
+
+    @ReactProp(name="polylines")
+    public void setPolylines(RCTAMapView mapView, ReadableArray polylines){
+        if (polylines==null)
+            return;
+        ShapeHelper<Polyline> polylineHelper = mapView.getPolylineHelper();
+        if (mapView.isReady()){
+            polylineHelper.drawShapes(polylines);
+        }else {
+           polylineHelper.setDataFromJS(polylines);
+        }
+    }
+
+
+    @ReactProp(name="markers")
+    public void setMarkers(RCTAMapView mapView, ReadableArray markers){
+        if (markers==null)
+            return;
+        ShapeHelper<Marker> shapeHelper = mapView.getMarkerHelper();
+        if (mapView.isReady()){
+            shapeHelper.drawShapes(markers);
+        }else {
+            shapeHelper.setDataFromJS(markers);
+        }
+    }
+
+    @ReactProp(name="region")
+    public void setRegion(RCTAMapView mapView,ReadableMap region){
+        if (region==null)
+            return;
+        if (mapView.isReady()){
+            if (region.hasKey("radius")){
+                mapView.setRegion(region);
+            }else {
+                mapView.setRegionByLatLngs(region);
+            }
+        }else {
+            mapView.setMapRegion(region);
+        }
+    }
+
+    @ReactProp(name="bearing")
+    public void setBearing(RCTAMapView mapView, float bearing){
+        if (mapView.isReady()){
+            mapView.getAMAP().animateCamera(CameraUpdateFactory.changeBearing(bearing));
+        }else {
+            mapView.setBearing(bearing);
+        }
+    }
+
+    @ReactProp(name="tilt")
+    public void setTilt(RCTAMapView mapView, float tilt){
+        if (mapView.isReady()){
+            mapView.getAMAP().animateCamera(CameraUpdateFactory.changeTilt(tilt));
+        }else {
+            mapView.setTilt(tilt);
+        }
+    }
+
+    @Override
+    protected void addEventEmitters(
+            final ThemedReactContext reactContext,
+            final RCTAMapView view) {
+    }
+
+
+    @Override
+    public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
+        return MapBuilder.<String, Object>builder()
+                .put("onDidMoveByUser", MapBuilder.of("registrationName", "onDidMoveByUser"))//registrationName 后的名字,RN中方法也要是这个名字否则不执行
+                .put("onMapZoomChange", MapBuilder.of("registrationName", "onMapZoomChange"))
+                .put("onSingleTapped", MapBuilder.of("registrationName", "onSingleTapped"))
+                .put("onLongTapped", MapBuilder.of("registrationName", "onLongTapped"))
+                .put("onAnnotationDragChange", MapBuilder.of("registrationName", "onAnnotationDragChange"))
+                .put("onAttachedToWindow", MapBuilder.of("registrationName", "onAttachedToWindow"))
+                .put("onAnnotationClick", MapBuilder.of("registrationName", "onAnnotationClick"))
+                .put("onInfoWindowClick", MapBuilder.of("registrationName", "onInfoWindowClick"))
+                .build();
+    }
+
+}

+ 1037 - 0
android/src/main/java/com/reactnativecomponent/amap/RCTAMapModule.java

@@ -0,0 +1,1037 @@
+package com.reactnativecomponent.amap;
+
+import android.graphics.Bitmap;
+import android.support.v4.print.PrintHelper;
+import android.util.Log;
+
+import com.amap.api.maps.AMap;
+import com.amap.api.maps.CameraUpdate;
+import com.amap.api.maps.CameraUpdateFactory;
+import com.amap.api.maps.MapView;
+import com.amap.api.maps.model.Circle;
+import com.amap.api.maps.model.CircleOptions;
+import com.amap.api.maps.model.LatLng;
+import com.amap.api.maps.model.Marker;
+import com.amap.api.maps.model.MarkerOptions;
+import com.amap.api.maps.model.Polygon;
+import com.amap.api.maps.model.PolygonOptions;
+import com.amap.api.maps.model.Polyline;
+import com.amap.api.maps.model.PolylineOptions;
+import com.amap.api.services.core.AMapException;
+import com.amap.api.services.core.LatLonPoint;
+import com.amap.api.services.core.PoiItem;
+import com.amap.api.services.geocoder.GeocodeResult;
+import com.amap.api.services.geocoder.GeocodeSearch;
+import com.amap.api.services.geocoder.RegeocodeAddress;
+import com.amap.api.services.geocoder.RegeocodeQuery;
+import com.amap.api.services.geocoder.RegeocodeResult;
+import com.amap.api.services.poisearch.PoiResult;
+import com.amap.api.services.poisearch.PoiSearch;
+
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.bridge.Callback;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.bridge.WritableArray;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.WritableNativeArray;
+import com.facebook.react.modules.core.RCTNativeAppEventEmitter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.amap.api.maps.AMapUtils.calculateLineDistance;
+
+public class RCTAMapModule extends ReactContextBaseJavaModule implements PoiSearch.OnPoiSearchListener, GeocodeSearch.OnGeocodeSearchListener {
+    ReactApplicationContext mContext;
+
+    private PoiSearch poiSearch;
+    private int defaultRadius = 3000;
+    private final String onPOISearchDoneEventName = "amap.onPOISearchDone";
+    private final String onReGeocodeSearchDoneEvent = "OnReGeocodeSearchDoneEvent";
+
+    public RCTAMapModule(ReactApplicationContext reactContext) {
+        super(reactContext);
+        mContext = reactContext;
+        PoiSearch poiSearch = new PoiSearch(mContext, null);
+        this.poiSearch = poiSearch;
+    }
+
+    @Override
+    public String getName() {
+        return "AMapModule";
+    }
+
+    @Override
+    public Map<String, Object> getConstants() {
+        final Map<String, Object> constants = new HashMap<>();
+        constants.put("OnPOISearchDoneEvent", onPOISearchDoneEventName);
+        constants.put("OnReGeocodeSearchDoneEvent", onReGeocodeSearchDoneEvent);
+        return constants;
+    }
+
+    @ReactMethod
+    public void setCenterCoordinate(final int reactTag, final ReadableMap coordinate) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+                if (mapView == null) {
+                    Log.d("AMAP", "mapView is null.");
+                    return;
+                }
+                Log.d("AMAP", String.format("setCenterCoordinate: %s", coordinate.toString()));
+                mapView.setCenterLocation(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"));
+            }
+        });
+    }
+
+    @ReactMethod
+    public void searchPoiByCenterCoordinate(ReadableMap params) {
+
+        String types = "";
+        if (params.hasKey("types")) {
+            types = params.getString("types");
+        }
+        String keywords = "";
+        if (params.hasKey("keywords")) {
+            keywords = params.getString("keywords");
+        }
+
+        PoiSearch.Query query = new PoiSearch.Query(keywords, types);
+
+        if (params.hasKey("limit")) {
+            int limit = params.getInt("limit");
+            query.setPageSize(limit);// 设置每页最多返回多少条 poiitem
+        }
+        if (params.hasKey("page")) {
+            int page = params.getInt("page");
+            query.setPageNum(page);//设置查询页码,从 1 开始
+        }
+        poiSearch.setQuery(query);
+        if (params.hasKey("coordinate")) {
+            ReadableMap coordinateMap = params.getMap("coordinate");
+            double latitude = coordinateMap.getDouble("latitude");
+            double longitude = coordinateMap.getDouble("longitude");
+            int radius = defaultRadius;
+            if (params.hasKey("radius")) {
+                radius = params.getInt("radius");
+            }
+            poiSearch.setBound(new PoiSearch.SearchBound(new LatLonPoint(latitude, longitude), radius)); //设置周边搜索的中心点以及半径(单位: 米, 默认3公里)
+        }
+        poiSearch.setOnPoiSearchListener(this);
+        poiSearch.searchPOIAsyn();
+    }
+
+    @Override
+    public void onPoiSearched(PoiResult result, int rCode) {
+        List<PoiItem> poiItems;
+        WritableMap dataMap = Arguments.createMap();
+        if (rCode == 1000) {
+            if (result != null && result.getQuery() != null) {// 搜索poi的结果
+                poiItems = result.getPois();
+
+                WritableArray array = Arguments.createArray();
+                for (PoiItem poi : poiItems) {
+                    WritableMap data = Arguments.createMap();
+                    data.putString("uid", poi.getPoiId());
+                    data.putString("name", poi.getTitle());
+                    data.putString("type", poi.getTypeDes());
+                    data.putDouble("longitude", poi.getLatLonPoint().getLongitude());
+                    data.putDouble("latitude", poi.getLatLonPoint().getLatitude());
+                    data.putString("address", poi.getSnippet());
+                    data.putString("tel", poi.getTel());
+                    data.putInt("distance", poi.getDistance());
+                    data.putString("cityCode", poi.getCityCode());
+                    data.putString("cityName", poi.getCityName());
+                    data.putString("provinceCode", poi.getProvinceCode());
+                    data.putString("provinceName", poi.getProvinceName());
+                    data.putString("adCode", poi.getAdCode());
+                    data.putString("adName", poi.getAdName());
+                    array.pushMap(data);
+                }
+
+                dataMap.putString("keywords", poiSearch.getQuery().getQueryString());
+                dataMap.putString("types", poiSearch.getQuery().getCategory());
+                dataMap.putArray("list", array);
+            }
+        } else {
+            WritableMap error = Arguments.createMap();
+            error.putString("code", String.valueOf(rCode));
+            dataMap.putMap("error", error);
+        }
+
+        mContext
+                .getJSModule(RCTNativeAppEventEmitter.class)
+                .emit(onPOISearchDoneEventName, dataMap);
+    }
+
+    @Override
+    public void onPoiItemSearched(PoiItem poiItem, int i) {
+
+    }
+
+    private Boolean isLineInCircle(LatLng center, LatLng location, Float radius) {
+        float dist = calculateLineDistance(center, location);
+        if (dist > radius) {
+            return false;
+        }
+        return true;
+    }
+
+    @ReactMethod
+    public void isLinesInCircle(ReadableMap centerCoordinate, Float radius, ReadableArray lines, Callback callback) {
+        LatLng center = new LatLng(centerCoordinate.getDouble("latitude"), centerCoordinate.getDouble("longitude"));
+        WritableMap data = Arguments.createMap();
+        WritableArray ret = Arguments.createArray();
+
+        for (int i = 0; i < lines.size(); i++) {
+            ReadableMap lineCoordinate = lines.getMap(i);
+            ReadableMap departure = lineCoordinate.getMap("departure");
+            ReadableMap arrive = lineCoordinate.getMap("arrive");
+
+            LatLng depLatLng = new LatLng(departure.getDouble("latitude"), departure.getDouble("longitude"));
+            LatLng arrLatLng = new LatLng(arrive.getDouble("latitude"), arrive.getDouble("longitude"));
+
+            if (isLineInCircle(center, depLatLng, radius) && isLineInCircle(center, arrLatLng, radius)) {
+                ret.pushBoolean(true);
+            } else {
+                ret.pushBoolean(false);
+            }
+        }
+        data.putArray("results", ret);
+        callback.invoke(data);
+    }
+
+    @ReactMethod
+    public void searchPoiByUid(String uid, Callback callback) {
+        try {
+            PoiItem poi = poiSearch.searchPOIId(uid);
+            callback.invoke(poi);
+        } catch (AMapException e) {
+            callback.invoke();
+        }
+    }
+
+    @ReactMethod
+    public void setRegionByLatLngs(final int reactTag, final ReadableMap region) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "setRegionByLatLngs: mapView is null.");
+                    return;
+                }
+
+                ReadableArray coordinates = region.getArray("coordinates");
+                boolean animate = true;
+                if (region.hasKey("animate"))
+                    animate = region.getBoolean("animate");
+
+                mapView.setRegionConfigByLatLngs(region);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void setLatLngZoom(final int reactTag, final ReadableMap config) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "setLatLngZoom: mapView is null.");
+                    return;
+                }
+
+                ReadableMap coordinate = config.getMap("coordinate");
+                boolean animate = true;
+                if (config.hasKey("animate"))
+                    animate = config.getBoolean("animate");
+
+                Double zoomLevel = mapView.getZoomLevel();
+                if (config.hasKey("zoomLevel"))
+                    zoomLevel = config.getDouble("zoomLevel");
+
+
+                LatLng latLng;
+                if (coordinate.hasKey("latitude"))
+                    latLng = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"));
+                else
+                    latLng = new LatLng(coordinate.getDouble("lat"), coordinate.getDouble("lng"));
+
+                CameraUpdate update = CameraUpdateFactory.newLatLngZoom(latLng, zoomLevel.floatValue());
+                if (animate) {
+                    mapView.animateCamera(update);
+                } else {
+                    mapView.changeCamera(update);
+                }
+            }
+        });
+    }
+
+
+    @ReactMethod
+    public void setRegion(final int reactTag, final ReadableMap region) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+                                                        public void run() {
+                                                            final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                                                            if (mapView == null) {
+                                                                Log.d("AMAP", "setRegion: mapView is null.");
+                                                                return;
+                                                            }
+
+                                                            mapView.setRegionConfig(region);
+                                                        }
+                                                    }
+        );
+    }
+
+    @ReactMethod
+    public void minZoomLevel(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "minZoomLevel: mapView is null.");
+                    return;
+                }
+
+                callback.invoke(mapView.getMinZoomLevel());
+            }
+        });
+    }
+
+    @ReactMethod
+    public void maxZoomLevel(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "maxZoomLevel: mapView is null.");
+                    return;
+                }
+
+                callback.invoke(mapView.getMaxZoomLevel());
+            }
+        });
+    }
+
+    @ReactMethod
+    public void zoomLevel(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "zoomLevel: mapView is null.");
+                    return;
+                }
+
+                callback.invoke(mapView.getZoomLevel());
+            }
+        });
+    }
+
+    private Marker addAnnotation(RCTAMapView mapView, ReadableMap config) {
+        ReadableMap point = config.getMap("coordinate");
+        String imgName = config.getString("imageName");
+
+        MarkerOptions markerOptions = new MarkerOptions();
+        if (config.hasKey("title")) {
+            String title = config.getString("title");
+            if (!title.isEmpty())
+                markerOptions.title(title);
+        }
+
+        if (config.hasKey("snippet")) {
+            String snippet = config.getString("snippet");
+            if (!snippet.isEmpty())
+                markerOptions.snippet(snippet);
+        }
+
+        if (config.hasKey("angle")) {
+            float angle = (float) config.getDouble("angle");
+            markerOptions.rotateAngle(angle);
+        }
+
+        boolean draggable = false;
+        if (config.hasKey("draggable")) {
+            draggable = config.getBoolean("draggable");
+        }
+        markerOptions.draggable(draggable);
+
+        boolean visible = true;
+        if (config.hasKey("visible")) {
+            visible = config.getBoolean("visible");
+        }
+        markerOptions.visible(visible);
+
+        LatLng latLng;
+        if (point.hasKey("latitude"))
+            latLng = new LatLng(point.getDouble("latitude"), point.getDouble("longitude"));
+        else
+            latLng = new LatLng(point.getDouble("lat"), point.getDouble("lng"));
+        markerOptions.position(latLng);
+        Marker marker = mapView.addMarker(markerOptions, imgName, config);
+        return marker;
+    }
+
+    @ReactMethod
+    public void addAnnotation(final int reactTag, final ReadableMap config, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addAnnotation: mapView is null.");
+                    return;
+                }
+
+                Marker marker = addAnnotation(mapView, config);
+                callback.invoke(marker.getId());
+            }
+        });
+    }
+
+    @ReactMethod
+    public void addAnnotations(final int reactTag, final ReadableArray configs, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addAnnotations: mapView is null.");
+                    return;
+                }
+
+                WritableArray markers = new WritableNativeArray();
+                for (int i = 0; i < configs.size(); i++) {
+                    Marker marker = addAnnotation(mapView, configs.getMap(i));
+                    markers.pushString(marker.getId());
+                }
+                callback.invoke(markers);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeAnnotation(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removeAnnotation: mapView is null.");
+                    return;
+                }
+
+                mapView.removeMarker(key);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeAnnotations(final int reactTag, final ReadableArray keys) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removeAnnotation: mapView is null.");
+                    return;
+                }
+
+                for (int i = 0; i < keys.size(); i++) {
+                    mapView.removeMarker(keys.getString(i));
+                }
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeAllAnnotations(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addAnnotation: mapView is null.");
+                    return;
+                }
+
+                mapView.removeAllMarkers();
+                callback.invoke(true);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void showInfoWindow(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "showInfoWindow: mapView is null.");
+                    return;
+                }
+                mapView.showInfoWindow(key);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void hideInfoWindow(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "hideInfoWindow: mapView is null.");
+                    return;
+                }
+                mapView.hideInfoWindow(key);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void showAnnotation(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "showAnnotation: mapView is null.");
+                    return;
+                }
+                mapView.showAnnotation(key);
+            }
+        });
+    }
+
+
+    @ReactMethod
+    public void hideAnnotation(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "hideAnnotation: mapView is null.");
+                    return;
+                }
+                mapView.hideAnnotation(key);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void showAnnotations(final int reactTag, final ReadableArray keys) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "showAnnotations: mapView is null.");
+                    return;
+                }
+                for (int i = 0; i < keys.size(); i++) {
+                    mapView.showAnnotation(keys.getString(i));
+                }
+            }
+        });
+    }
+
+
+    @ReactMethod
+    public void hideAnnotations(final int reactTag, final ReadableArray keys) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "hideAnnotations: mapView is null.");
+                    return;
+                }
+                for (int i = 0; i < keys.size(); i++) {
+                    mapView.hideAnnotation(keys.getString(i));
+                }
+            }
+        });
+    }
+
+
+    private Circle addCircle(RCTAMapView mapView, ReadableMap config) {
+        int strokeColor = Utils.parseColor(config.getString("strokeColor"));
+        int fillColor = Utils.parseColor(config.getString("fillColor"));
+        int lineWidth = config.getInt("lineWidth");
+        double radius = config.getDouble("radius");
+        ReadableMap coordinate = config.getMap("coordinate");
+        LatLng latLng;
+        if (coordinate.hasKey("latitude"))
+            latLng = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"));
+        else
+            latLng = new LatLng(coordinate.getDouble("lat"), coordinate.getDouble("lng"));
+
+        CircleOptions circleOption = new CircleOptions();
+        circleOption.strokeWidth(lineWidth);
+        circleOption.fillColor(fillColor);
+        circleOption.strokeColor(strokeColor);
+        circleOption.radius(radius);
+        circleOption.center(latLng);
+
+        Circle circle = mapView.addCircle(circleOption,config);
+        return circle;
+    }
+
+    @ReactMethod
+    public void addCircle(final int reactTag, final ReadableMap config, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addCircle: mapView is null.");
+                    return;
+                }
+                Circle circle = addCircle(mapView, config);
+                callback.invoke(circle.getId());
+            }
+        });
+    }
+
+    @ReactMethod
+    public void addCircles(final int reactTag, final ReadableArray configs, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addCircles: mapView is null.");
+                    return;
+                }
+
+                WritableArray circles = new WritableNativeArray();
+                for (int i = 0; i < configs.size(); i++) {
+                    ReadableMap config = configs.getMap(i);
+                    Circle circle = addCircle(mapView, config);
+                    circles.pushString(circle.getId());
+                }
+                callback.invoke(circles);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeCircle(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removeCircle: mapView is null.");
+                    return;
+                }
+
+                mapView.removeCircle(key);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeCircles(final int reactTag, final ReadableArray circles) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removeCircles: mapView is null.");
+                    return;
+                }
+
+                for (int i = 0; i < circles.size(); i++) {
+                    mapView.removeCircle(circles.getString(i));
+                }
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeAllCircles(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removeCircles: mapView is null.");
+                    return;
+                }
+
+                mapView.removeAllCircles();
+                callback.invoke(true);
+            }
+        });
+    }
+
+    private Polyline addPolyline(RCTAMapView mapView, final ReadableMap config) {
+        int strokeColor = Utils.parseColor(config.getString("strokeColor"));
+        int lineWidth = config.getInt("lineWidth");
+
+        ReadableArray coordinates = config.getArray("coordinates");
+        List<LatLng> latLngs = new ArrayList<>();
+        for (int i = 0; i < coordinates.size(); i++) {
+            ReadableMap point = coordinates.getMap(i);
+            LatLng latLng;
+            if (point.hasKey("latitude"))
+                latLng = new LatLng(point.getDouble("latitude"), point.getDouble("longitude"));
+            else
+                latLng = new LatLng(point.getDouble("lat"), point.getDouble("lng"));
+            latLngs.add(latLng);
+        }
+        PolylineOptions polylineOptions = new PolylineOptions();
+        polylineOptions.color(strokeColor);
+        polylineOptions.width(lineWidth);
+        polylineOptions.addAll(latLngs);
+        Polyline polyline = mapView.addPolyline(polylineOptions,config);
+        return polyline;
+    }
+
+    @ReactMethod
+    public void addPolylines(final int reactTag, final ReadableArray configs, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addPolylines: mapView is null.");
+                    return;
+                }
+
+                WritableArray polylines = new WritableNativeArray();
+                for (int i = 0; i < configs.size(); i++) {
+                    Polyline polyline = addPolyline(mapView, configs.getMap(i));
+                    polylines.pushString(polyline.getId());
+                }
+                callback.invoke(polylines);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void addPolyline(final int reactTag, final ReadableMap config, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addPolyline: mapView is null.");
+                    return;
+                }
+
+                Polyline polyline = addPolyline(mapView, config);
+                callback.invoke(polyline.getId());
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removePolyline(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removePolyline: mapView is null.");
+                    return;
+                }
+
+                mapView.removePolyline(key);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removePolylines(final int reactTag, final ReadableArray keys) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removePolyline: mapView is null.");
+                    return;
+                }
+
+                for (int i = 0; i < keys.size(); i++) {
+                    mapView.removePolyline(keys.getString(i));
+                }
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeAllPolylines(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removePolyline: mapView is null.");
+                    return;
+                }
+
+                mapView.removeAllPolylines();
+                callback.invoke(true);
+            }
+        });
+    }
+
+    private Polygon addPolygon(RCTAMapView mapView, ReadableMap config) {
+        int strokeColor = Utils.parseColor(config.getString("strokeColor"));
+        int lineWidth = config.getInt("lineWidth");
+        int fillColor = Utils.parseColor(config.getString("fillColor"));
+
+        ReadableArray coordinates = config.getArray("coordinates");
+        List<LatLng> latLngs = new ArrayList<>();
+        for (int i = 0; i < coordinates.size(); i++) {
+            ReadableMap point = coordinates.getMap(i);
+            LatLng latLng;
+            if (point.hasKey("latitude"))
+                latLng = new LatLng(point.getDouble("latitude"), point.getDouble("longitude"));
+            else
+                latLng = new LatLng(point.getDouble("lat"), point.getDouble("lng"));
+            latLngs.add(latLng);
+        }
+
+        PolygonOptions polygonOptions = new PolygonOptions();
+        polygonOptions.strokeWidth(lineWidth);
+        polygonOptions.fillColor(fillColor);
+        polygonOptions.strokeColor(strokeColor);
+        polygonOptions.addAll(latLngs);
+
+        Polygon polygon = mapView.addPolygon(polygonOptions,config);
+        return polygon;
+    }
+
+    @ReactMethod
+    public void addPolygon(final int reactTag, final ReadableMap config, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addPolygon: mapView is null.");
+                    return;
+                }
+
+                Polygon polygon = addPolygon(mapView, config);
+                callback.invoke(polygon.getId());
+            }
+        });
+    }
+
+    @ReactMethod
+    public void addPolygons(final int reactTag, final ReadableArray configs, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "addPolygons: mapView is null.");
+                    return;
+                }
+
+                WritableArray polygons = new WritableNativeArray();
+                for (int i = 0; i < configs.size(); i++) {
+                    Polygon polygon = addPolygon(mapView, configs.getMap(i));
+                    polygons.pushString(polygon.getId());
+                }
+                callback.invoke(polygons);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removePolygon(final int reactTag, final String key) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removePolygon: mapView is null.");
+                    return;
+                }
+
+                mapView.removePolygon(key);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removePolygons(final int reactTag, final ReadableArray keys) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removePolygons: mapView is null.");
+                    return;
+                }
+
+                for (int i = 0; i < keys.size(); i++) {
+                    mapView.removePolygon(keys.getString(i));
+                }
+            }
+        });
+    }
+
+    @ReactMethod
+    public void removeAllPolygons(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "removePolygons: mapView is null.");
+                    return;
+                }
+
+                mapView.removeAllPolygons();
+                callback.invoke(true);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void userLocation(final int reactTag, final Callback callback) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "userLocation: mapView is null.");
+                    return;
+                }
+            }
+        });
+    }
+
+    @ReactMethod
+    public void setMapType(final int reactTag, final int mapType) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "setMapType: mapView is null.");
+                    return;
+                }
+
+                mapView.setMapType(mapType);
+            }
+        });
+    }
+
+    @ReactMethod
+    public void movieToUserLocation(final int reactTag) {
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                final RCTAMapView mapView = ((RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag));
+
+                if (mapView == null) {
+                    Log.d("AMAP", "movieToUserLocation: mapView is null.");
+                    return;
+                }
+
+                mapView.moveToMyLocation();
+            }
+        });
+    }
+
+    @ReactMethod
+    public void reGoecodeSearch(ReadableMap config) {
+        if (config == null)
+            return;
+        GeocodeSearch geocodeSearch = new GeocodeSearch(mContext);
+        geocodeSearch.setOnGeocodeSearchListener(this);
+        ReadableMap coordinate = config.getMap("coordinate");
+        LatLonPoint latLonPoint = new LatLonPoint(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"));
+        RegeocodeQuery query = new RegeocodeQuery(latLonPoint, (float) config.getDouble("radius"), GeocodeSearch.GPS);
+        geocodeSearch.getFromLocationAsyn(query);
+    }
+
+    @Override
+    public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
+        WritableMap data = Arguments.createMap();
+        if (i == 1000) {
+            RegeocodeAddress address = regeocodeResult.getRegeocodeAddress();
+            data.putString("district", address.getDistrict());
+            data.putString("township", address.getTownship());
+        } else {
+            WritableMap error = Arguments.createMap();
+            error.putString("code", String.valueOf(i));
+            data.putMap("error", error);
+        }
+
+        mContext
+                .getJSModule(RCTNativeAppEventEmitter.class)
+                .emit(onReGeocodeSearchDoneEvent, data);
+
+    }
+
+    @Override
+    public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
+
+    }
+
+    @ReactMethod
+    public void printCurrentMapShot(final int reactTag) {
+        RCTAMapView rctaMapView = (RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag);
+        rctaMapView.getAMAP().getMapScreenShot(new AMap.OnMapScreenShotListener() {
+            @Override
+            public void onMapScreenShot(final Bitmap bitmap) {
+                PrintHelper printHelper = new PrintHelper(mContext.getCurrentActivity());
+                printHelper.setScaleMode(PrintHelper.SCALE_MODE_FIT);
+                printHelper.printBitmap("print_map", bitmap);
+
+            }
+
+            @Override
+            public void onMapScreenShot(Bitmap bitmap, int i) {
+
+            }
+        });
+    }
+
+    @ReactMethod
+    public void setBearing(final int reactTag, final float bearing){
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                RCTAMapView mapView = (RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag);
+                mapView.getAMAP().animateCamera(CameraUpdateFactory.changeBearing(bearing));
+            }
+        });
+    }
+
+    @ReactMethod
+    public void setTilt(final int reactTag, final float tilt){
+        mContext.getCurrentActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                RCTAMapView mapView = (RCTAMapView) mContext.getCurrentActivity().findViewById(reactTag);
+                mapView.getAMAP().animateCamera(CameraUpdateFactory.changeTilt(tilt));
+            }
+        });
+    }
+
+}

+ 33 - 0
android/src/main/java/com/reactnativecomponent/amap/RCTAMapPackage.java

@@ -0,0 +1,33 @@
+package com.reactnativecomponent.amap;
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.JavaScriptModule;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+
+
+public class RCTAMapPackage implements ReactPackage {
+    @Override
+    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
+        return Arrays.<NativeModule>asList(
+                new RCTAMapModule(reactContext)
+        );
+    }
+
+    //@Override deperacted
+    public List<Class<? extends JavaScriptModule>> createJSModules() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
+        return Arrays.<ViewManager>asList(
+                new RCTAMapManager());
+    }
+}

+ 1117 - 0
android/src/main/java/com/reactnativecomponent/amap/RCTAMapView.java

@@ -0,0 +1,1117 @@
+package com.reactnativecomponent.amap;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.amap.api.location.AMapLocation;
+import com.amap.api.location.AMapLocationClient;
+import com.amap.api.location.AMapLocationClientOption;
+import com.amap.api.location.AMapLocationListener;
+import com.amap.api.maps.AMap;
+import com.amap.api.maps.CameraUpdate;
+import com.amap.api.maps.CameraUpdateFactory;
+import com.amap.api.maps.MapView;
+import com.amap.api.maps.TextureMapView;
+import com.amap.api.maps.UiSettings;
+import com.amap.api.maps.model.BitmapDescriptor;
+import com.amap.api.maps.model.BitmapDescriptorFactory;
+import com.amap.api.maps.model.CameraPosition;
+import com.amap.api.maps.model.Circle;
+import com.amap.api.maps.model.CircleOptions;
+import com.amap.api.maps.model.LatLng;
+import com.amap.api.maps.model.LatLngBounds;
+import com.amap.api.maps.model.Marker;
+import com.amap.api.maps.model.MarkerOptions;
+import com.amap.api.maps.model.MyLocationStyle;
+import com.amap.api.maps.model.Polygon;
+import com.amap.api.maps.model.PolygonOptions;
+import com.amap.api.maps.model.Polyline;
+import com.amap.api.maps.model.PolylineOptions;
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.uimanager.ThemedReactContext;
+import com.facebook.react.uimanager.events.RCTEventEmitter;
+import com.reactnativecomponent.amap.util.ShapeHelper;
+import com.reactnativecomponent.amap.util.SensorEventHelper;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import static com.amap.api.maps.AMapOptions.LOGO_POSITION_BOTTOM_RIGHT;
+import static com.amap.api.maps.AMapOptions.ZOOM_POSITION_RIGHT_CENTER;
+
+
+public class RCTAMapView extends FrameLayout implements AMapLocationListener,
+        AMap.OnCameraChangeListener,
+        AMap.OnMarkerDragListener, AMap.OnMarkerClickListener,
+        AMap.OnMapLongClickListener,
+        AMap.OnMapClickListener,
+        AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener {
+    private static final String UID = "uid";
+    private TextureMapView TEXTUREMAPVIEW;
+    private MapView MAPVIEW;
+    private AMapLocationClient mlocationClient;
+    private AMapLocationClientOption mLocationOption;
+    private SensorEventHelper mSensorHelper; // 给定位点增加方向
+    private AMap AMAP;
+    private UiSettings mapUiSettings;
+
+    private ThemedReactContext CONTEXT;
+    private ViewGroup.LayoutParams PARAM;
+
+    // 一些默认设置
+    private boolean zoomControls = false;
+    private boolean zoomGestures = true;
+    private boolean scaleControls = false;
+    private boolean compassEnable = false;
+    private boolean tiltGestures = true;
+    private boolean rotateGestures = true;
+
+    private ImageView CenterView;
+
+    private ShapeHelper<Marker> markerHelper = new ShapeHelper<Marker>(this,ShapeHelper.MARKER);
+    private ShapeHelper<Circle> circleHelper = new ShapeHelper<Circle>(this,ShapeHelper.CIRCLE);
+    private ShapeHelper<Polyline> polylineHelper = new ShapeHelper<Polyline>(this,ShapeHelper.POLYLINE);
+    private ShapeHelper<Polygon> polygonHelper = new ShapeHelper<Polygon>(this, ShapeHelper.POLYGON);
+    private ReadableMap region;
+    private boolean isReady;
+
+    private long startTime;
+    private LatLng myLatLng;
+    public boolean autoCenterCameraWhenLocationChanged = true;
+    private CameraPosition lastCameraPosition;
+
+    // 一些可以通过 props 配置的项目
+    private int mapType;
+    private float zoomLevel;
+    private LatLng centerLocation;
+    private String customMapStylePath;
+    private int mapViewType;
+    private RCTInfoWindow infoWindowObj;
+    private float bearing = -1;
+    private float tilt = -1;
+    private boolean showUserLocation = true;
+
+    public boolean isShowUserLocation() {
+        return showUserLocation;
+    }
+    public void setShowUserLocation(boolean showUserLocation) {
+        this.showUserLocation = showUserLocation;
+    }
+
+
+    public float getBearing() {
+        return bearing;
+    }
+
+    public void setBearing(float bearing) {
+        this.bearing = bearing;
+    }
+
+    public float getTilt() {
+        return tilt;
+    }
+
+    public void setTilt(float tilt) {
+        this.tilt = tilt;
+    }
+
+    public void setZoomLevel(float zoomLevel) {
+        this.zoomLevel = zoomLevel;
+        setZoomLevel();
+    }
+
+    private void setZoomLevel() {
+        if(AMAP != null && zoomLevel != 0.0f) {
+            CameraUpdate update = CameraUpdateFactory.zoomTo(zoomLevel);
+            animateCamera(update);
+        }
+    }
+
+    public float getMinZoomLevel() {return this.AMAP.getMinZoomLevel();}
+
+    public float getMaxZoomLevel() {return this.AMAP.getMaxZoomLevel();}
+
+    public double getZoomLevel() {return AMAP.getCameraPosition().zoom;}
+
+    public RCTAMapView(ThemedReactContext context) {
+        super(context);
+        this.CONTEXT = context;
+        CenterView = new ImageView(context);
+        PARAM = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        /**
+         * 处理中心点控件位置
+         */
+//        if (centerMarker != null && centerMarker != "") {
+//            HEIGHT = getHeight();
+//            WIDTH = getWidth();
+//            LayoutParams params = (LayoutParams) CenterView.getLayoutParams();
+//
+//            viewWidth = CenterView.getMeasuredWidth();
+//            viewHeight = CenterView.getMeasuredHeight();
+//
+//            params.setMargins(WIDTH / 2 - viewWidth / 2, HEIGHT / 2 - viewHeight, 0, 0);
+//            CenterView.setLayoutParams(params);
+//        }
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    /**
+     * Activity onResume后调用view的onAttachedToWindow
+     */
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        Log.d("AMAP", "onAttachedToWindow");
+
+        init();
+        isReady = true;
+        draw();
+        //startLocation(true);
+        makeBearing();
+        makeTilt();
+        setUserLocationMarker(showUserLocation);
+        ReactContext reactContext = (ReactContext) getContext();
+        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
+                getId(),
+                "onAttachedToWindow",
+                null);
+    }
+
+    public void setUserLocationMarker(boolean showUserLocation) {
+        MyLocationStyle myLocationStyle = new MyLocationStyle();
+        myLocationStyle.interval(2000);
+        myLocationStyle.showMyLocation(showUserLocation);
+        myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.gps_point));
+        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);
+        myLocationStyle.strokeColor(Color.TRANSPARENT);
+        myLocationStyle.radiusFillColor(Color.TRANSPARENT);
+        AMAP.setMyLocationStyle(myLocationStyle);
+        AMAP.setMyLocationEnabled(true);
+    }
+
+    private void makeTilt() {
+        if (tilt == -1)
+            return;
+        AMAP.animateCamera(CameraUpdateFactory.changeTilt(tilt));
+    }
+
+    private void makeBearing() {
+        if (bearing == -1)
+            return;
+        AMAP.animateCamera(CameraUpdateFactory.changeBearing(bearing));
+    }
+
+    private void draw() {
+        if (circleHelper.getsize()!=0){
+            circleHelper.addShapes(circleHelper.getDataFromJS());
+        }
+        if (polygonHelper.getsize()!=0){
+            polygonHelper.addShapes(polygonHelper.getDataFromJS());
+        }
+        if (polylineHelper.getsize()!=0){
+            polylineHelper.addShapes(polylineHelper.getDataFromJS());
+        }
+        if (markerHelper.getsize()!=0){
+            markerHelper.addShapes(markerHelper.getDataFromJS());
+        }
+        if (region!=null){
+            if (region.hasKey("radius")){
+                setRegion(region);
+            }else {
+                setRegionByLatLngs(region);
+            }
+        }
+    }
+
+    /**
+     * 初始化控件,定位位置
+     */
+    private void init() {
+        mSensorHelper = new SensorEventHelper(CONTEXT);
+        if (mSensorHelper != null) {
+            mSensorHelper.registerSensorListener();
+        }
+        if (this.mapViewType == 1) {
+            TEXTUREMAPVIEW = new TextureMapView(CONTEXT);
+            TEXTUREMAPVIEW.setLayoutParams(PARAM);
+            TEXTUREMAPVIEW.onCreate(CONTEXT.getCurrentActivity().getIntent().getExtras());
+            AMAP = TEXTUREMAPVIEW.getMap();
+            setMapOptions();
+            this.addView(TEXTUREMAPVIEW);
+        } else {
+            MAPVIEW = new MapView(CONTEXT);
+            MAPVIEW.setLayoutParams(PARAM);
+            MAPVIEW.onCreate(CONTEXT.getCurrentActivity().getIntent().getExtras());
+            AMAP = MAPVIEW.getMap();
+            setMapOptions();
+            this.addView(MAPVIEW);
+        }
+    }
+
+
+    /**
+     * 设置一些默认的amap的属性
+     */
+    private void setMapOptions() {
+        AMAP.setMapType(AMap.MAP_TYPE_NORMAL);// 矢量地图模式
+        mapUiSettings = AMAP.getUiSettings();//实例化UiSettings类
+        mapUiSettings.setZoomControlsEnabled(zoomControls);//是否显示缩放按钮
+        mapUiSettings.setZoomPosition(ZOOM_POSITION_RIGHT_CENTER);//缩放按钮位置  右边界中部:ZOOM_POSITION_RIGHT_CENTER 右下:ZOOM_POSITION_RIGHT_BUTTOM。
+        mapUiSettings.setLogoPosition(LOGO_POSITION_BOTTOM_RIGHT);//Logo的位置 左下:LOGO_POSITION_BOTTOM_LEFT 底部居中:LOGO_POSITION_BOTTOM_CENTER 右下:LOGO_POSITION_BOTTOM_RIGHT
+        mapUiSettings.setCompassEnabled(compassEnable);//是否显示 指南针
+        mapUiSettings.setZoomGesturesEnabled(zoomGestures);//是否支持手势缩放
+        mapUiSettings.setScaleControlsEnabled(scaleControls);//是否显示比例尺
+        mapUiSettings.setTiltGesturesEnabled(tiltGestures);//是否允许倾斜
+        mapUiSettings.setRotateGesturesEnabled(rotateGestures); // 是否允许旋转
+
+        mapUiSettings.setMyLocationButtonEnabled(false);// 设置默认定位按钮是否显示
+        AMAP.setMyLocationEnabled(false);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
+
+        AMAP.setOnCameraChangeListener(this);// 对 amap 添加移动地图事件监听器
+        AMAP.setOnMarkerDragListener(this); // 对 marker 移动事件监听
+        AMAP.setOnMapLongClickListener(this); // 对 map 长按事件监听
+        AMAP.setOnMapClickListener(this); // 对 map 点击事件监听
+
+        AMAP.setOnMarkerClickListener(this);
+        AMAP.setOnInfoWindowClickListener(this);
+
+        if(this.infoWindowObj != null)
+            AMAP.setInfoWindowAdapter(this); //自定义的 infoWindow
+
+        // 一些初始化的时候设定的数据,需要在此完成,因为设定的时候还没有初始化地图
+        setCustomMapStylePath();
+        setZoomLevel();
+        setMapType();
+        setCenterLocation();
+
+    }
+
+    @Override
+    public void onMarkerDragStart(Marker marker) {
+        Log.d("AMAP", "on marker darg start");
+    }
+
+    @Override
+    public void onMarkerDrag(Marker marker) {
+        Log.d("AMAP", "on marker drag");
+    }
+
+    @Override
+    public void onMarkerDragEnd(Marker marker) {
+        Log.d("AMAP", "onAnnotationDragChange");
+
+        WritableMap dataMap = Arguments.createMap();
+        dataMap.putString("key", marker.getId());
+
+        WritableMap position = Arguments.createMap();
+        position.putDouble("latitude", marker.getPosition().latitude);
+        position.putDouble("longitude", marker.getPosition().longitude);
+        dataMap.putMap("coordinate", position);
+
+        CONTEXT.getJSModule(RCTEventEmitter.class).receiveEvent(
+                getId(),
+                "onAnnotationDragChange",
+                dataMap);
+    }
+
+    @Override
+    public boolean onMarkerClick(Marker marker) {
+        WritableMap dataMap = Arguments.createMap();
+        dataMap.merge(markerHelper.getShapeConfig(marker.getId()));
+        CONTEXT.getJSModule(RCTEventEmitter.class).receiveEvent(
+                getId(),
+                "onAnnotationClick",
+                dataMap);
+        return true;
+    }
+
+    @Override
+    public void onInfoWindowClick(Marker marker) {
+        Log.d("AMAP", "infoWindow click : " + marker.getId());
+        WritableMap dataMap = Arguments.createMap();
+        dataMap.putString("key", marker.getId());
+        CONTEXT.getJSModule(RCTEventEmitter.class).receiveEvent(
+                getId(),
+                "onInfoWindowClick",
+                dataMap);
+    }
+
+    @Override
+    public void onMapLongClick(LatLng latLng) {
+        Log.d("AMAP", "onLongTapped");
+
+        WritableMap dataMap = Arguments.createMap();
+        WritableMap coordinate = Arguments.createMap();
+
+        coordinate.putDouble("latitude", latLng.latitude);
+        coordinate.putDouble("longitude", latLng.longitude);
+
+        dataMap.putMap("coordinate", coordinate);
+
+        CONTEXT.getJSModule(RCTEventEmitter.class).receiveEvent(
+                getId(),
+                "onLongTapped",
+                dataMap);
+    }
+
+    @Override
+    public void onMapClick(LatLng latLng) {
+        Log.d("AMAP", "onSingleTapped");
+
+        WritableMap dataMap = Arguments.createMap();
+        WritableMap coordinate = Arguments.createMap();
+
+        coordinate.putDouble("latitude", latLng.latitude);
+        coordinate.putDouble("longitude", latLng.longitude);
+
+        dataMap.putMap("coordinate", coordinate);
+
+        CONTEXT.getJSModule(RCTEventEmitter.class).receiveEvent(
+                getId(),
+                "onSingleTapped",
+                dataMap);
+    }
+
+    /**
+     * 调用函数moveCamera来改变可视区域
+     */
+    public void changeCamera(CameraUpdate update) {
+        AMAP.moveCamera(update);
+    }
+
+    public void animateCamera(CameraUpdate update) {
+        AMAP.stopAnimation();
+        AMAP.animateCamera(update);
+    }
+
+    /**
+     * 获得图片资源ID
+     *
+     * @return
+     */
+    private int getImageId(String fileName) {
+        int drawableId = CONTEXT.getCurrentActivity().getResources().getIdentifier(fileName, "drawable", CONTEXT.getPackageName());
+        if (drawableId == 0) {
+            drawableId = CONTEXT.getCurrentActivity().getResources().getIdentifier("splash", "drawable", CONTEXT.getPackageName());
+        }
+
+        return drawableId;
+    }
+
+    /**
+     * 根据动画调用函数animateCamera来改变可视区域
+     */
+    private void animateCamera(CameraUpdate update, AMap.CancelableCallback callback) {
+
+        AMAP.animateCamera(update, 1000, callback);
+
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        if (CONTEXT.getCurrentActivity().getIntent() != null && CONTEXT.getCurrentActivity().getIntent().getExtras() != null) {
+            if (MAPVIEW != null) {
+                MAPVIEW.onSaveInstanceState(CONTEXT.getCurrentActivity().getIntent().getExtras());
+            } else {
+                TEXTUREMAPVIEW.onSaveInstanceState(CONTEXT.getCurrentActivity().getIntent().getExtras());
+            }
+        }
+        return super.onSaveInstanceState();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        Log.d("AMAP", "onDetachedFromWindow");
+        if(MAPVIEW != null) {
+            this.removeView(MAPVIEW);
+            MAPVIEW.onDestroy();
+        } else {
+            this.removeView(TEXTUREMAPVIEW);
+            TEXTUREMAPVIEW.onDestroy();
+        }
+        if (mlocationClient != null){
+            mlocationClient.onDestroy();
+            mlocationClient = null;
+        }
+        super.onDetachedFromWindow();
+    }
+
+    /**
+     * 对应onResume、对应onPause
+     *
+     * @param hasWindowFocus
+     */
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+
+        super.onWindowFocusChanged(hasWindowFocus);
+
+        if (hasWindowFocus) {
+//            对应onResume
+            if(MAPVIEW != null)
+                MAPVIEW.onResume();
+            else
+                TEXTUREMAPVIEW.onResume();
+        } else {
+            //对应onPause
+            if(MAPVIEW != null)
+                MAPVIEW.onPause();
+            else
+                TEXTUREMAPVIEW.onPause();
+
+        }
+
+    }
+
+    @Override
+    public void onLocationChanged(AMapLocation amapLocation) {
+        if (amapLocation != null && amapLocation.getErrorCode() == 0) {
+            // 有返回值就认为定位成功,不管是否有改变,都绘制定位点
+            myLatLng = new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude());
+
+            if(autoCenterCameraWhenLocationChanged) {
+                //移动镜头定位到点location
+                CameraUpdate update = CameraUpdateFactory.newLatLng(myLatLng);
+                animateCamera(update);
+            }
+        }
+    }
+
+    /**
+     * 获得当前控件中心点坐标
+     */
+    public LatLng getCenterLocation() {
+        LatLng latlng = AMAP.getCameraPosition().target;
+        return latlng;
+    }
+
+    /**
+     * 设置并移动到中心点坐标
+     */
+    public void setCenterLocation(double latitude, double longitude) {
+        LatLng latlng = new LatLng(latitude, longitude);
+        this.centerLocation = latlng;
+        setCenterLocation();
+    }
+
+    private void setCenterLocation() {
+        if(AMAP != null && this.centerLocation != null)
+            animateCamera(CameraUpdateFactory.newLatLng(this.centerLocation));
+    }
+    /**
+     * 定位到设备定位位置
+     */
+    public void startLocation(Boolean isOnceLocation) {
+        startTime = System.currentTimeMillis();
+        Log.i("AMAP", "start get my location, startTime:" + startTime);
+        if (mlocationClient == null) {
+            Log.i("AMAP", "mlocationClient = null");
+            mlocationClient = new AMapLocationClient(CONTEXT);
+            //设置定位监听
+            mlocationClient.setLocationListener(this);
+
+            mLocationOption = new AMapLocationClientOption();
+            //设置为高精度定位模式
+            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
+            mLocationOption.setOnceLocation(isOnceLocation);
+//            mLocationOption.setOnceLocationLatest(true);
+            mLocationOption.setLocationCacheEnable(true);//定位缓存策略
+            //mLocationOption.setInterval(2000); // ms
+
+            //设置定位参数
+            mlocationClient.setLocationOption(mLocationOption);
+
+            // 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求
+            // 在定位结束后,在合适的生命周期调用onDestroy()方法
+            // 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
+        }
+        mlocationClient.startLocation();
+    }
+
+    @Override
+    public View getInfoContents(Marker marker) {
+        return null;
+    }
+
+    //@Override
+    public long getInfoWindowUpdateTime() {
+        return 5 * 60 * 1000; // 5min
+        //return 1000;
+    }
+
+    @Override
+    public View getInfoWindow(Marker marker) {
+        return this.infoWindowObj.getInfoWindow(marker, markerHelper.getShapeConfig(marker.getId()));
+    }
+
+    public void showInfoWindow(String key) {
+        if(markerHelper.getDrawedShapes().containsKey(key)) {
+            Marker marker = markerHelper.getShape(key);
+            marker.showInfoWindow();
+        }
+    }
+
+    public void hideInfoWindow(String key) {
+        if(markerHelper.getDrawedShapes().containsKey(key)) {
+            Marker marker = markerHelper.getShape(key);
+            marker.hideInfoWindow();
+        }
+    }
+
+    public void showAnnotation(String key) {
+        if(markerHelper.getDrawedShapes().containsKey(key)) {
+            Marker marker = markerHelper.getShape(key);
+            marker.setVisible(true);
+        }
+    }
+
+    public void hideAnnotation(String key) {
+        if(markerHelper.getDrawedShapes().containsKey(key)) {
+            Marker marker = markerHelper.getShape(key);
+            marker.setVisible(false);
+        }
+    }
+
+
+    private Marker addMarker(LatLng latLng, BitmapDescriptor bitmapDescriptor) {
+        MarkerOptions markerOptions = new MarkerOptions();
+        markerOptions.position(latLng);
+        markerOptions.icon(bitmapDescriptor);
+        return addMarker(markerOptions);
+    }
+
+    public Marker addMarker(MarkerOptions markerOptions, String imgName, ReadableMap config) {
+        float offsetX = 0.5f;
+        float offsetY = 0.5f;
+        if(config.hasKey("customView")){
+            try {
+                Class customView = Class.forName(config.getString("customView"));
+                Constructor constructor = customView.getConstructor(Context.class,ReadableMap.class);
+                BaseCustomView view = (BaseCustomView) constructor.newInstance(CONTEXT,config.hasKey("customViewProps")?config.getMap("customViewProps"):null);
+                markerOptions.icon(BitmapDescriptorFactory.fromView(view));
+                HashMap<String,Float> map = view.getOffset();
+                if(map != null){
+                    if (map.containsKey("offsetX"))
+                        offsetX = map.get("offsetX");
+                    if (map.containsKey("offsetY"))
+                        offsetY = map.get("offsetY");
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }else {
+            int resId = getImageId(imgName.toLowerCase());
+            BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(resId);
+            markerOptions.icon(bitmapDescriptor);
+        }
+
+        if (config.hasKey("offset")) {
+            offsetX = (float) config.getMap("offset").getDouble("x");
+            offsetY = (float) config.getMap("offset").getDouble("y");
+        }
+        markerOptions.anchor(offsetX,offsetY);
+
+        return addMarker(markerOptions, config);
+    }
+
+    public Marker addMarker(MarkerOptions markerOptions) {
+        ReadableMap config =  Arguments.createMap();
+        return addMarker(markerOptions, config);
+    }
+
+    public Marker addMarker(MarkerOptions markerOptions, ReadableMap config) {
+        Marker marker = AMAP.addMarker(markerOptions);
+        boolean flat = true;
+        if (config.hasKey("flat")){
+            flat = config.getBoolean("flat");
+        }
+        marker.setFlat(flat);
+
+        if (config.hasKey("isToTop")){
+            if (config.getBoolean("isToTop"))
+                marker.setToTop();
+        }
+        markerHelper.addShape(marker.getId(),marker,config);
+        return marker;
+    }
+
+    public void removeMarker(String key) {
+        Marker marker = markerHelper.getShape(key);
+        marker.destroy();
+        if(this.infoWindowObj != null)
+            this.infoWindowObj.removeInfoWindow(key);
+    }
+
+    public void removeAllMarkers(){
+        markerHelper.removeAllShapes();
+    }
+
+    public Circle addCircle(CircleOptions circleOptions,ReadableMap config) {
+        Circle circle = AMAP.addCircle(circleOptions);
+        circleHelper.addShape(circle.getId(),circle,config);
+        return circle;
+    }
+    public void addCircle(final ReadableMap config) {
+        this.CONTEXT.getCurrentActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                int strokeColor = Utils.parseColor(config.getString("strokeColor"));
+                int fillColor = Utils.parseColor(config.getString("fillColor"));
+                int lineWidth = config.getInt("lineWidth");
+                double radius = config.getDouble("radius");
+                ReadableMap coordinate = config.getMap("coordinate");
+                LatLng latLng;
+                if(coordinate.hasKey("latitude"))
+                    latLng = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"));
+                else
+                    latLng = new LatLng(coordinate.getDouble("lat"), coordinate.getDouble("lng"));
+
+                CircleOptions circleOption = new CircleOptions();
+                circleOption.strokeWidth(lineWidth);
+                circleOption.fillColor(fillColor);
+                circleOption.strokeColor(strokeColor);
+                circleOption.radius(radius);
+                circleOption.center(latLng);
+                addCircle(circleOption,config);
+            }
+        });
+    }
+    public void addPolygon(final ReadableMap config) {
+        this.CONTEXT.getCurrentActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                int strokeColor = Utils.parseColor(config.getString("strokeColor"));
+                int lineWidth = config.getInt("lineWidth");
+                int fillColor = Utils.parseColor(config.getString("fillColor"));
+
+                ReadableArray coordinates = config.getArray("coordinates");
+                List<LatLng> latLngs = new ArrayList<>();
+                for(int i=0; i< coordinates.size(); i++) {
+                    ReadableMap point = coordinates.getMap(i);
+                    LatLng latLng;
+                    if(point.hasKey("latitude"))
+                        latLng = new LatLng(point.getDouble("latitude"), point.getDouble("longitude"));
+                    else
+                        latLng = new LatLng(point.getDouble("lat"), point.getDouble("lng"));
+                    latLngs.add(latLng);
+                }
+
+                PolygonOptions polygonOptions = new PolygonOptions();
+                polygonOptions.strokeWidth(lineWidth);
+                polygonOptions.fillColor(fillColor);
+                polygonOptions.strokeColor(strokeColor);
+                polygonOptions.addAll(latLngs);
+                addPolygon(polygonOptions,config);
+            }
+        });
+    }
+    public void addPolyline(final ReadableMap config) {
+        this.CONTEXT.getCurrentActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                int strokeColor = Utils.parseColor(config.getString("strokeColor"));
+                int lineWidth = config.getInt("lineWidth");
+
+                ReadableArray coordinates = config.getArray("coordinates");
+                List<LatLng> latLngs = new ArrayList<>();
+                for(int i=0; i< coordinates.size(); i++) {
+                    ReadableMap point = coordinates.getMap(i);
+                    LatLng latLng;
+                    if(point.hasKey("latitude"))
+                        latLng = new LatLng(point.getDouble("latitude"), point.getDouble("longitude"));
+                    else
+                        latLng = new LatLng(point.getDouble("lat"), point.getDouble("lng"));
+                    latLngs.add(latLng);
+                }
+                PolylineOptions polylineOptions = new PolylineOptions();
+                polylineOptions.color(strokeColor);
+                polylineOptions.width(lineWidth);
+                polylineOptions.addAll(latLngs);
+                addPolyline(polylineOptions,config);
+            }
+        });
+    }
+    public void addMarkers(final ReadableMap config) {
+        this.CONTEXT.getCurrentActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                ReadableMap point = config.getMap("coordinate");
+                String imgName = "";
+                if (config.hasKey("imageName")){
+                    imgName = config.getString("imageName");
+                }
+
+                MarkerOptions markerOptions = new MarkerOptions();
+                if (config.hasKey("title")) {
+                    String title = config.getString("title");
+                    if(!title.isEmpty())
+                        markerOptions.title(title);
+                }
+
+                if (config.hasKey("snippet")) {
+                    String snippet = config.getString("snippet");
+                    if(!snippet.isEmpty())
+                        markerOptions.snippet(snippet);
+                }
+
+                if(config.hasKey("angle")) {
+                    float angle = (float) config.getDouble("angle");
+                    markerOptions.rotateAngle(angle);
+                }
+
+                boolean draggable = false;
+                if(config.hasKey("draggable")) {
+                    draggable = config.getBoolean("draggable");
+                }
+                markerOptions.draggable(draggable);
+
+                boolean visible = true;
+                if(config.hasKey("visible")) {
+                    visible = config.getBoolean("visible");
+                }
+                markerOptions.visible(visible);
+
+                LatLng latLng;
+                if(point.hasKey("latitude"))
+                    latLng = new LatLng(point.getDouble("latitude"), point.getDouble("longitude"));
+                else
+                    latLng = new LatLng(point.getDouble("lat"), point.getDouble("lng"));
+                markerOptions.position(latLng);
+                addMarker(markerOptions, imgName, config);
+            }
+        });
+    }
+
+    public void removeCircle(String key) {
+        if(circleHelper.getDrawedShapes().containsKey(key)) {
+            Circle circle = circleHelper.getShape(key);
+            circle.remove();
+        }
+    }
+
+    public void removeAllCircles(){
+        circleHelper.removeAllShapes();
+    }
+
+    public Polygon addPolygon(PolygonOptions polygonOptions, ReadableMap config) {
+        Polygon polygon = AMAP.addPolygon(polygonOptions);
+        polygonHelper.addShape(polygon.getId(),polygon,config);
+        return polygon;
+    }
+
+    public void removePolygon(String key) {
+        if(polygonHelper.getDrawedShapes().containsKey(key)) {
+            Polygon polygon = polygonHelper.getShape(key);
+            polygon.remove();
+        }
+    }
+
+    public void removeAllPolygons(){
+        polygonHelper.removeAllShapes();
+    }
+
+    public Polyline addPolyline(PolylineOptions polylineOptions, ReadableMap config) {
+        Polyline polyline = AMAP.addPolyline(polylineOptions);
+        polylineHelper.addShape(polyline.getId(),polyline,config);
+        return polyline;
+    }
+
+    public void removePolyline(String key) {
+        if(polylineHelper.getDrawedShapes().containsKey(key)) {
+            Polyline polyline = polylineHelper.getShape(key);
+            polyline.remove();
+        }
+    }
+
+    public void removeAllPolylines(){
+        polylineHelper.removeAllShapes();
+    }
+
+    @Override
+    public void onCameraChange(CameraPosition cameraPosition) {
+
+
+    }
+
+    /**
+     * 控制中心点动画 获取中心点坐标 查询周边
+     *
+     * @param cameraPosition
+     */
+    @Override
+    public void onCameraChangeFinish(CameraPosition cameraPosition) {
+        Log.i("AMAP", String.format("onCameraChangeFinish: %s", cameraPosition));
+
+//        /**
+//         * 中心点动画开始
+//         */
+//        ObjectAnimator translationYAnim = ObjectAnimator.ofFloat(CenterView, "translationY", 0.0f, -viewHeight / 2, 0.0f);
+//        translationYAnim.setDuration(600);
+////        translationYAnim.setRepeatCount(ValueAnimator.RESTART);//重复一次
+////        translationYAnim.setRepeatMode(ValueAnimator.INFINITE);
+//        translationYAnim.start();
+//        /**
+//         * 中心点动画结束
+//         */
+
+        LatLng latlng = cameraPosition.target;//获取屏幕中心点
+        ReactContext reactContext = (ReactContext) getContext();
+
+        if (lastCameraPosition != null) {
+            LatLng lastLatLng = lastCameraPosition.target;
+            if (lastLatLng.latitude != latlng.latitude || lastLatLng.longitude != latlng.longitude) {
+
+                WritableMap eventMap = Arguments.createMap();
+                WritableMap dataMap = Arguments.createMap();
+                WritableMap centerCoordinateMap = Arguments.createMap();
+                centerCoordinateMap.putDouble("latitude", latlng.latitude);
+                centerCoordinateMap.putDouble("longitude", latlng.longitude);
+                dataMap.putMap("centerCoordinate", centerCoordinateMap);
+                eventMap.putMap("data", dataMap);
+                reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
+                        getId(),
+                        "onDidMoveByUser",
+                        eventMap);
+            }
+
+            if (lastCameraPosition.zoom != cameraPosition.zoom) {
+                WritableMap dataMap = Arguments.createMap();
+                dataMap.putDouble("zoomLevel", cameraPosition.zoom);
+                reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
+                        getId(),
+                        "onMapZoomChange",
+                        dataMap);
+            }
+        }
+        lastCameraPosition = cameraPosition;
+    }
+
+    public void setMapViewType(int mapViewType){
+        this.mapViewType = mapViewType;
+        // 这个属性在运行时修改无效
+    }
+
+    public void setMapType(int mapType) {
+        this.mapType = mapType;
+        setMapType();
+    }
+
+    private void setMapType() {
+        // 取值是 1-5 例如 AMAP.MAP_TYPE_BUS
+        if(AMAP != null && this.mapType != 0)
+            AMAP.setMapType(mapType);
+    }
+
+    public void moveToMyLocation() {
+        boolean isOnce = true;
+        startLocation(isOnce);
+    }
+
+    private String getAssetsPath(String fileName) {
+        String filePath = null;
+        try {
+            filePath = fileName;
+        }catch (Exception e){};
+        return filePath;
+    }
+
+    public void setCustomMapStylePath(String customMapStyleFileName) {
+        String filePath = null;
+        InputStream inputStream = null;
+        FileOutputStream out = null;
+
+        try {
+            inputStream = CONTEXT.getAssets().open(customMapStyleFileName);
+            byte[] b = new byte[inputStream.available()];
+            inputStream.read(b);
+            filePath = CONTEXT.getFilesDir().getAbsolutePath() + "/" + customMapStyleFileName;
+            File f = new File(filePath);
+            if (!f.exists()) {
+                // TODO: 要更新必须要重新起一个地图的名字,或许可以有更好的方式
+                Log.d("AMAP", "Style not exist.");
+                f.createNewFile();
+                out = new FileOutputStream(f);
+                out.write(b);
+            } else {
+                Log.d("AMAP", "Style file is there");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (inputStream != null)
+                    inputStream.close();
+
+                if (out != null)
+                    out.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        this.customMapStylePath = filePath;
+
+        setCustomMapStylePath();
+    }
+
+    private void setCustomMapStylePath() {
+        if(AMAP != null && this.customMapStylePath != null) {
+            AMAP.setCustomMapStylePath(this.customMapStylePath);
+            AMAP.setMapCustomEnable(true);
+        }
+    }
+
+    public void setInfoWindowClass(String className) {
+
+        try {
+            this.infoWindowObj = new RCTInfoWindow(CONTEXT, className);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setScaleControls(boolean scaleControls) {
+        if(scaleControls)
+            this.scaleControls = scaleControls;
+    }
+
+    public void setTiltGestures(boolean tiltGestures) {
+        if(!tiltGestures)
+            this.tiltGestures = tiltGestures;
+    }
+
+    public void setRotateGestures(boolean rotateGestures) {
+        if(!rotateGestures)
+            this.rotateGestures = rotateGestures;
+    }
+    public boolean isReady(){
+        return isReady;
+    }
+
+    public void setRegion(final ReadableMap region) {
+        this.CONTEXT.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                setRegionConfig(region);
+            }}
+        );
+    }
+
+    public void setRegionConfig(ReadableMap region){
+        ReadableMap center = region.getMap("center");
+        double centerLat = center.getDouble("latitude");
+        double centerLng = center.getDouble("longitude");
+
+        double radius = region.getDouble("radius");
+
+        boolean animate = true;
+        if(region.hasKey("animate"))
+            animate = region.getBoolean("animate");
+
+
+        double distance = Math.sqrt(2*radius*radius);
+        ReadableMap southwestGPS = HaversineAlgorithm.addDistanceToGPS(centerLat, centerLng, -distance, -distance);
+        LatLng southwestLatLng = new LatLng(southwestGPS.getDouble("latitude"), southwestGPS.getDouble("longitude"));
+
+        ReadableMap northeastGPS = HaversineAlgorithm.addDistanceToGPS(centerLat, centerLng, distance, distance);
+        LatLng northeastLatLng = new LatLng(northeastGPS.getDouble("latitude"), northeastGPS.getDouble("longitude"));
+
+        int padding2Px = 100;
+        if (region.hasKey("padding")){
+            padding2Px = Utils.dip2px(CONTEXT,(float) region.getDouble("padding"));
+        }
+
+        CameraUpdate update = CameraUpdateFactory.newLatLngBounds(new LatLngBounds(southwestLatLng, northeastLatLng), padding2Px); //100 是经验值。。
+
+        Log.d("AMAP", String.format("setRegion input: %s, output: sw %s, ne %s", region, southwestGPS.toString(), northeastGPS.toString()));
+
+        if(animate) {
+            animateCamera(update);
+        } else {
+            changeCamera(update);
+        }
+    }
+
+    public void setRegionByLatLngs(final ReadableMap region) {
+        CONTEXT.getCurrentActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                setRegionConfigByLatLngs(region);
+            }
+        });
+    }
+    public void setRegionConfigByLatLngs(ReadableMap region){
+        ReadableArray coordinates = region.getArray("coordinates");
+        boolean animate = true;
+        if (region.hasKey("animate"))
+            animate = region.getBoolean("animate");
+
+        LatLngBounds.Builder builder = LatLngBounds.builder();
+        for (int i = 0; i < coordinates.size(); i++) {
+            ReadableMap coordinate = coordinates.getMap(i);
+            LatLng latLng;
+            if(coordinate.hasKey("latitude"))
+                latLng = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"));
+            else
+                latLng = new LatLng(coordinate.getDouble("lat"), coordinate.getDouble("lng"));
+
+            builder.include(latLng);
+        }
+
+        int padding2Px = 100;
+        if (region.hasKey("padding")){
+            padding2Px = Utils.dip2px(CONTEXT,(float) region.getDouble("padding"));
+        }
+
+        CameraUpdate update = CameraUpdateFactory.newLatLngBounds(builder.build(), padding2Px);
+        if (animate) {
+            animateCamera(update);
+        } else {
+            changeCamera(update);
+        }
+    }
+
+
+    public ShapeHelper getMarkerHelper(){
+        return markerHelper;
+    }
+
+    public ShapeHelper<Circle> getCircleHelper() {
+        return circleHelper;
+    }
+
+    public ShapeHelper<Polyline> getPolylineHelper() {
+        return polylineHelper;
+    }
+
+    public ShapeHelper<Polygon> getPolygonHelper() {
+        return polygonHelper;
+    }
+
+    //region
+    public void setMapRegion(ReadableMap region){
+        this.region = region;
+    }
+
+    public AMap getAMAP(){
+        return AMAP;
+    }
+
+}
+

+ 44 - 0
android/src/main/java/com/reactnativecomponent/amap/RCTInfoWindow.java

@@ -0,0 +1,44 @@
+package com.reactnativecomponent.amap;
+
+import android.view.View;
+
+import com.amap.api.maps.model.Marker;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReadableMap;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * Created by wd on 14/09/2017.
+ */
+
+public class RCTInfoWindow {
+    AMAPInfoWindowAdapter infowindow;
+
+    public RCTInfoWindow(ReactContext context, String className) {
+        try {
+            Class<?> c = Class.forName(className);
+            Constructor cons = c.getConstructor(ReactContext.class);
+            infowindow = (AMAPInfoWindowAdapter) cons.newInstance(context);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public View getInfoWindow(Marker marker, ReadableMap config) {
+        try {
+            return infowindow.getInfoWindow(marker, config);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public void removeInfoWindow(String key) {
+        try {
+            infowindow.removeInfoWindow(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 138 - 0
android/src/main/java/com/reactnativecomponent/amap/Utils.java

@@ -0,0 +1,138 @@
+/**
+ *
+ */
+package com.reactnativecomponent.amap;
+
+import android.graphics.Color;
+import android.text.TextUtils;
+
+import com.amap.api.location.AMapLocation;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import android.content.Context;
+
+public class Utils {
+	/**
+	 *  开始定位
+	 */
+	public final static int MSG_LOCATION_START = 0;
+	/**
+	 * 定位完成
+	 */
+	public final static int MSG_LOCATION_FINISH = 1;
+	/**
+	 * 停止定位
+	 */
+	public final static int MSG_LOCATION_STOP= 2;
+
+	public final static String KEY_URL = "URL";
+	public final static String URL_H5LOCATION = "file:///android_asset/location.html";
+	/**
+	 * 根据定位结果返回定位信息的字符串
+	 * @param
+	 * @return
+	 */
+	public synchronized static String getLocationStr(AMapLocation location){
+		if(null == location){
+			return null;
+		}
+		StringBuffer sb = new StringBuffer();
+		//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
+		if(location.getErrorCode() == 0){
+			sb.append("定位成功" + "\n");
+			sb.append("定位类型: " + location.getLocationType() + "\n");
+			sb.append("经    度    : " + location.getLongitude() + "\n");
+			sb.append("纬    度    : " + location.getLatitude() + "\n");
+			sb.append("精    度    : " + location.getAccuracy() + "米" + "\n");
+			sb.append("提供者    : " + location.getProvider() + "\n");
+
+			if (location.getProvider().equalsIgnoreCase(
+					android.location.LocationManager.GPS_PROVIDER)) {
+				// 以下信息只有提供者是GPS时才会有
+				sb.append("速    度    : " + location.getSpeed() + "米/秒" + "\n");
+				sb.append("角    度    : " + location.getBearing() + "\n");
+				// 获取当前提供定位服务的卫星个数
+				sb.append("星    数    : "
+						+ location.getSatellites() + "\n");
+			} else {
+				// 提供者是GPS时是没有以下信息的
+				sb.append("国    家    : " + location.getCountry() + "\n");
+				sb.append("省            : " + location.getProvince() + "\n");
+				sb.append("市            : " + location.getCity() + "\n");
+				sb.append("城市编码 : " + location.getCityCode() + "\n");
+				sb.append("区            : " + location.getDistrict() + "\n");
+				sb.append("区域 码   : " + location.getAdCode() + "\n");
+				sb.append("地    址    : " + location.getAddress() + "\n");
+				sb.append("兴趣点    : " + location.getPoiName() + "\n");
+				//定位完成的时间
+				sb.append("定位时间: " + formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
+			}
+		} else {
+			//定位失败
+			sb.append("定位失败" + "\n");
+			sb.append("错误码:" + location.getErrorCode() + "\n");
+			sb.append("错误信息:" + location.getErrorInfo() + "\n");
+			sb.append("错误描述:" + location.getLocationDetail() + "\n");
+		}
+		//定位之后的回调时间
+		sb.append("回调时间: " + formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
+		return sb.toString();
+	}
+
+	private static SimpleDateFormat sdf = null;
+	public synchronized static String formatUTC(long l, String strPattern) {
+		if (TextUtils.isEmpty(strPattern)) {
+			strPattern = "yyyy-MM-dd HH:mm:ss";
+		}
+		if (sdf == null) {
+			try {
+				sdf = new SimpleDateFormat(strPattern, Locale.CHINA);
+			} catch (Throwable e) {
+			}
+		} else {
+			sdf.applyPattern(strPattern);
+		}
+		return sdf == null ? "NULL" : sdf.format(l);
+	}
+
+	/**
+	 * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
+	 */
+	public static int dip2px(Context context, float dpValue) {
+		final float scale = context.getResources().getDisplayMetrics().density;
+		return (int) (dpValue * scale + 0.5f);
+	}
+
+	public static int parseColor(String color){
+		char[] chars = color.split("#")[1].toCharArray();
+		String red="",green="",blue="",alpha="";
+		switch(color.length()){
+			case 4:   //#rgb
+				red = chars[0]+""+chars[0];
+			    green = chars[1]+""+chars[1];
+			    blue = chars[2]+""+chars[2];
+			    alpha = "";
+				break;
+			case 5:   //#rgba
+                red = chars[0]+""+chars[0];
+                green = chars[1]+""+chars[1];
+                blue = chars[2]+""+chars[2];
+                alpha = chars[3]+""+chars[3];
+				break;
+			case 7:   //#rrggbb
+                red = chars[0]+""+chars[1];
+                green = chars[2]+""+chars[3];
+                blue = chars[4]+""+chars[5];
+                alpha = "";
+				break;
+			case 9:   //#rrggbbaa
+                red = chars[0]+""+chars[1];
+                green = chars[2]+""+chars[3];
+                blue = chars[4]+""+chars[5];
+                alpha = chars[6]+""+chars[7];
+				break;
+		}
+		return Color.parseColor("#"+alpha+red+green+blue);
+	}
+}

+ 98 - 0
android/src/main/java/com/reactnativecomponent/amap/util/SensorEventHelper.java

@@ -0,0 +1,98 @@
+package com.reactnativecomponent.amap.util;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.view.Display;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import com.amap.api.maps.model.Marker;
+
+public class SensorEventHelper implements SensorEventListener {
+
+	private SensorManager mSensorManager;
+	private Sensor mSensor;
+	private long lastTime = 0;
+	private final int TIME_SENSOR = 100;
+	private float mAngle;
+	private Context mContext;
+	private Marker mMarker;
+
+	public SensorEventHelper(Context context) {
+		mContext = context;
+		mSensorManager = (SensorManager) context
+				.getSystemService(Context.SENSOR_SERVICE);
+		mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
+
+	}
+
+	public void registerSensorListener() {
+		mSensorManager.registerListener(this, mSensor,
+				SensorManager.SENSOR_DELAY_NORMAL);
+	}
+
+	public void unRegisterSensorListener() {
+		mSensorManager.unregisterListener(this, mSensor);
+	}
+
+	public void setCurrentMarker(Marker marker) {
+		mMarker = marker;
+	}
+
+	@Override
+	public void onAccuracyChanged(Sensor sensor, int accuracy) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void onSensorChanged(SensorEvent event) {
+		if (System.currentTimeMillis() - lastTime < TIME_SENSOR) {
+			return;
+		}
+		switch (event.sensor.getType()) {
+		case Sensor.TYPE_ORIENTATION: {
+			float x = event.values[0];
+			x += getScreenRotationOnPhone(mContext);
+			x %= 360.0F;
+			if (x > 180.0F)
+				x -= 360.0F;
+			else if (x < -180.0F)
+				x += 360.0F;
+			
+			if (Math.abs(mAngle - x) < 3.0f) {
+				break;
+			}
+			mAngle = Float.isNaN(x) ? 0 : x;
+			if (mMarker != null) {
+				mMarker.setRotateAngle(360-mAngle);
+			}
+			lastTime = System.currentTimeMillis();
+		}
+		}
+
+	}
+
+	public static int getScreenRotationOnPhone(Context context) {
+		final Display display = ((WindowManager) context
+				.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+
+		switch (display.getRotation()) {
+		case Surface.ROTATION_0:
+			return 0;
+
+		case Surface.ROTATION_90:
+			return 90;
+
+		case Surface.ROTATION_180:
+			return 180;
+
+		case Surface.ROTATION_270:
+			return -90;
+		}
+		return 0;
+	}
+}

+ 172 - 0
android/src/main/java/com/reactnativecomponent/amap/util/ShapeHelper.java

@@ -0,0 +1,172 @@
+package com.reactnativecomponent.amap.util;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.bridge.ReadableMap;
+import com.reactnativecomponent.amap.RCTAMapView;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+public class ShapeHelper<T> {
+    private static final String UID = "uid";
+    public static final int CIRCLE = 1;
+    public static final int POLYLINE = 2;
+    public static final int POLYGON = 3;
+    public static final int MARKER = 4;
+
+    private ReadableArray dataFromJS = null;
+    private HashMap<String,ShapeHolder<T>> drawedShapes = new HashMap<>();
+    private HashSet<String> drawedUIDS = new HashSet<>();
+    private RCTAMapView mapView = null;
+    private int type = 0;
+
+    public ShapeHelper(RCTAMapView mapView, int shapeType){
+        this.mapView = mapView;
+        this.type = shapeType;
+    }
+
+    public int getsize(){
+        if (dataFromJS == null)
+            return 0;
+        return dataFromJS.size();
+    }
+
+    public void addShape(String key ,T t, ReadableMap config){
+        if (drawedShapes == null)
+            return;
+        String uid = null;
+        if (config.hasKey(UID)){
+            uid = config.getString(UID);
+            drawedUIDS.add(uid);
+        }
+        ShapeHolder<T> holder = new ShapeHolder(t,config,uid);
+        drawedShapes.put(key, holder);
+    }
+
+    public void removeShape(String key){
+        switch (type){
+            case CIRCLE:
+                mapView.removeCircle(key);
+                break;
+            case POLYLINE:
+                mapView.removePolyline(key);
+                break;
+            case POLYGON:
+                mapView.removePolygon(key);
+                break;
+            case MARKER:
+                mapView.removeMarker(key);
+                break;
+            default:break;
+        }
+    }
+
+    public HashSet<String> getUidsFromJS(ReadableArray dataFromJS){
+        HashSet<String> UIDsfromJS = new HashSet<>();
+        for (int i = 0; i < dataFromJS.size(); i++) {
+            ReadableMap map = dataFromJS.getMap(i);
+            if (map.hasKey(UID)){
+                UIDsfromJS.add(map.getString(UID));
+            }
+        }
+        return UIDsfromJS;
+    }
+
+    public void removeShapes(ReadableArray dataFromJS){
+        HashSet<String> UIDsfromJS = getUidsFromJS(dataFromJS);
+
+        Iterator<String> iterator = drawedShapes.keySet().iterator();
+        while (iterator.hasNext()){
+            String key = iterator.next();
+            ShapeHolder<T> next = drawedShapes.get(key);
+            if (next.uid == null){
+                removeShape(key);
+                iterator.remove();
+            }else {
+                if (!UIDsfromJS.contains(next.uid)){
+                    removeShape(key);
+                    iterator.remove();
+                    drawedUIDS.remove(next.uid);
+                }
+            }
+        }
+    }
+
+    public void removeAllShapes(){
+        Iterator<String> iterator = drawedShapes.keySet().iterator();
+        while (iterator.hasNext()){
+            String key = iterator.next();
+            removeShape(key);
+        }
+        drawedShapes.clear();
+        drawedUIDS.clear();
+    }
+
+    private void addShapeView(ReadableMap config){
+        switch (type){
+            case CIRCLE:
+                mapView.addCircle(config);
+                break;
+            case POLYLINE:
+                mapView.addPolyline(config);
+                break;
+            case POLYGON:
+                mapView.addPolygon(config);
+                break;
+            case MARKER:
+                mapView.addMarkers(config);
+                break;
+            default:break;
+        }
+    }
+
+    public void addShapes(ReadableArray dataFromJS){
+        for (int i = 0; i < dataFromJS.size(); i++) {
+            if (dataFromJS.getMap(i).hasKey(UID)){
+                String uid = dataFromJS.getMap(i).getString(UID);
+                if (!drawedUIDS.contains(uid)){
+                    addShapeView(dataFromJS.getMap(i));
+                }
+            }else {
+                addShapeView(dataFromJS.getMap(i));
+            }
+        }
+    }
+
+    public void drawShapes(ReadableArray dataFromJS){
+        this.dataFromJS = dataFromJS;
+        removeShapes(dataFromJS);
+        addShapes(dataFromJS);
+    }
+
+    public ReadableMap getShapeConfig(String key){
+        return drawedShapes.get(key).drawedMarkerConfig;
+    }
+
+    public T getShape(String key){
+        return drawedShapes.get(key).shape;
+    }
+
+    public ReadableArray getDataFromJS() {
+        return dataFromJS;
+    }
+
+    public void setDataFromJS(ReadableArray dataFromJS) {
+        this.dataFromJS = dataFromJS;
+    }
+
+    public HashMap<String, ShapeHolder<T>> getDrawedShapes() {
+        return drawedShapes;
+    }
+
+    public static class ShapeHolder<T>{
+        public T shape;
+        public ReadableMap drawedMarkerConfig;
+        public String uid;
+
+        ShapeHolder(T t, ReadableMap config, String uid){
+            this.shape = t;
+            this.drawedMarkerConfig = config;
+            this.uid = uid;
+        }
+    }
+
+}

BIN
android/src/main/res/drawable/gps_point.png


+ 3 - 0
android/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">RCTAMap</string>
+</resources>

BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/3d_sky_day.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/3d_sky_night.data


+ 101 - 0
ios/RCTAMap/AMap.bundle/AMap3D.bundle/3dlandscape.xml

@@ -0,0 +1,101 @@
+<Xml>
+  <XmlVerSion>v1.0</XmlVerSion>
+  <NavigationParam>
+    <!--横屏:1-->
+    <ScreenDirection>1</ScreenDirection>
+    <!--相机角度多少帧会跟随道路朝向,单位“帧”,10帧/秒-->
+    <InterpolationFrame>30</InterpolationFrame>
+    <!--相机默认仰角(20-80)-->
+    <DefaultTitle>70</DefaultTitle>
+    <!--相机推近后的到地面的默认初始距离(米)-->
+    <DefaultCamerah>40</DefaultCamerah>
+    <!--相机角度前置车标多少米-->
+    <ForwardDis0>20</ForwardDis0>
+    <!--相机角度前置车标多少米(针对掉头)-->
+    <ForwardDis1>10</ForwardDis1>
+
+    <!--距离语音点多少米开始下压,0不检测语音点-->
+    <DisBeforeSound>100</DisBeforeSound>
+    <!--走过语音点多少米后开始抬起-->
+    <DisAfterSound>100</DisAfterSound>
+    <!--路口三维推近仰角(20-80)-->
+    <SoundTitle>70</SoundTitle>
+    <!--相机推近后的到地面的最小距离(米)-->
+    <SoundCamerah>40</SoundCamerah>
+
+    <!--距离Pick点多少米开始下压,0不检测Pick点-->
+    <DisBeforePick>100</DisBeforePick>
+    <!--走过Pick点多少米后开始抬起-->
+    <DisAfterPick>100</DisAfterPick>
+    <!--Pick推近最小仰角(20-80)-->
+    <PickTitle>75</PickTitle>
+    <!--相机推近后的到地面的最小距离(米)-->
+    <PickCamerah>3.0</PickCamerah>
+    <!--距离DisBeforePick前的Pick采样间隔(米/帧),实际采样间隔再加上车速-->
+    <PickInterval>4</PickInterval>
+
+    <!--完成下压的限制距离(米)-->
+    <LimitDis>10</LimitDis>
+    
+    <!--转弯箭头距离车位置多远开始显示-->
+    <TrunPicMaxDis>250</TrunPicMaxDis>
+    <!--转弯提示文字距离车位置多远开始不显示-->
+    <TrunPicMinDis>25</TrunPicMinDis>
+    <!--转弯提示文字的大小,单位"像素"-->
+    <TrunPicSize>50</TrunPicSize>
+
+    <!--10米比例尺车标宽度,单位"米"-->
+    <CarWidth>6.5</CarWidth>
+
+    <!--车道线宽,单位"米"-->
+    <RoadLineWidth>7.0</RoadLineWidth>
+    <!--车道线颜色-->
+    <LineColorRed>0</LineColorRed>
+    <LineColorGreen>174</LineColorGreen>
+    <LineColorBlue>255</LineColorBlue>
+    <LineColorAlpha>204</LineColorAlpha>
+
+    <!--方向线向前长度,单位"米"-->
+    <LineforwardLength>50</LineforwardLength>
+    <!--方向线向后长度,单位"米"-->
+    <LinebackLength>60</LinebackLength>
+    <!--方向线宽度,单位"米"-->
+    <LineWidth>7.0</LineWidth>
+    <!--车道线融合(0-255,0全透,暂无效)-->
+    <LineAlpha>100</LineAlpha>
+    
+  </NavigationParam>
+  <AnimateParam>
+    <!--二维进入三维,蒙板颜色红色分量[0,255]-->
+    <ColorInRed>29</ColorInRed>
+    <!--二维进入三维,蒙板颜色绿色分量[0,255]-->
+    <ColorInGreed>30</ColorInGreed>
+    <!--二维进入三维,蒙板颜色蓝色分量[0,255]-->
+    <ColorInBlue>26</ColorInBlue>
+    <!--二维动画帧数-->
+    <FrameIn2d>4</FrameIn2d>
+    <!--三维动画帧数-->
+    <FrameIn3d>6</FrameIn3d>
+
+    <!--三维退出二维,蒙板颜色红色分量[0,255]-->
+    <ColorOutRed>29</ColorOutRed>
+    <!--三维退出二维,蒙板颜色绿色分量[0,255]-->
+    <ColorOutGreed>30</ColorOutGreed>
+    <!--三维退出二维,蒙板颜色蓝色分量[0,255]-->
+    <ColorOutBlue>26</ColorOutBlue>
+    <!--二维动画帧数-->
+    <FrameOut2d>2</FrameOut2d>
+    <!--三维动画帧数-->
+    <FrameOut3d>3</FrameOut3d>
+
+    <!--2d透明度变化范围起始值[0,255]-->
+    <AlphaBegin2d>60</AlphaBegin2d>
+    <!--2d透明度变化范围结束值[0,255]-->
+    <AlphaEnd2d>120</AlphaEnd2d>
+    <!--透明度变化范围起始值[0,255]-->
+    <AlphaBegin3d>180</AlphaBegin3d>
+    <!--透明度变化范围结束值[0,255]-->
+    <AlphaEnd3d>100</AlphaEnd3d>
+    
+  </AnimateParam> 
+</Xml>

+ 101 - 0
ios/RCTAMap/AMap.bundle/AMap3D.bundle/3dportrait.xml

@@ -0,0 +1,101 @@
+<Xml>
+  <XmlVerSion>v1.0</XmlVerSion>
+  <NavigationParam>
+    <!--竖屏:0-->
+    <ScreenDirection>0</ScreenDirection>
+    <!--相机角度多少帧会跟随道路朝向,单位“帧”,10帧/秒-->
+    <InterpolationFrame>30</InterpolationFrame>
+    <!--相机默认仰角(20-80)-->
+    <DefaultTitle>65</DefaultTitle>
+    <!--相机推近后的到地面的默认初始距离(米)-->
+    <DefaultCamerah>50</DefaultCamerah>
+    <!--相机角度前置车标多少米-->
+    <ForwardDis0>20</ForwardDis0>
+    <!--相机角度前置车标多少米(针对掉头)-->
+    <ForwardDis1>10</ForwardDis1>
+
+    <!--距离语音点多少米开始下压,0不检测语音点-->
+    <DisBeforeSound>100</DisBeforeSound>
+    <!--走过语音点多少米后开始抬起-->
+    <DisAfterSound>100</DisAfterSound>
+    <!--路口三维推近仰角(20-80)-->
+    <SoundTitle>65</SoundTitle>
+    <!--相机推近后的到地面的最小距离(米)-->
+    <SoundCamerah>50</SoundCamerah>
+
+    <!--距离Pick点多少米开始下压,0不检测Pick点-->
+    <DisBeforePick>100</DisBeforePick>
+    <!--走过Pick点多少米后开始抬起-->
+    <DisAfterPick>100</DisAfterPick>
+    <!--Pick推近最小仰角(20-80)-->
+    <PickTitle>70</PickTitle>
+    <!--相机推近后的到地面的最小距离(米)-->
+    <PickCamerah>3.0</PickCamerah>
+    <!--距离DisBeforePick前的Pick采样间隔(米/帧),实际采样间隔再加上车速-->
+    <PickInterval>4</PickInterval>
+
+    <!--完成下压的限制距离(米)-->
+    <LimitDis>10</LimitDis>
+    
+    <!--转弯箭头距离车位置多远开始显示-->
+    <TrunPicMaxDis>250</TrunPicMaxDis>
+    <!--转弯提示文字距离车位置多远开始不显示-->
+    <TrunPicMinDis>25</TrunPicMinDis>
+    <!--转弯提示文字的大小,单位"像素"-->
+    <TrunPicSize>50</TrunPicSize>
+
+    <!--10米比例尺车标宽度,单位"米"-->
+    <CarWidth>6.5</CarWidth>
+
+    <!--车道线宽,单位"米"-->
+    <RoadLineWidth>7.0</RoadLineWidth>
+    <!--车道线颜色-->
+    <LineColorRed>0</LineColorRed>
+    <LineColorGreen>174</LineColorGreen>
+    <LineColorBlue>255</LineColorBlue>
+    <LineColorAlpha>204</LineColorAlpha>
+
+    <!--方向线向前长度,单位"米"-->
+    <LineforwardLength>60</LineforwardLength>
+    <!--方向线向后长度,单位"米"-->
+    <LinebackLength>60</LinebackLength>
+    <!--方向线宽度,单位"米"-->
+    <LineWidth>7.0</LineWidth>
+    <!--车道线融合(0-255,0全透,暂无效)-->
+    <LineAlpha>100</LineAlpha>
+    
+  </NavigationParam>
+  <AnimateParam>
+    <!--二维进入三维,蒙板颜色红色分量[0,255]-->
+    <ColorInRed>29</ColorInRed>
+    <!--二维进入三维,蒙板颜色绿色分量[0,255]-->
+    <ColorInGreed>30</ColorInGreed>
+    <!--二维进入三维,蒙板颜色蓝色分量[0,255]-->
+    <ColorInBlue>26</ColorInBlue>
+    <!--二维动画帧数-->
+    <FrameIn2d>4</FrameIn2d>
+    <!--三维动画帧数-->
+    <FrameIn3d>6</FrameIn3d>
+
+    <!--三维退出二维,蒙板颜色红色分量[0,255]-->
+    <ColorOutRed>29</ColorOutRed>
+    <!--三维退出二维,蒙板颜色绿色分量[0,255]-->
+    <ColorOutGreed>30</ColorOutGreed>
+    <!--三维退出二维,蒙板颜色蓝色分量[0,255]-->
+    <ColorOutBlue>26</ColorOutBlue>
+    <!--二维动画帧数-->
+    <FrameOut2d>2</FrameOut2d>
+    <!--三维动画帧数-->
+    <FrameOut3d>3</FrameOut3d>
+
+    <!--2d透明度变化范围起始值[0,255]-->
+    <AlphaBegin2d>60</AlphaBegin2d>
+    <!--2d透明度变化范围结束值[0,255]-->
+    <AlphaEnd2d>120</AlphaEnd2d>
+    <!--透明度变化范围起始值[0,255]-->
+    <AlphaBegin3d>180</AlphaBegin3d>
+    <!--透明度变化范围结束值[0,255]-->
+    <AlphaEnd3d>100</AlphaEnd3d>
+    
+  </AnimateParam> 
+</Xml>

BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/cross_bg.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/cross_bg_day.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/cross_bg_night.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/d_yellow.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/d_yellow_day.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/d_yellow_night.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/grass_day.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/grass_night.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/road_bottom.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/road_bottom_day.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/road_bottom_night.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/roadbk_main.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/roadbk_main_day.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/VM3DRes/roadbk_main_night.png


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/bktile.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/bktile_n.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/building.data


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
ios/RCTAMap/AMap.bundle/AMap3D.bundle/config_1_1_1470722888.data


+ 1 - 0
ios/RCTAMap/AMap.bundle/AMap3D.bundle/config_2_1_1470363686.data

@@ -0,0 +1 @@
+{"data":[{"mapmode":0,"maptime":0,"mapstate":6,"channel":0,"style":"0","stylefile":"style_17_10","iconsfile":"0"},{"mapmode":0,"maptime":1,"mapstate":6,"channel":0,"style":"0","stylefile":"style_17_10","iconsfile":"0"},{"mapmode":1,"maptime":0,"mapstate":6,"channel":0,"style":"0","stylefile":"style_17_10","iconsfile":"0"},{"mapmode":1,"maptime":1,"mapstate":6,"channel":0,"style":"0","stylefile":"style_17_10","iconsfile":"0"},{"mapmode":2,"maptime":0,"mapstate":6,"channel":0,"style":"0","stylefile":"style_17_10","iconsfile":"0"},{"mapmode":2,"maptime":1,"mapstate":6,"channel":0,"style":"0","stylefile":"style_17_10","iconsfile":"0"}]}

BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/dash.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/dash_cd.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/dash_tq.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_11_12_1488521704.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_1_12_1498048291.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_26_10_1476066932.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_27_10_1475031813.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_2_12_1498048312.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_3_12_1498048330.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_4_12_1488521409.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_50_10_1470645645.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_5_12_1488354051.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_6_12_1497253591.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_7_12_1497253551.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_8_12_1498048348.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/icons_9_10_1476066932.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/lineround.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/roadarrow.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/search_scenic_icon.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_100_10_1497254453.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_10_10_1472718686.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_12_10_1467006104.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_13_10_1497252546.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_14_10_1497252572.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_15_10_1497583771.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_17_10_1488360312.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_1_10_1498047646.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_30_10_1498047712.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_31_10_1498047749.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_32_10_1498047781.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_33_10_1498047815.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_3_10_1497252336.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_4_10_1498463093.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_50_10_1470645645.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_5_10_1498463124.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_6_10_1497252523.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/style_8_10_1497252659.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tbl.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tbl_l.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tbl_n.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tgl.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tgl_l.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tgl_n.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_amble.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_congestion.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_null.data


BIN
ios/RCTAMap/AMap.bundle/AMap3D.bundle/tmc_blind_severe_congestion.data


Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно