AMapGeolocationModule.java 11.9 KB
package cn.feewee.amap3d.modules;

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.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItemV2;
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.poisearch.PoiResultV2;
import com.amap.api.services.poisearch.PoiSearchV2;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;

@SuppressWarnings("unused")
public class AMapGeolocationModule extends ReactContextBaseJavaModule implements AMapLocationListener {
    private final ReactApplicationContext reactContext;
    private final AMapLocationClientOption option = new AMapLocationClientOption();
    private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter;
    private AMapLocationClient client;
    private GeocodeSearch geocodeSearch;

    public AMapGeolocationModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @NotNull
    @Override
    public String getName() {
        return "AMapGeolocation";
    }

    @Override
    public void onLocationChanged(AMapLocation location) {
        if (location != null) {
            eventEmitter.emit("AMapGeolocation", toJSON(location));
        }
    }

    @ReactMethod
    public void init(String key, Promise promise) throws Exception {
        if (client != null) {
            client.onDestroy();
        }

        AMapLocationClient.setApiKey(key);
        AMapLocationClient.updatePrivacyShow(reactContext, true, true);
        AMapLocationClient.updatePrivacyAgree(reactContext, true);
        client = new AMapLocationClient(reactContext);
        geocodeSearch = new GeocodeSearch(reactContext);
        client.setLocationListener(this);
        eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
        promise.resolve(null);
    }

    @ReactMethod
    public void start() {
        client.startLocation();
    }

    @ReactMethod
    public void stop() {
        client.stopLocation();
    }

    @ReactMethod
    public void addListener(String name) {
    }

    @ReactMethod
    public void removeListeners(Integer count) {
    }

    @ReactMethod
    public void isStarted(Promise promise) {
        promise.resolve(client.isStarted());
    }

    @ReactMethod
    public void getLastKnownLocation(Promise promise) {
        promise.resolve(toJSON(client.getLastKnownLocation()));
    }

