Android仿微信地图定位和位置选择(上)

一、地图集成

        集成腾讯地图SDK,https://lbs.qq.com/,申请AppKey。

1、dependencies

implementation 'com.tencent.map.geolocation:TencentLocationSdk-openplatform:7.2.6'
implementation 'com.tencent.map:tencent-map-vector-sdk:4.3.4'

2、AndroidManifest.xml

<application
	<meta-data
        android:name="TencentMapSDK"
        android:value="*****-*****-*****-*****-*****-*****"/>
</application>

3、权限

<!--腾讯地图 SDK 要求的权限(开始)-->
<!--访问网络获取地图服务-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--检查网络可用性-->
<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.WRITE_EXTERNAL_STORAGE"/>
<!--获取 device id 辨别设备-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--腾讯地图 SDK 要求的权限(结束)-->

注意:这块除了AndroidManifest.xml权限之外还需要动态定义以下权限:

Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.READ_PHONE_STATE

另外还需要打开手机定位功能:

public static void showSystemGPS(Activity activity) {
    if (!isOpenGPS()) {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        WeDaActivity a = (WeDaActivity) activity;
        a.startActivityForResult(intent, ConstantUtils.REQUEST_SYSTEM_OPEN_GPS, (requestCode, resultCode, data) -> {
            if (isOpenGPS()) {
                UIUtils.showToast(activity, "GPS打开成功");
            } else {
                UIUtils.showToast(activity, "GPS打开失败");
            }
        });
    } else {
        UIUtils.showToast(activity, "GPS已经打开了");
    }
}

public static boolean isOpenGPS() {
    LocationManager locationManager
            = (LocationManager) ApplicationUtils.getContext().getSystemService(Context.LOCATION_SERVICE);
    return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}

4、混淆

-keep class com.tencent.tencentmap.**{*;}
-keep class com.tencent.map.**{*;}
-keep class com.tencent.beacontmap.**{*;}
-keep class navsns.**{*;}
-dontwarn com.qq.**
-dontwarn com.tencent.**

二、定义视图布局

1、地图控制布局

<com.tencent.tencentmap.mapsdk.maps.MapView
    android:id="@+id/mapview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

2、搜索框控件布局

<EditText
    android:id="@+id/et_search"
    android:layout_width="match_parent"
    android:layout_height="33dp"
    android:layout_marginLeft="15dp"
    android:layout_marginTop="10dp"
    android:layout_marginRight="15dp"
    android:layout_marginBottom="10dp"
    android:layout_toLeftOf="@+id/tv_cancel_search"
    android:background="@drawable/shape_search_map"
    android:focusable="false"
    android:focusableInTouchMode="true"
    android:gravity="center"
    android:hint="@string/map_search_hint"
    android:imeOptions="actionSearch"
    android:inputType="text"
    android:paddingLeft="10dp"
    android:singleLine="true"
    android:textColor="@color/c_181818"
    android:textSize="15sp" />

3、进度条控件布局

<ProgressBar
    android:id="@+id/pb_progress"
    style="@android:style/Widget.Holo.ProgressBar"
    android:layout_width="70dp"
    android:layout_height="70dp"
    android:layout_gravity="center"
    android:visibility="visible" />

 三、绑定地图生命周期

    @Override
    public void onDestroy() {
        mapView.onDestroy();
        super.onDestroy();
        tencentMap.removeTencentMapGestureListener(mapGestureListener);
    }

    @Override
    public void onPause() {
        mapView.onPause();
        super.onPause();
    }

    @Override
    public void onResume() {
        mapView.onResume();
        super.onResume();
    }

    @Override
    public void onStop() {
        mapView.onStop();
        super.onStop();
    }

    @Override
    public void onStart() {
        mapView.onStart();
        super.onStart();
    }

四、请求定位

1、创建定位请求对象

mapView = view.findViewById(R.id.mapview);
tencentMap = mapView.getMap();

//创建地图请求对象
locationManager = TencentLocationManager.getInstance(context);
locationRequest = TencentLocationRequest.create();
locationRequest.setInterval(3000);

        setInterval:用于设置连续定位的请求的间隔时间,这里设置3000毫秒回调一次。如果只需要定位一次,则调用locationManager.removeUpdates(this);取消连续定位回调。

2、请求定位信息

private void requestLocationUpdates() {
    int error = locationManager.requestLocationUpdates(
            locationRequest, LocationMapFragment.this);
    String des = "";
    switch (error) {
        case 0:
            des = "成功注册监听器";
            break;
        case 1:
            des = "设备缺少使用腾讯定位服务需要的基本条件";
            break;
        case 2:
            des = "manifest 中配置的 key 不正确";
            break;
        case 3:
            des = "自动加载libtencentloc.so失败";
            break;

        default:
            break;
    }
    LogUtils.d(des);
}

五、注册回调

1、实现地图相关接口

  • LocationSource:页面显示和关闭的回调
  • TencentLocationListener:连续定位获取位置信息的回调

(1)LocationSource

@Override
public void activate(OnLocationChangedListener arg0) {
    mChangedListener = arg0;
    //页面打开,请求定位信息
    requestLocationUpdates();
}

@Override
public void deactivate() {
    //页面移出,清除位置回调
    locationManager.removeUpdates(this);
    locationManager = null;
    locationRequest = null;
    mChangedListener = null;
}

