Android imitation wechat map positioning and location selection

1, Map integration

        Integrate Tencent map SDK, https://lbs.qq.com/ , apply for 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. Authority

<!--Tencent map SDK Required permissions(start)-->
<!--Access the web for map services-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--Check network availability-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- visit WiFi state -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--External storage write permission is required to save the map cache-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--obtain device id Discrimination device-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--Tencent map SDK Required permissions(end)-->

Note: in addition to the AndroidManifest.xml permission, the following permissions need to be dynamically defined:

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

In addition, you need to turn on the mobile phone positioning function:

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 Open successfully");
            } else {
                UIUtils.showToast(activity, "GPS Open failed");
            }
        });
    } else {
        UIUtils.showToast(activity, "GPS It's already open");
    }
}

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

4. Confusion

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

2, Define view layout

1. Map control layout

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

2. Search box control layout

<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. Progress bar control layout

<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" />

  3, Bind map lifecycle

    @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();
    }

4, Request location

1. Create location request object

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

//Create map request object
locationManager = TencentLocationManager.getInstance(context);
locationRequest = TencentLocationRequest.create();
locationRequest.setInterval(3000);

         setInterval: used to set the interval between requests for continuous positioning. Here, a callback of 3000 milliseconds is set. If you only need to locate once, call locationManager.removeUpdates(this); Cancel continuous positioning callback.

2. Request location information

private void requestLocationUpdates() {
    int error = locationManager.requestLocationUpdates(
            locationRequest, LocationMapFragment.this);
    String des = "";
    switch (error) {
        case 0:
            des = "Successfully registered listener";
            break;
        case 1:
            des = "The device lacks the basic conditions required to use Tencent location services";
            break;
        case 2:
            des = "manifest Configured in key incorrect";
            break;
        case 3:
            des = "Automatic loading libtencentloc.so fail";
            break;

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

5, Register callback

1. Implement Map related interfaces

  • LocationSource: callback for page display and closing
  • TencentLocationListener: callback for continuously locating and obtaining location information

(1)LocationSource

@Override
public void activate(OnLocationChangedListener arg0) {
    mChangedListener = arg0;
    //The page opens to request location information
    requestLocationUpdates();
}

@Override
public void deactivate() {
    //Page out, clear position callback
    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());
        //Set latitude and longitude
        location.setLatitude(tencentLocation.getLatitude());
        location.setLongitude(tencentLocation.getLongitude());
        //Set the precision, which will be set as the circular radius representing the precision on the anchor point
        location.setAccuracy(tencentLocation.getAccuracy());
        //Set the rotation angle of the locator. Note that tencentLocation.getBearing() can only be obtained when gps is used
        location.setBearing((float) tencentLocation.getBearing());
        //Return location information to map
        mChangedListener.onLocationChanged(location);
        //Remove the callback and request only once. If continuous positioning is required, delete this line of code
        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 = "Permission is prohibited";
            break;
        case TencentLocationListener.STATUS_DISABLED:
            desc = "Module off";
            break;
        case TencentLocationListener.STATUS_ENABLED:
            desc = "Module on";
            break;
        case TencentLocationListener.STATUS_GPS_AVAILABLE:
            desc = "GPS Available, representative GPS The switch is turned on and the star search positioning is successful";
            break;
        case TencentLocationListener.STATUS_GPS_UNAVAILABLE:
            desc = "GPS Not available, possible gps Permission is prohibited or star search cannot be successful";
            break;
        case TencentLocationListener.STATUS_LOCATION_SWITCH_OFF:
            desc = "Position information switch off, in android M In the system, it is forbidden to perform at this time wifi scanning";
            break;

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

4. Register Related listening

//Register gesture events
tencentMap.addTencentMapGestureListener(mapGestureListener);
tencentMap.setLocationSource(this);
tencentMap.setMyLocationEnabled(true);
tencentMap.getUiSettings().setRotateGesturesEnabled(false);
//Location result callback
tencentMap.setOnMyLocationChangeListener(onMyLocationChangeListener);

private TencentMap.OnMyLocationChangeListener onMyLocationChangeListener = new TencentMap.OnMyLocationChangeListener() {
    @Override
    public void onMyLocationChange(Location location) {
        LogUtils.d("Built in locator click callback");
        if (!TextUtils.isEmpty(longitude) && !TextUtils.isEmpty(latitude)) {
            //Location data source passed
            Double lo = StringUtils.getDouble(longitude);
            Double la = StringUtils.getDouble(latitude);
            position = new LatLng(la, lo);
            longitude = null;
            latitude = null;
        } else {
            //GPS positioning source
            position = new LatLng(location.getLatitude(), location.getLongitude());
            page = 1;
        }
        moveMap(position);
        presenter.setOriginLaLng(position);
        presenter.getNearAddress(position, page, fromMarker);
    }
};

         SetOnMyLocationChangeListener users get the result of location callback. After registering the TencentLocationListener interface, they call the requestLocationUpdates request location information, trigger the onLocationChanged callback, and pass the event through mChangedListener.onLocationChanged to setOnMyLocationChangeListener callback in onLocationChanged.

        There are two parameters: longitude and latitude, which are the coordinate information set by the user. If the user passes the position, the center point of the map will be displayed at that position, otherwise the information of the current position will be set.

6, Move map to center point

private void moveMap(LatLng latLng) {
    //latLng coordinate information of the center point, 15 represents the zoom scale of the display map
    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 15);
    tencentMap.animateCamera(cameraUpdate, new TencentMap.CancelableCallback() {
        @Override
        public void onFinish() {
            
        }

        @Override
        public void onCancel() {

        }
    });
}

7, Set Marker

        marker settings can be customized or system.

private void setMarker(LatLng latLng) {
    //Set custom marker style
//        MarkerOptions markerOptions = new MarkerOptions(latLng);
//        markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_location_pin));
//        markerOptions.visible(true);
//        marker = tencentMap.addMarker(markerOptions);
//        marker.setFixingPointEnable(true);

    //Configure marker style
    //HUE_BLUE: set the marker color to blue 
    MarkerOptions options = new MarkerOptions()
            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
            .position(latLng);
    marker = tencentMap.addMarker(options);
    //Set marker fixed to center point
    LatLng target = tencentMap.getCameraPosition().target;
    //Coordinate system conversion, coordinate information is converted to the center point information of the screen
    markerPoint = tencentMap.getProjection().toScreenLocation(target);
    marker.setFixingPointEnable(true);
    marker.setFixingPoint(markerPoint.x, markerPoint.y);
}

        Note: the marker setting needs to be set after the position is moved, because moveMap is an asynchronous operation with animation. If moveMap does not finish setting the marker, the set marker is invalid and will not be displayed; If you gesture to zoom the map after positioning, multiple markers will appear on the map.

        Since the content is relatively long, the common basic settings of the map will end here. The next article introduces the rest.

Keywords: Android

Added by kol090 on Mon, 06 Sep 2021 04:46:49 +0300