    @ReactMethod
    public void setOnceLocation(boolean value) {
        option.setOnceLocation(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setWifiScan(boolean value) {
        option.setWifiScan(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setInterval(int interval) {
        option.setInterval(interval);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setSensorEnable(boolean value) {
        option.setSensorEnable(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setOpenAlwaysScanWifi(boolean value) {
        AMapLocationClientOption.setOpenAlwaysScanWifi(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setNeedAddress(boolean value) {
        option.setNeedAddress(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setOnceLocationLatest(boolean value) {
        option.setOnceLocationLatest(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setMockEnable(boolean value) {
        option.setMockEnable(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setLocationCacheEnable(boolean value) {
        option.setLocationCacheEnable(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setGpsFirst(boolean value) {
        option.setGpsFirst(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setHttpTimeout(int value) {
        option.setHttpTimeOut(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setGpsFirstTimeout(int value) {
        option.setGpsFirstTimeout(value);
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setLocationMode(String mode) {
        option.setLocationMode(AMapLocationClientOption.AMapLocationMode.valueOf(mode));
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setLocationPurpose(String purpose) {
        option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.valueOf(purpose));
        client.setLocationOption(option);
    }

    @ReactMethod
    public void setGeoLanguage(String language) {
        option.setGeoLanguage(AMapLocationClientOption.GeoLanguage.valueOf(language));
        client.setLocationOption(option);
    }

     @ReactMethod
    public void reverseGeoCode(double lat, double lng, Float radius, Promise promise) {
        if (lat <= 0 || lng <= 0) {
            promise.reject(String.valueOf(-2), "无效的经纬度");
            return;
        }
        LatLonPoint poi = new LatLonPoint(lat, lng);
        RegeocodeQuery regeocodeQuery = new RegeocodeQuery(poi, 50.0F, GeocodeSearch.AMAP);
        if (radius != null && radius >= 0f) {
            regeocodeQuery.setRadius(radius);
        }
        regeocodeQuery.setPoiType("");
        try {
            RegeocodeAddress fromLocation = geocodeSearch.getFromLocation(regeocodeQuery);
            if (!fromLocation.getFormatAddress().isEmpty()) {
                WritableMap map = Arguments.createMap();
                map.putString("address", fromLocation.getFormatAddress());
                map.putString("country", fromLocation.getCountry());
                map.putString("province", fromLocation.getProvince());
                map.putString("city", fromLocation.getCity());
                map.putString("cityCode", fromLocation.getCityCode());
                map.putString("district", fromLocation.getDistrict());
                map.putString("street", fromLocation.getStreetNumber().getStreet());
                map.putString("streetNumber", fromLocation.getStreetNumber().getStreet());
                map.putString("adCode", fromLocation.getAdCode());
                promise.resolve(map);
            } else {
                promise.reject(String.valueOf(-1), "坐标地址解析失败,请重试");
            }
        } catch (AMapException ae) {
            promise.reject(String.valueOf(ae.getErrorCode()), ae.getErrorMessage(), ae);
        } catch (Exception e) {
            promise.reject(String.valueOf(-1), "坐标地址解析失败,请重试", e);
        }
    }

    @ReactMethod
    public void searchPoi(String keyWord, String city, Promise promise) {
        WritableMap params = Arguments.createMap();
        try {
            if (city == null || city.isEmpty()) {
                promise.reject(String.valueOf(-3), "请选择城市");
                return;
            }
            if (keyWord == null || keyWord.isEmpty()) {
                promise.reject(String.valueOf(-4), "请输入关键字");
                return;
            }
            PoiSearchV2.Query query = new PoiSearchV2.Query(keyWord, "", city);
            query.setDistanceSort(true);
            query.setPageNum(1);
            query.setPageSize(13);
            PoiSearchV2 searchV2 = new PoiSearchV2(reactContext, query);
            PoiResultV2 resultV2 = searchV2.searchPOI();
            ArrayList<PoiItemV2> pois = resultV2.getPois();
            WritableArray array = Arguments.createArray();
            if (pois != null) {
                for (PoiItemV2 info : pois) {
                    if (info.getLatLonPoint() == null || info.getTitle() == null ||
                            info.getTitle().isEmpty() || info.getSnippet() == null || info.getSnippet().isEmpty()) {
                        continue;
                    }
                    WritableMap par = Arguments.createMap();
                    par.putString("address", info.getSnippet());
                    par.putString("provinceCode", info.getProvinceCode());
                    par.putString("province", info.getProvinceName());
                    par.putString("cityCode", info.getCityCode());
                    par.putString("city", info.getCityName());
                    par.putString("areaCode", info.getAdCode());
                    par.putString("area", info.getAdName());
                    par.putString("name", info.getTitle());
                    par.putString("uid", info.getPoiId());
                    par.putString("typeCode", info.getTypeCode());
                    par.putString("type", info.getTypeDes());
                    par.putDouble("latitude", info.getLatLonPoint().getLatitude());
                    par.putDouble("longitude", info.getLatLonPoint().getLongitude());
                    array.pushMap(par);
                }
                params.putInt("total", array.size());
            }
            params.putArray("result", array);
            promise.resolve(params);
        } catch (AMapException ae) {
            promise.reject(String.valueOf(ae.getErrorCode()), ae.getErrorMessage(), ae);
        } catch (Exception e) {
            promise.reject(String.valueOf(-1), "地址搜索失败,请重试", e);
        }
    }


    private ReadableMap toJSON(AMapLocation location) {
        if (location == null) {
            return null;
        }
        WritableMap map = Arguments.createMap();
        map.putInt("errorCode", location.getErrorCode());
        map.putString("errorInfo", location.getErrorInfo());
        map.putString("locationDetail", location.getLocationDetail());
        if (location.getErrorCode() == AMapLocation.LOCATION_SUCCESS) {
            map.putDouble("timestamp", location.getTime());
            map.putDouble("accuracy", location.getAccuracy());
            map.putDouble("latitude", location.getLatitude());
            map.putDouble("longitude", location.getLongitude());
            map.putDouble("altitude", location.getAltitude());
            map.putDouble("speed", location.getSpeed());
            map.putDouble("heading", location.getBearing());
            map.putInt("locationType", location.getLocationType());
            map.putString("coordinateType", location.getCoordType());
            map.putInt("gpsAccuracy", location.getGpsAccuracyStatus());
            map.putInt("trustedLevel", location.getTrustedLevel());
            if (!location.getAddress().isEmpty()) {
                map.putString("address", location.getAddress());
                map.putString("description", location.getDescription());
                map.putString("poiName", location.getPoiName());
                map.putString("country", location.getCountry());
                map.putString("province", location.getProvince());
                map.putString("city", location.getCity());
                map.putString("cityCode", location.getCityCode());
                map.putString("district", location.getDistrict());
                map.putString("street", location.getStreet());
                map.putString("streetNumber", location.getStreetNum());
                map.putString("adCode", location.getAdCode());
            }
        }
        return map;
    }
}