一、组件开发前准备

   首先,新建高德地图开发者账号,获取地图的key。

   进入自己的高德开发账号,点击‘创建新应用’  

   

Android 高德地图离线地图_json

创建应用完成点击右上角的添加新key

 

Android 高德地图离线地图_json_02

 

Android 高德地图离线地图_android_03

发布版SHA1以及调试版SHA1获取:

1、打开android studio 找到Terminal并打开,或者在最下面找到Terminal 如下图:

 

Android 高德地图离线地图_json_04

2、 输入命令  C:    进入c盘;

3、接着 输入命令   cd Users\Administrator   其中Administrator是自己的用户名  Administrator文件下有个.adnroid文件, 输入命令   cd  .android,最后就找到了.android,如图:

 

Android 高德地图离线地图_android_05

 

4、输入命令  keytool -list -v -keystore debug.keystore  其中debug.keystore是studio默认的keystore,按回车,然后输入秘钥:android(系统默认)    回车(秘钥库口令是看不到的)如下图:

 

Android 高德地图离线地图_android_06

这样就成功获取到开发版的SHA1值了

二、获取发布版的SHA1:

获取发布版的SHA1,跟获取开发版的SHA1的1、2、3步骤一样,不一样的地方就是第4步稍微不同而已。

1、同上;

2、同上;

3、同上;

4、输入命令  keytool -list -v -keystore 文件目录\自己的签名文件 比如我的:keytool -list -v -keystore E:\签名文件\android.keystore ,接着按回车,然后输入秘钥:(我只知道我的,哈哈)    回车(秘钥库口令是看不到的)如下图:

 

Android 高德地图离线地图_json_07

这样就成功获取到发布版的SHA1值了

 

Android 高德地图离线地图_Android 高德地图离线地图_08

 

在AndroidManifest.xml中添加相应的权限

<!-- 允许程序打开网络套接字-->
<uses-permission android:name="android.permission.INTERNET" />
 <!-- 允许程序设置内置sd卡的写权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <!-- 允许程序获取网络状 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 允许程序访问WiFi网络信息-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 允许程序读写手机状态和身份-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 允许程序访问CellID或WiFi热点来获取粗略的位置-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

添加高德地图的apiKey

 

Android 高德地图离线地图_android_09

在app的build.gradle中添加相关依赖:

 

Android 高德地图离线地图_Android 高德地图离线地图_10

 

Android 高德地图离线地图_Android 高德地图离线地图_11

二、组件开发

1、自定义MapView控件

  新建布局文件location_layout.xml。布局文件里主要放了一个mapView控件。

Android 高德地图离线地图_json_12

  

  新建WeexMapView继承LinearLayout类,开发一个自定义的组合组件。

  

Android 高德地图离线地图_Android 高德地图离线地图_13

/*定位模式设置*/
public void setMapModel(int model){
    switch (model){
        case 1://连续定位、蓝点不会移动到地图中心点,定位点依照设备方向旋转,并且蓝点会跟随设备移动。
            myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
            break;
        case 2://连续定位、且将视角移动到地图中心点,定位蓝点跟随设备移动。(1秒1次定位)
            myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);
            break;
        case 3://连续定位、且将视角移动到地图中心点,地图依照设备方向旋转,定位点会跟随设备移动。(1秒1次定位)
            myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_MAP_ROTATE);
            break;
        case 4://连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)默认执行此种模式。
            myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);
            break;
    }
    aMap.setMyLocationStyle(myLocationStyle);
}
//设置默认定位按钮是否显示,非必需设置。
public void showLocationButton(boolean isShow){
    aMap.getUiSettings().setMyLocationButtonEnabled(isShow);
}
// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
public void showLocationPoint(boolean isShow){
    aMap.setMyLocationEnabled(isShow);
}
public void setMapType(int type){
    switch (type){
        case 1:
            aMap.setMapType(AMap.MAP_TYPE_NORMAL);// 设置普通地图模式
            break;
        case 2:
            aMap.setMapType(AMap.MAP_TYPE_NAVI);// 设置导航地图模式
            break;
        case 3:
            aMap.setMapType(AMap.MAP_TYPE_NIGHT);// 设置夜景地图模式
            break;
        case 4:
            aMap.setMapType(AMap.MAP_TYPE_SATELLITE);// 设置卫星地图模式
            break;
    }
}
 public void onDestroy(){
    mapView.onDestroy();
 }
 public void onResume(){
     mapView.onResume();
 }
 public void onPause(){
     mapView.onPause();
 }
 public void onCreate(Bundle outState){
     mapView.onCreate(outState);
 }
 public void onSaveInstanceState(Bundle outState){
     mapView.onSaveInstanceState(outState);
 }