(2)TencentLocationListener

@Override
public void onLocationChanged(TencentLocation tencentLocation, int arg1, String arg2) {
    if (arg1 == TencentLocation.ERROR_OK && mChangedListener != null) { 
        Location location = new Location(tencentLocation.getProvider());
        //设置经纬度
        location.setLatitude(tencentLocation.getLatitude());
        location.setLongitude(tencentLocation.getLongitude());
        //设置精度,这个值会被设置为定位点上表示精度的圆形半径
        location.setAccuracy(tencentLocation.getAccuracy());
        //设置定位标的旋转角度,注意 tencentLocation.getBearing() 只有在 gps 时才有可能获取
        location.setBearing((float) tencentLocation.getBearing());
        //将位置信息返回给地图
        mChangedListener.onLocationChanged(location);
        //移出回调,只请求一次,如果需要连续定位,删除这行代码
        locationManager.removeUpdates(this);
    } else {
        LogUtils.d("onLocationChanged error");
    }
}

@Override
public void onStatusUpdate(String s, int i, String s1) {
    String desc = "";
    switch (i) {
        case TencentLocationListener.STATUS_DENIED:
            desc = "权限被禁止";
            break;
        case TencentLocationListener.STATUS_DISABLED:
            desc = "模块关闭";
            break;
        case TencentLocationListener.STATUS_ENABLED:
            desc = "模块开启";
            break;
        case TencentLocationListener.STATUS_GPS_AVAILABLE:
            desc = "GPS可用,代表GPS开关打开,且搜星定位成功";
            break;
        case TencentLocationListener.STATUS_GPS_UNAVAILABLE:
            desc = "GPS不可用,可能 gps 权限被禁止或无法成功搜星";
            break;
        case TencentLocationListener.STATUS_LOCATION_SWITCH_OFF:
            desc = "位置信息开关关闭,在android M系统中,此时禁止进行wifi扫描";
            break;

        default:
            break;
    }
    LogUtils.d("location status:" + s + ", " + s1 + " " + desc);
}

4、注册相关监听

//注册手势事件
tencentMap.addTencentMapGestureListener(mapGestureListener);
tencentMap.setLocationSource(this);
tencentMap.setMyLocationEnabled(true);
tencentMap.getUiSettings().setRotateGesturesEnabled(false);
//定位结果回调
tencentMap.setOnMyLocationChangeListener(onMyLocationChangeListener);

private TencentMap.OnMyLocationChangeListener onMyLocationChangeListener = new TencentMap.OnMyLocationChangeListener() {
    @Override
    public void onMyLocationChange(Location location) {
        LogUtils.d("内置定位标点击回调");
        if (!TextUtils.isEmpty(longitude) && !TextUtils.isEmpty(latitude)) {
            //传递的定位数据源
            Double lo = StringUtils.getDouble(longitude);
            Double la = StringUtils.getDouble(latitude);
            position = new LatLng(la, lo);
            longitude = null;
            latitude = null;
        } else {
            //GPS定位源
            position = new LatLng(location.getLatitude(), location.getLongitude());
            page = 1;
        }
        moveMap(position);
        presenter.setOriginLaLng(position);
        presenter.getNearAddress(position, page, fromMarker);
    }
};

        setOnMyLocationChangeListener用户获取定位回调的结果,在注册TencentLocationListener接口后,调用requestLocationUpdates请求位置信息,触发onLocationChanged回调,在onLocationChanged中将事件通过mChangedListener.onLocationChanged传递给setOnMyLocationChangeListener回调。

        这块有两个参数longitude、latitude是用户设置的坐标信息,如果用户传递了位置,则显示地图的中心点在该位置,否则设置当前位置的信息。

六、移动地图到中心点

private void moveMap(LatLng latLng) {
    //latLng中心点的坐标信息,15表示显示地图的缩放比例
    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 15);
    tencentMap.animateCamera(cameraUpdate, new TencentMap.CancelableCallback() {
        @Override
        public void onFinish() {
            
        }

        @Override
        public void onCancel() {

        }
    });
}

七、设置Marker

        marker的设置可以自定义,也可采用系统的。

private void setMarker(LatLng latLng) {
    //设置自定义marker样式
//        MarkerOptions markerOptions = new MarkerOptions(latLng);
//        markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_location_pin));
//        markerOptions.visible(true);
//        marker = tencentMap.addMarker(markerOptions);
//        marker.setFixingPointEnable(true);

    //配置marker样式
    //HUE_BLUE:设置marker颜色为蓝色 
    MarkerOptions options = new MarkerOptions()
            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
            .position(latLng);
    marker = tencentMap.addMarker(options);
    //设置marker固定到中心点
    LatLng target = tencentMap.getCameraPosition().target;
    //坐标系转换,坐标信息转换为屏幕的中心点信息
    markerPoint = tencentMap.getProjection().toScreenLocation(target);
    marker.setFixingPointEnable(true);
    marker.setFixingPoint(markerPoint.x, markerPoint.y);
}

        注意:marker的设置需要在位置移动之后设置,因为moveMap是带有动画的异步操作,如果moveMap没执行完毕设置marker,则设置的marker无效,不显示;如果定位后手势缩放地图,则在地图上会出现多个marker。

        由于内容比较长,地图的常用基本设置就到这里结束,下篇文章介绍剩余的内容。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值