一、组件开发前准备
首先,新建高德地图开发者账号,获取地图的key。
进入自己的高德开发账号,点击‘创建新应用’
创建应用完成点击右上角的添加新key
发布版SHA1以及调试版SHA1获取:
1、打开android studio 找到Terminal并打开,或者在最下面找到Terminal 如下图:
2、 输入命令 C: 进入c盘;
3、接着 输入命令 cd Users\Administrator 其中Administrator是自己的用户名 Administrator文件下有个.adnroid文件, 输入命令 cd .android,最后就找到了.android,如图:
4、输入命令 keytool -list -v -keystore debug.keystore 其中debug.keystore是studio默认的keystore,按回车,然后输入秘钥:android(系统默认) 回车(秘钥库口令是看不到的)如下图:
这样就成功获取到开发版的SHA1值了
二、获取发布版的SHA1:
获取发布版的SHA1,跟获取开发版的SHA1的1、2、3步骤一样,不一样的地方就是第4步稍微不同而已。
1、同上;
2、同上;
3、同上;
4、输入命令 keytool -list -v -keystore 文件目录\自己的签名文件 比如我的:keytool -list -v -keystore E:\签名文件\android.keystore ,接着按回车,然后输入秘钥:(我只知道我的,哈哈) 回车(秘钥库口令是看不到的)如下图:
这样就成功获取到发布版的SHA1值了
在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
在app的build.gradle中添加相关依赖:
二、组件开发
1、自定义MapView控件
新建布局文件location_layout.xml。布局文件里主要放了一个mapView控件。
新建WeexMapView继承LinearLayout类,开发一个自定义的组合组件。
/*定位模式设置*/
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()方法中注册组件。
三、组件主要功能及使用方法
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);
参数是一个坐标的集合