2、开发WXMapComponent组件

新建WXMapComponent继承 WXComponent<WeexMapView>
   WXMapComponent.java代码如下:
   public class WXMapComponent extends WXComponent<WeexMapView> {
    WeexMapView mapView;
    WXSDKInstance wxInstance; //weex实例对象,用于获得上下文
    boolean clicked=false;
    //两个不同参数的构造方法
    public WXMapComponent(WXSDKInstance instance, WXDomObject dom, WXVContainer parent) {
        super(instance, dom, parent);
        wxInstance = instance;
    }
    public WXMapComponent(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, int type) {
        super(instance, dom, parent, type);
        wxInstance = instance;
    }
    @Override
    protected WeexMapView initComponentHostView(@NonNull Context context) {
        //获得WeexMapView的对象
        this.mapView = new WeexMapView(context);
        return this.mapView;
    }
    @Override
    protected void onCreate() {
        super.onCreate();
    }
    @Override
    public void onActivityDestroy() {
        super.onActivityDestroy();

    }
    /*定位模式设置*/
    @WXComponentProp(name = "model")
    public void setMapModel(int model) {
       mapView.setMapModel(model);
    }
    //设置默认定位按钮是否显示,非必需设置。
    @WXComponentProp(name = "showLocationButton")
    public void showLocationButton(boolean isShow){
        mapView.showLocationButton(isShow);
    }
    // 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
    @WXComponentProp(name = "showLocationPoint")
    public void showLocationPoint(boolean isShow)
    {
        mapView.showLocationPoint(isShow);
    }
    /**
     *设置地图模式:夜间模式,卫星图模式等
     * @param type
     */
    @WXComponentProp(name = "mapType")
    public void setMapType(int type){
        mapView.setMapType(type);
    }
    /**
     * 在地图上显示提示信息
     * @param lnt 经度
     * @param lat 纬度
     * @param title 标题
     * @param content 内容
     * @param draggable 是否可拖动
     * @param setFlat 是否平贴地图
     * @param isAnimation 是否使用动画
     * @param duration 动画时间长度
     * @param clickCallback marker点击事件的js回调
     * @param dragCallback  marker拖动事件的js回调
     */
    @JSMethod(uiThread = true)
    public void addMarker(float lnt, float lat, String title, String content,
                          boolean draggable, boolean setFlat, boolean isAnimation, long duration,
                          JSCallback clickCallback,JSCallback dragCallback) {
        LatLng latLng = new LatLng(lnt,lat);
        MarkerOptions markerOption = new MarkerOptions();
        markerOption.position(latLng);
        markerOption.title(title).snippet(content);
        markerOption.draggable(draggable);//设置Marker可拖动
        markerOption.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory
                .decodeResource(wxInstance.getContext().getResources(), R.drawable.cercle)));
        // 将Marker设置为贴地显示,可以双指下拉地图查看效果
        markerOption.setFlat(setFlat);//设置marker平贴地图效果
        Marker marker=mapView.getaMap().addMarker(markerOption);
        if(isAnimation){
            Animation animation = new RotateAnimation(marker.getRotateAngle(),marker.getRotateAngle()+180,0,0,0);
            animation.setDuration(duration);
            animation.setInterpolator(new LinearInterpolator());
            marker.setAnimation(animation);
            marker.startAnimation();
        }
        /*点击事件*/
        mapView.getaMap().setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                marker.showInfoWindow();
                return true;
            }
        });
        /*拖动事件*/
        mapView.getaMap().setOnMarkerDragListener(new AMap.OnMarkerDragListener() {
            @Override
            public void onMarkerDragStart(Marker marker) {
            }
            @Override
            public void onMarkerDrag(Marker marker) {
            }
            @Override
            public void onMarkerDragEnd(Marker marker) {
            }
        });
    }
    /**
     * @param lat 经度
     * @param lng 纬度
     * @param radius 半径
     * @param strokeWidth 边框宽度
     * 添加圆形区域
     */
    @JSMethod(uiThread = true)
    public void addCircle(float lat,float lng,int radius,int strokeWidth){
     LatLng latLng=new LatLng(lat,lng);
     mapView.getaMap().addCircle(new CircleOptions().
             center(latLng).radius(radius).fillColor(Color.BLUE).
             strokeColor(Color.RED).strokeWidth(strokeWidth));
    }

    /**
     * 在地图上绘制线
     * @param list 坐标数组
     * @throws JSONException
     */
    @JSMethod(uiThread = true)
    public void addLine(ArrayList list) throws JSONException {
        ArrayList<LatLng> latLngList=new ArrayList<LatLng>();
        for(int i=0;i<list.size();i++){
            com.alibaba.fastjson.JSONObject jsonObj=(com.alibaba.fastjson.JSONObject) list.get(i);
            /*H5传过来的是BigDecimal,BigDecimal转换成float类型*/
            BigDecimal bigLat= (BigDecimal) jsonObj.get("latitude");
            BigDecimal bigLng= (BigDecimal) jsonObj.get("longitude");
            float lat=bigLat.floatValue();
            float lng=bigLng.floatValue();
//            Log.d(lat+"-"+lng,"经纬度");
            LatLng latLng=new LatLng(lat,lng);
            latLngList.add(latLng);
        }
        mapView.getaMap().addPolyline(new PolylineOptions().addAll(latLngList).width(10).color(Color.BLUE));
    }
    /**
     * 绘制热力图图层
     * @param list
     */
    @JSMethod(uiThread = true)
    public void addTileOverlay(ArrayList list){
        ArrayList<LatLng> latLngList=new ArrayList<LatLng>();
        for(int i=0;i<list.size();i++){
            com.alibaba.fastjson.JSONObject jsonObj=(com.alibaba.fastjson.JSONObject) list.get(i);
            /*H5传过来的是BigDecimal,BigDecimal转换成float类型*/
            BigDecimal bigLat= (BigDecimal) jsonObj.get("latitude");
            BigDecimal bigLng= (BigDecimal) jsonObj.get("longitude");
            float lat=bigLat.floatValue();
            float lng=bigLng.floatValue();
//            Log.d(lat+"-"+lng,"经纬度");
            LatLng latLng=new LatLng(lat,lng);
            latLngList.add(latLng);
        }
        // 构建热力图 HeatmapTileProvider
        HeatmapTileProvider.Builder builder = new HeatmapTileProvider.Builder();
        builder.data(latLngList); // 设置热力图绘制的数据
//                .gradient(A); // 设置热力图渐变,有默认值 DEFAULT_GRADIENT,可不设置该接口
// Gradient 的设置可见参考手册
// 构造热力图对象
        HeatmapTileProvider heatmapTileProvider = builder.build();
        // 初始化 TileOverlayOptions
        TileOverlayOptions tileOverlayOptions = new TileOverlayOptions();
        tileOverlayOptions.tileProvider(heatmapTileProvider); // 设置瓦片图层的提供者
// 向地图上添加 TileOverlayOptions 类对象
        mapView.getaMap().addTileOverlay(tileOverlayOptions);
    }
    @JSMethod(uiThread = true)
    public void setInfoWindowAdapter(){
      mapView.getaMap().setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
          /**
           * 监听自定义infowindow窗口的infowindow事件回调
           */
          @Override
          public View getInfoWindow(Marker marker) {
              return null;
          }
          View infoWindow = null;
          /**
           * 监听自定义infowindow窗口的infocontents事件回调
           */
          @Override
          public View getInfoContents(Marker marker) {
              if(infoWindow == null) {
                  infoWindow = LayoutInflater.from(wxInstance.getContext()).inflate(
                          R.layout.custom_info_window, null);
              }
//              render(marker, infoWindow);
              return infoWindow;
           //加载custom_info_window.xml布局文件作为InfoWindow的样式
          }
      });
      mapView.getaMap().setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
          @Override
          public void onInfoWindowClick(Marker marker) {
             String content=marker.getSnippet().toString();
              Toast.makeText(wxInstance.getContext(),content,Toast.LENGTH_LONG).show();
          }
      });
    }
}

   值得注意的一点是在H5界面的json数组通过组件的接口传到原生需要用ArrayList接收,在把ArrayList中的每一个元素转换成com.alibaba.fastjson.JSONObject。通过JSONObject的get("JsonName"),可以获得存在json中的值。

for(int i=0;i<list.size();i++){
            com.alibaba.fastjson.JSONObject jsonObj=(com.alibaba.fastjson.JSONObject) list.get(i);
            /*H5传过来的是BigDecimal,BigDecimal转换成float类型*/
            BigDecimal bigLat= (BigDecimal) jsonObj.get("latitude");
            BigDecimal bigLng= (BigDecimal) jsonObj.get("longitude");
            float lat=bigLat.floatValue();
            float lng=bigLng.floatValue();
//            Log.d(lat+"-"+lng,"经纬度");
            LatLng latLng=new LatLng(lat,lng);
            latLngList.add(latLng);
        }

3、开发WXMapModule组件

WXLocationModule 继承WXModule类,其中添加@JSMethod的方法可以在H5界面调用。

 

 

public class WXLocationModule extends WXModule{
   /*
    * 通过经纬度获得对应的位置信息
    */
    @JSMethod
    public void getLocationInfo(float longitude,float latitude,final JSCallback callback) {
        GeocodeSearch geocoderSearch = new GeocodeSearch(mWXSDKInstance.getContext());//位置搜对象
        LatLonPoint point=new LatLonPoint(longitude,latitude);//坐标
        float range=200;//范围
        RegeocodeQuery query=new RegeocodeQuery(point,200,GeocodeSearch.AMAP);
        geocoderSearch.getFromLocationAsyn(query);
        geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
            @Override
            public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {//获得位置信息的回调方法
                Map<String, Object> map = new HashMap<>();
                map.put("locationInfo", regeocodeResult);
                callback.invokeAndKeepAlive(map);
            }
            @Override
            public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
            }
        });
    }
    /*
    *地址转换成坐标
    */
    @JSMethod
    public void getLocationByName(String name,String cityCode,final JSCallback callback){
        GeocodeSearch geocoderSearch = new GeocodeSearch(mWXSDKInstance.getContext());//位置搜对象
        // name表示地址,第二个参数表示查询城市,中文或者中文全拼,citycode、adcode
        GeocodeQuery query = new GeocodeQuery(name,cityCode);
        geocoderSearch.getFromLocationNameAsyn(query);
        geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
            @Override
            public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
            }
            @Override
            public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
                Map<String, Object> map = new HashMap<>();
                map.put("location", geocodeResult);
                callback.invokeAndKeepAlive(map);
            }
        });
    }
    /**
     * @param pace 地点
     * @param type 类型
     */
    @JSMethod
    public void getWeatherInfo(String pace,String type){
    //检索参数为城市和天气类型,实况天气为WEATHER_TYPE_LIVE、天气预报为WEATHER_TYPE_FORECAST
    }
    /**
     * 计算两点之间的距离
     * @param latLng1
     * @param latLng2
     */
    @JSMethod
    public void getDistance(LatLng latLng1,LatLng latLng2){
        float distance = AMapUtils.calculateLineDistance(latLng1,latLng2);
    }

    /**
     * 下载离线地图
     * @param cityname
     */
    @JSMethod
    public void downloadMapOffline(String cityname) throws AMapException {
//构造OfflineMapManager对象
            amapManager = new OfflineMapManager(mWXSDKInstance.getContext(), new OfflineMapManager.OfflineMapDownloadListener() {
            @Override
            public void onDownload(int i, int i1, String s) {
            }
            @Override
            public void onCheckUpdate(boolean b, String s) {
            }

            @Override
            public void onRemove(boolean b, String s, String s1) {
            }
        });
//按照citycode下载
//        amapManager.downloadByCityCode(String citycode);
//按照cityname下载
        amapManager.downloadByCityName(cityname);
//        amapManager.pause();
//        amapManager.stop();
        // 设置应用单独的地图存储目录
//        MapsInitializer.sdcardDir = "自定义的目录";
    }

    /**
     * @param cityname
     * @throws AMapException
     */
    @JSMethod
    public void updateOfflineCityByName(String cityname) throws AMapException {
        //通过updateOfflineCityByName方法判断离线地图数据是否存在更新
        amapManager.updateOfflineCityByName(cityname);
    }
    public void deleteOfflineCityByName(String cityName){
        //删除某一城市的离线地图包
        amapManager.remove(cityName);
    }
    /**
     * 获取下载的离线地图列表
     */
    @JSMethod
    public void getDownloadOfflineMapCityList(){
//        获取城市列表
        ArrayList<OfflineMapCity> offlineMapCityList = amapManager.getOfflineMapCityList();
//        获取省列表
        ArrayList<OfflineMapProvince> offlineMapProvinceList = amapManager.getOfflineMapProvinceList();
//        获取已下载城市列表
        ArrayList<OfflineMapCity> downloadOfflineMapCityList = amapManager.getDownloadOfflineMapCityList();
//        获取正在或等待下载城市列表
        ArrayList<OfflineMapCity> downloadingCityList = amapManager.getDownloadingCityList();
    }
}

 

4、注册Component和Module

在新建myAplication继承Application,在其onCreate()方法中注册组件。

 

Android 高德地图离线地图_android_14

 

三、组件主要功能及使用方法

1)WXlocationModule使用
  在H5中引入组件:
  var location=weex.requireModule('Location');
1、根据描述和城市编码获得坐标信息
location.getLocationByName('廊坊市广阳区新奥科技园B座','0316',function (res) {
     self.point=res.location.geocodeAddressList[0].latLonPoint;//获得坐标信息
    });2、根据坐标获得位置信息
  location.getLocationInfo(lat,lnt,function (res) {
    var info=res;
   });3、获得天气信息
  location.getWeatherInfo('北京市','now',function (res) {
    var weatherInfo=res;
  });4、得到两个坐标点之间的距离
 location.getDistance(latLng1,latLng2,function (res) {
    var distance=res;
 });5、离线地图相关
location.downloadMapOffline(cityname);//下载离线地图,可设置下载路径
  location.deleteOfflineCityByName(cityName);//删除离线地图
  location.getDownloadOfflineMapCityList()//获得离线地图列表

2)WXMapComponent使用

   在H5中使用组件:

<map ref="myMap" style="width: 750px;height: 1300px" showLocationButton="true" model="1" showLocationPoint="true" mapType="1">
</map>
 showLocationButton:是否显示定位按钮
    Model:定位方式
    mapType:地图模式(卫星图,夜间图等)
showLocationPoint:是否显示当前所在点的标示图

1、显示地图上某个坐标处的标示,点击显示提示信息

this.$refs.myMap.addMarker(lat, lnt, '新奥科技园', '新奥科技园B座',
    true, false, true, 1.00,      //参数:经度、纬度、标题、内容、是否可拖动、是否平贴地图、是否使用动画、动画时间
    function (res) {//点击事件
     modal.toast({message:'click'})
    },function (res) {//拖动事件
      modal.toast({message:'drag'})
    });

2、以某个坐标点为圆心,画一个圆形图

self.$refs.myMap.addCircle(self.point.latitude,self.point.longitude,1000,20);

     第一个和第二个参数分别为圆心的经度和纬度坐标,第三个参数为半径,第四个参数为圆形的线的宽度

3、在地图上绘制线

self.$refs.myMap.addLine(self.pointList);

   参数是一个坐标点的集合

4、在地图上绘制热力图层

self.$refs.myMap.addTileOverlay(self.pointList);

    参数是一个坐标的集合