Commit c5a91ed7 authored by wind.wang's avatar wind.wang

init

parents
# Changelog
init project to ability platform
#1.2.8
修复安卓和ios多个map之间的跳转时,前一个页面的mark点击失效问题
#1.2.8
添加了 onMoveComplete函数,onMoveComplete 与 onChange只能二选一, onMoveComplete在移动地图的时候中心点变了都会调用
# 1.3.0
添加了 onMovingChange 回调函数
#2.0.0
集成github比较好的mapview组件,修复了一些bug
https://github.com/qiuxiang/react-native-amap3d
#2.0.1
重命名一些文件的名称,修复了ios的一些bug
#2.0.2-amap2d
s.dependency 'React'
#2.0.2-amap2d.3
web端的定位 AMap变量改为 window.AMap
#2.0.2-amap2d.4
中心点偶然会偏移
#2.0.2-amap2d.5
fetchLocation 错误信息安卓支持 if(error) 判断
\ No newline at end of file
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>android</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(LOCAL_INSTALLATION(/Applications/Android Studio.app/Contents/gradle/gradle-3.2))
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=/Applications/Android Studio.app/Contents/gradle/gradle-3.2
java.home=
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
}
}
}
buildscript {
ext.kotlin_version = '1.2.41'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
}
}
allprojects {
repositories {
jcenter()
maven { url "$projectDir/../node_modules/react-native/android" }
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.1.0'
compile files('libs/AMap_Search_V4.0.0_20170111.jar')
compile files('libs/AMap_Location_V3.3.0_20170118.jar')
compile 'com.facebook.react:react-native:+'
}
\ No newline at end of file
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.terminus.rctamap">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>
package io.terminus.rnamap;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import io.terminus.rnamap.service.GeocodeManager;
import io.terminus.rnamap.service.LocationManager;
import io.terminus.rnamap.service.MapNavigationManager;
/**
* io.terminus.rnamap
* Created by Allen.Chiang on 19/01/2017.
*/
public class AMapReactPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new LocationManager(reactContext));
modules.add(new GeocodeManager(reactContext));
modules.add(new MapNavigationManager(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
List<ViewManager> modules = new ArrayList<>();
return modules;
}
}
package io.terminus.rnamap;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.widget.Toast;
import com.amap.api.location.AMapLocation;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.StreetNumber;
import io.terminus.rnamap.model.LocationDO;
/**
* io.terminus.rnamap
* Created by Allen.Chiang on 22/01/2017.
*/
public class AMapUtils {
public static LocationDO createLocationDO(AMapLocation aMapLocation) {
LocationDO locationDO = new LocationDO();
locationDO.setLatitude(String.valueOf(aMapLocation.getLatitude()));
locationDO.setLongitude(String.valueOf(aMapLocation.getLongitude()));
locationDO.setAdCode(aMapLocation.getAdCode());
locationDO.setFormattedAddress(aMapLocation.getAddress());
locationDO.setCountry(aMapLocation.getCountry());
locationDO.setProvince(aMapLocation.getProvince());
locationDO.setCity(aMapLocation.getCity());
locationDO.setDistrict(aMapLocation.getDistrict());
locationDO.setCityCode(aMapLocation.getCityCode());
locationDO.setStreet(aMapLocation.getStreet());
locationDO.setNumber(aMapLocation.getStreetNum());
locationDO.setPOIName(aMapLocation.getPoiName());
locationDO.setAOIName(aMapLocation.getAoiName());
return locationDO;
}
/**
* 和iOS统一返回格式
*
* @param address address
* @return LocationDO
*/
public static LocationDO convert2Location(RegeocodeAddress address) {
LocationDO locationDO = new LocationDO();
locationDO.setFormattedAddress(address.getFormatAddress());
locationDO.setCountry(address.getTownship());
locationDO.setProvince(address.getProvince());
locationDO.setCityCode(address.getCityCode());
locationDO.setCity(address.getCity());
locationDO.setDistrict(address.getDistrict());
locationDO.setAdCode(address.getAdCode());
StreetNumber streetNumber = address.getStreetNumber();
if (streetNumber != null) {
LatLonPoint point = streetNumber.getLatLonPoint();
if (point != null) {
locationDO.setLatitude(String.valueOf(point.getLatitude()));
locationDO.setLongitude(String.valueOf(point.getLongitude()));
}
locationDO.setStreet(streetNumber.getStreet());
locationDO.setNumber(streetNumber.getNumber());
}
return locationDO;
}
/**
* 和iOS统一返回格式
*
* @param address address
* @return LocationDO
*/
public static LocationDO convert2Location(GeocodeAddress address) {
LocationDO locationDO = new LocationDO();
locationDO.setFormattedAddress(address.getFormatAddress());
locationDO.setCountry(address.getTownship());
locationDO.setProvince(address.getProvince());
locationDO.setCity(address.getCity());
// android这里没有返回citycode,但是ios有返回,这里可能导致不一样
locationDO.setAdCode(address.getAdcode());
LatLonPoint point = address.getLatLonPoint();
if (point != null) {
locationDO.setLatitude(String.valueOf(point.getLatitude()));
locationDO.setLongitude(String.valueOf(point.getLongitude()));
}
return locationDO;
}
public static Boolean isStringBlank(String str) {
if (str == null || str.length() == 0 || str.trim().length() == 0) {
return true;
}
return false;
}
public static void navigation(Context mContext,
String sname,
double slat,
double slon,
String dname,
double dlat,
double dlon){
if(!isMapInstall(mContext)){
Toast.makeText(mContext,"请下载安装高德地图",Toast.LENGTH_SHORT).show();
return;
}
String dat = "androidamap://route?sourceApplication="+mContext.getPackageName()+"&slat="+slat+"&slon="+slon+"&sname="+sname+"&dlat="+dlat+"&dlon="+dlon+"&dname="+dname+"&dev=0&t=2";
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(dat));
mContext.startActivity(intent);
}
public static boolean isMapInstall(Context mContext){
try {
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo("com.autonavi.minimap", PackageManager.GET_UNINSTALLED_PACKAGES);
if(info != null){
return true;
}
}catch (Exception e){
e.printStackTrace();
}
return false;
}
}
package io.terminus.rnamap.model;
/**
* Created by wenboli on 17/7/12.
*/
import com.amap.api.services.district.DistrictItem;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import java.util.ArrayList;
import java.util.List;
public class DistrictResultDO implements WritableObject {
private String latitude;
private String longitude;
private String adcode;
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLatitude() {
return latitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getLongitude() {
return longitude;
}
public void setAdcode(String adcode) {
this.adcode = adcode;
}
public String getAdcode() {
return adcode;
}
public DistrictResultDO(DistrictItem districtItem) {
latitude = String.valueOf(districtItem.getCenter().getLatitude());
longitude = String.valueOf(districtItem.getCenter().getLongitude()) ;
adcode = districtItem.getAdcode();
}
public WritableMap writableMap() {
WritableMap writableMap = Arguments.createMap();
writableMap.putString("adCode", adcode);
writableMap.putString("latitude", latitude);
writableMap.putString("longitude", longitude);
return writableMap;
}
}
package io.terminus.rnamap.model;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import java.util.Map;
/**
* io.terminus.rnamap.model
* Created by Allen.Chiang on 19/01/2017.
*/
public class ErrorDO implements WritableObject {
private String message;
private Integer code;
private Map<String, String> userInfo;
public ErrorDO(String message, Integer code) {
this.message = message;
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Map<String, String> getUserInfo() {
return userInfo;
}
public void setUserInfo(Map<String, String> userInfo) {
this.userInfo = userInfo;
}
@Override
public WritableMap writableMap() {
WritableMap map = Arguments.createMap();
map.putString("message", message);
map.putInt("code", code);
if (null != userInfo) {
WritableMap userInfoMap = Arguments.createMap();
for (Map.Entry<String, String> entry : userInfo.entrySet()) {
userInfoMap.putString(entry.getKey(), entry.getValue());
}
map.putMap("userInfo", userInfoMap);
}
return map;
}
}
package io.terminus.rnamap.model;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import java.util.List;
/**
* io.terminus.rnamap.model
* Created by Allen.Chiang on 19/01/2017.
*/
public class LocationDO implements WritableObject {
// gps坐标信息,纬度
private String latitude;
// gps坐标信息,经度
private String longitude;
// 格式化地址
private String formattedAddress;
// 国家
private String country;
// 省
private String province;
// 市
private String city;
// 区
private String district;
// 城市编码
private String cityCode;
// 区域编码
private String adCode;
// 街道名称
private String street;
// 门牌号
private String number;
// 兴趣点名称
private String POIName;
// 所属兴趣点名称
private String AOIName;
// 周边兴趣点
private List<POIDO> poidoList;
// 周边兴趣点所属
private List<String> aoidoList;
public WritableMap writableMap() {
WritableMap map = Arguments.createMap();
map.putString("latitude", latitude);
map.putString("longitude", longitude);
map.putString("formattedAddress", formattedAddress);
map.putString("country", country);
map.putString("province", province);
map.putString("city", city);
map.putString("district", district);
map.putString("cityCode", cityCode);
map.putString("adCode", adCode);
map.putString("street", street);
map.putString("number", number);
map.putString("POIName", POIName);
map.putString("AOIName", AOIName);
WritableArray pois = Arguments.createArray();
if (poidoList != null) {
for (POIDO poido : poidoList) {
pois.pushMap(poido.writableMap());
}
}
WritableArray aois = Arguments.createArray();
if (aoidoList != null) {
for (String aoido : aoidoList) {
aois.pushString(aoido);
}
}
map.putArray("aois", aois);
map.putArray("pois", pois);
return map;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getFormattedAddress() {
return formattedAddress;
}
public void setFormattedAddress(String formattedAddress) {
this.formattedAddress = formattedAddress;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getAdCode() {
return adCode;
}
public void setAdCode(String adCode) {
this.adCode = adCode;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getPOIName() {
return POIName;
}
public void setPOIName(String POIName) {
this.POIName = POIName;
}
public String getAOIName() {
return AOIName;
}
public void setAOIName(String AOIName) {
this.AOIName = AOIName;
}
public List<POIDO> getPoidoList() {
return poidoList;
}
public void setPoidoList(List<POIDO> poidoList) {
this.poidoList = poidoList;
}
public List<String> getAoidoList() {
return aoidoList;
}
public void setAoidoList(List<String> aoidoList) {
this.aoidoList = aoidoList;
}
}
package io.terminus.rnamap.model;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import java.util.ArrayList;
import java.util.List;
/**
* io.terminus.rnamap.model
* Created by Allen.Chiang on 20/01/2017.
*/
public class LocationListDO implements WritableObject {
private List<LocationDO> list;
public LocationListDO(List<LocationDO> list) {
this.list = list;
}
public void addLocation(LocationDO locationDO) {
if (this.list == null) {
this.list = new ArrayList<>();
}
this.list.add(locationDO);
}
@Override
public WritableMap writableMap() {
WritableArray writableArray = Arguments.createArray();
if (list != null) {
for (LocationDO locationDO : list) {
writableArray.pushMap(locationDO.writableMap());
}
}
WritableMap writableMap = Arguments.createMap();
writableMap.putArray("list", writableArray);
return writableMap;
}
}
package io.terminus.rnamap.model;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import java.util.Map;
/**
* User : yh
* Date : 17/3/8
*/
public class MapPointDO {
public MapPointDO(ReadableMap data){
if(data.hasKey("latitude")){
latitude = data.getDouble("latitude");
}
if(data.hasKey("longitude")){
longitude = data.getDouble("longitude");
}
if(data.hasKey("title")){
title = data.getString("title");
}
if(data.hasKey("subTitle")){
subTitle = data.getString("subTitle");
}
if(data.hasKey("desc")){
desc = data.getString("desc");
}
if(data.hasKey("iconImageName")){
iconImageName = data.getString("iconImageName");
}
if(data.hasKey("extra")){
extra = data.getString("extra");
}
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public String getIconImageName() {
return iconImageName;
}
public void setIconImageName(String iconImageName) {
this.iconImageName = iconImageName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubTitle() {
return subTitle;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
private double latitude;
private double longitude;
private String iconImageName;
private String title;
private String subTitle;
private String desc;
private String extra;
}
package io.terminus.rnamap.model;
import com.amap.api.services.core.PoiItem;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
/**
* io.terminus.rnamap.model
* Created by Allen.Chiang on 23/01/2017.
*/
public class POIDO implements WritableObject {
private String uid;
private String name;
private String type;
private String address;
private String adcode;
private String latitude;
private String longitude;
public void setPoiItem(PoiItem poiItem) {
this.uid = poiItem.getPoiId();
this.name = poiItem.getTitle();
this.type = poiItem.getTypeDes();
this.adcode = poiItem.getAdCode();
this.address = poiItem.getSnippet();
if (poiItem.getLatLonPoint() != null) {
latitude = String.valueOf(poiItem.getLatLonPoint().getLatitude());
longitude = String.valueOf(poiItem.getLatLonPoint().getLongitude());
}
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getAdcode() {
return adcode;
}
public void setAdcode(String adcode) {
this.adcode = adcode;
}
@Override
public WritableMap writableMap() {
WritableMap writableMap = Arguments.createMap();
writableMap.putString("uid", uid);
writableMap.putString("name", name);
writableMap.putString("type", type);
writableMap.putString("address", address);
writableMap.putString("adcode", adcode);
writableMap.putString("latitude", latitude);
writableMap.putString("longitude", longitude);
return writableMap;
}
}
package io.terminus.rnamap.model;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import java.util.ArrayList;
import java.util.List;
/**
* io.terminus.rnamap.model
* Created by Allen.Chiang on 20/01/2017.
*/
public class POISearchDO implements WritableObject {
private List<POIDO> pois;
private Integer count;
private POISuggestion suggestion;
public POISearchDO() {
pois = new ArrayList<>();
count = 0;
suggestion = new POISuggestion();
}
@Override
public WritableMap writableMap() {
WritableMap writableMap = Arguments.createMap();
if (pois != null) {
WritableArray array = Arguments.createArray();
for (POIDO poido : pois) {
array.pushMap(poido.writableMap());
}
writableMap.putArray("pois", array);
}
writableMap.putInt("count", count);
writableMap.putMap("suggestion", suggestion == null ? null : suggestion.writableMap());
return writableMap;
}
public List<POIDO> getPois() {
return pois;
}
public void setPois(List<POIDO> pois) {
this.pois = pois;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public POISuggestion getSuggestion() {
return suggestion;
}
public void setSuggestion(POISuggestion suggestion) {
this.suggestion = suggestion;
}
public static class POISuggestion implements WritableObject {
private List<String> keywords;
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
@Override
public WritableMap writableMap() {
WritableMap writableMap = Arguments.createMap();
if (keywords != null) {
WritableArray array = Arguments.createArray();
for (String keyword : keywords) {
array.pushString(keyword);
}
writableMap.putArray("keywords", array);
}
return writableMap;
}
}
}
package io.terminus.rnamap.model;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
/**
* io.terminus.rnamap.model
* Created by Allen.Chiang on 19/01/2017.
*/
public class ReactResultDO implements WritableObject {
private String requestId;
private WritableObject data;
private WritableObject error;
public ReactResultDO() {
}
public ReactResultDO(String requestId) {
this.requestId = requestId;
}
public ReactResultDO(String requestId, WritableObject data) {
this.requestId = requestId;
this.data = data;
}
public WritableMap writableMap() {
WritableMap map = Arguments.createMap();
map.putString("requestId", requestId);
map.putMap("data", data == null ? null : data.writableMap());
map.putMap("error", error == null ? null : error.writableMap());
return map;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public WritableObject getData() {
return data;
}
public void setData(WritableObject data) {
this.data = data;
}
public WritableObject getError() {
return error;
}
public void setError(WritableObject error) {
this.error = error;
}
}
package io.terminus.rnamap.model;
import com.facebook.react.bridge.WritableMap;
/**
* io.terminus.rnamap.model
* Created by Allen.Chiang on 19/01/2017.
*/
public interface WritableObject {
WritableMap writableMap();
}
package io.terminus.rnamap.searcher;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import io.terminus.rnamap.model.ErrorDO;
import io.terminus.rnamap.model.ReactResultDO;
import io.terminus.rnamap.model.WritableObject;
/**
* io.terminus.rnamap.service
* Created by Allen.Chiang on 20/01/2017.
*/
public class BaseEmitter {
private String requestId;
private ReactContext reactContext;
public BaseEmitter(String requestId, ReactContext reactContext) {
this.requestId = requestId;
this.reactContext = reactContext;
}
public ReactContext getReactContext() {
return reactContext;
}
public void sendEvent(String eventName, WritableMap writableMap) {
if (this.reactContext != null) {
writableMap.putString("requestId", requestId);
this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, writableMap);
}
}
public void sendEvent(String eventName, WritableObject writableObject) {
ReactResultDO resultDO = new ReactResultDO(requestId, writableObject);
this.sendEvent(eventName, resultDO.writableMap());
}
public void sendEventError(String eventName, ErrorDO errorDO) {
ReactResultDO resultDO = new ReactResultDO(requestId, errorDO);
sendEvent(eventName, resultDO.writableMap());
}
}
package io.terminus.rnamap.searcher;
/**
* Created by wenboli on 17/7/12.
*/
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.district.DistrictItem;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.amap.api.services.district.DistrictResult;
import com.amap.api.services.district.DistrictSearch;
import com.amap.api.services.district.DistrictSearchQuery;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import java.util.ArrayList;
import java.util.List;
import io.terminus.rnamap.AMapUtils;
import io.terminus.rnamap.model.DistrictResultDO;
import io.terminus.rnamap.model.ErrorDO;
import io.terminus.rnamap.model.LocationDO;
import io.terminus.rnamap.model.LocationListDO;
import io.terminus.rnamap.model.POIDO;
public class DistrictSearcher extends BaseEmitter implements DistrictSearch.OnDistrictSearchListener{
private static final int RESULT_CODE_SUCCESS = 1000;
private static final String EVENT_NAME_GEOCODE = "geocode";
private DistrictSearch search;
public DistrictSearcher(String requestId, ReactContext reactContext) {
super(requestId, reactContext);
search = new DistrictSearch(reactContext);
}
public void search(String key){
DistrictSearchQuery query = new DistrictSearchQuery();
query.setKeywords(key);
search.setQuery(query);
search.setOnDistrictSearchListener(this);
search.searchDistrictAsyn();
}
@Override
public void onDistrictSearched(DistrictResult districtResult) {
if (districtResult.getAMapException().getErrorCode() == RESULT_CODE_SUCCESS){
DistrictItem item = districtResult.getDistrict().get(0);
DistrictResultDO resultDO = new DistrictResultDO(item);
sendEvent(EVENT_NAME_GEOCODE, resultDO);
} else {
ErrorDO errorDO = new ErrorDO("AMap DistrictSearch error with code:", 0);
sendEventError(EVENT_NAME_GEOCODE, errorDO);
}
}
}
package io.terminus.rnamap.searcher;
import android.text.TextUtils;
import android.util.Log;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.geocoder.AoiItem;
import com.amap.api.services.geocoder.GeocodeAddress;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.geocoder.StreetNumber;
import com.facebook.react.bridge.ReactContext;
import java.util.ArrayList;
import java.util.List;
import io.terminus.rnamap.AMapUtils;
import io.terminus.rnamap.model.ErrorDO;
import io.terminus.rnamap.model.LocationDO;
import io.terminus.rnamap.model.LocationListDO;
import io.terminus.rnamap.model.POIDO;
/**
* io.terminus.rnamap
* Created by Allen.Chiang on 20/01/2017.
*/
public class GeocodeSearcher extends BaseEmitter implements GeocodeSearch.OnGeocodeSearchListener {
private static final int RESULT_CODE_SUCCESS = 1000;
private static final String EVENT_NAME_GEOCODE = "geocode";
public GeocodeSearch geocodeSearch = null;
public GeocodeSearcher(ReactContext context, String requestId) {
super(requestId, context);
this.geocodeSearch = new GeocodeSearch(context);
geocodeSearch.setOnGeocodeSearchListener(this);
}
@Override
public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int resultCode) {
if (RESULT_CODE_SUCCESS == resultCode) {
LocationDO locationDO = AMapUtils.convert2Location(regeocodeResult.getRegeocodeAddress());
List<PoiItem> poiItems = regeocodeResult.getRegeocodeAddress().getPois();
List<AoiItem> aoiItems = regeocodeResult.getRegeocodeAddress().getAois();
String adCode = regeocodeResult.getRegeocodeAddress().getAdCode();
if (poiItems != null) {
List<POIDO> pois = new ArrayList<>();
for (PoiItem poiItem : poiItems) {
POIDO poido = new POIDO();
poido.setPoiItem(poiItem);
if(!TextUtils.isEmpty(adCode)){
if(TextUtils.isEmpty(poido.getAdcode())){
poido.setAdcode(adCode);
}
}
pois.add(poido);
}
locationDO.setPoidoList(pois);
// locationDO.setAoidoList();
}
if (aoiItems != null) {
List<String> aois = new ArrayList<>();
for (AoiItem aoiItem : aoiItems) {
aois.add(aoiItem.getAoiName());
}
locationDO.setAoidoList(aois);
}
this.sendEvent(EVENT_NAME_GEOCODE, locationDO);
} else {
ErrorDO errorDO = new ErrorDO("AMap ReGeocode error with code:" + resultCode, resultCode);
this.sendEventError(EVENT_NAME_GEOCODE, errorDO);
}
}
@Override
public void onGeocodeSearched(GeocodeResult geocodeResult, int resultCode) {
if (RESULT_CODE_SUCCESS == resultCode && !geocodeResult.getGeocodeAddressList().isEmpty()) {
List<LocationDO> locations = new ArrayList<>();
for (GeocodeAddress address : geocodeResult.getGeocodeAddressList()) {
LocationDO locationDO = AMapUtils.convert2Location(address);
locations.add(locationDO);
}
LocationListDO listDO = new LocationListDO(locations);
this.sendEvent(EVENT_NAME_GEOCODE, listDO);
} else {
ErrorDO errorDO = null;
if (geocodeResult.getGeocodeAddressList().isEmpty()) {
errorDO = new ErrorDO("AMap ReGeocode success but result is empty", resultCode);
} else {
errorDO = new ErrorDO("AMap ReGeocode error with code:" + resultCode, resultCode);
}
this.sendEventError(EVENT_NAME_GEOCODE, errorDO);
}
}
}
package io.terminus.rnamap.searcher;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.facebook.react.bridge.ReactContext;
import java.util.ArrayList;
import java.util.List;
import io.terminus.rnamap.AMapUtils;
import io.terminus.rnamap.model.ErrorDO;
import io.terminus.rnamap.model.LocationDO;
import io.terminus.rnamap.model.POIDO;
import io.terminus.rnamap.model.POISearchDO;
/**
* io.terminus.rnamap.service
* Created by Allen.Chiang on 20/01/2017.
*/
public class POISearcher extends BaseEmitter implements PoiSearch.OnPoiSearchListener, AMapLocationListener {
private static final int RESULT_CODE_SUCCESS = 1000;
private static final int POI_SEARCH_PAGE_SIZE = 10;
private static final String EVENT_NAME_GEOCODE = "geocode";
public PoiSearch poiSearch = null;
private Integer pageNum = 0;
private Integer pageSize = POI_SEARCH_PAGE_SIZE;
private String keyword;
public POISearcher(ReactContext reactContext, String requestId) {
super(requestId, reactContext);
}
public void search(String keyword, String cityCode) {
search(keyword, cityCode, pageNum, pageSize);
}
public void search(String keyword, String cityCode, Integer pageNum, Integer pageSize) {
PoiSearch.Query query = new PoiSearch.Query(keyword, "", cityCode);
query.setPageNum(pageNum);
query.setPageSize(pageSize);
query.setCityLimit(true);
poiSearch = new PoiSearch(this.getReactContext(), query);
poiSearch.setOnPoiSearchListener(this);
poiSearch.searchPOIAsyn();
}
@Override
public void onPoiSearched(PoiResult poiResult, int resultCode) {
if (RESULT_CODE_SUCCESS == resultCode) {
POISearchDO searchDO = new POISearchDO();
// 没有返回总数,只能这么粗略计算了
searchDO.setCount(poiResult.getPageCount() * poiResult.getPois().size());
// 建议搜索内容
searchDO.getSuggestion().setKeywords(poiResult.getSearchSuggestionKeywords());
if (poiResult.getPois() != null) {
List<POIDO> pois = new ArrayList<>();
for (PoiItem poiItem : poiResult.getPois()) {
POIDO poido = new POIDO();
poido.setPoiItem(poiItem);
pois.add(poido);
}
searchDO.setPois(pois);
}
sendEvent(EVENT_NAME_GEOCODE, searchDO);
} else {
ErrorDO errorDO = new ErrorDO("AMap POISearch error with code:" + resultCode, resultCode);
sendEventError(EVENT_NAME_GEOCODE, errorDO);
}
}
@Override
public void onPoiItemSearched(PoiItem poiItem, int resultCode) {
}
/**
* 定位的回调方法
*
* @param aMapLocation aMapLocation
*/
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
LocationDO locationDO = AMapUtils.createLocationDO(aMapLocation);
if (keyword != null) {
// js没有传入cityCode,自动获取一次定位以后并搜索poi
search(keyword, locationDO.getCityCode(), pageNum, pageSize);
}
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
}
package io.terminus.rnamap.service;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeQuery;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import io.terminus.rnamap.AMapUtils;
import io.terminus.rnamap.searcher.GeocodeSearcher;
import io.terminus.rnamap.searcher.POISearcher;
import io.terminus.rnamap.searcher.DistrictSearcher;
/**
* io.terminus.rnamap.service
* Created by Allen.Chiang on 19/01/2017.
*/
public class GeocodeManager extends ReactContextBaseJavaModule {
public GeocodeManager(ReactApplicationContext reactContext) {
super(reactContext);
}
@ReactMethod
public void geocode(String requestId, String address, String cityCode) {
GeocodeSearcher searcher = new GeocodeSearcher(this.getReactApplicationContext(), requestId);
GeocodeQuery query = new GeocodeQuery(address, cityCode);
searcher.geocodeSearch.getFromLocationNameAsyn(query);
}
@ReactMethod
public void reGeocode(String requestId, String latitude, String longitude) {
GeocodeSearcher searcher = new GeocodeSearcher(this.getReactApplicationContext(), requestId);
LatLonPoint point = new LatLonPoint(Double.parseDouble(latitude), Double.parseDouble(longitude));
RegeocodeQuery query = new RegeocodeQuery(point, 200, GeocodeSearch.GPS);
searcher.geocodeSearch.getFromLocationAsyn(query);
}
@ReactMethod
public void reGeocodeByAmap(String requestId, String latitude, String longitude){
GeocodeSearcher searcher = new GeocodeSearcher(this.getReactApplicationContext(), requestId);
LatLonPoint point = new LatLonPoint(Double.parseDouble(latitude), Double.parseDouble(longitude));
RegeocodeQuery query = new RegeocodeQuery(point, 200, GeocodeSearch.AMAP);
searcher.geocodeSearch.getFromLocationAsyn(query);
}
@ReactMethod
public void poiSearch(String requestId, String keyword, String cityCode) {
poiSearchWithPage(requestId, keyword, cityCode, 0, 10);
}
@ReactMethod
public void poiSearchWithPage(String requestId, String keyword, String cityCode, Integer pageNum, Integer pageSize) {
POISearcher searcher = new POISearcher(this.getReactApplicationContext(), requestId);
if (AMapUtils.isStringBlank(cityCode)) {
LocationManager locationManager = new LocationManager(this.getReactApplicationContext());
locationManager.location(searcher);
searcher.setKeyword(keyword);
searcher.setPageNum(pageNum);
searcher.setPageSize(pageSize);
} else {
searcher.search(keyword, cityCode, pageNum, pageSize);
}
}
@ReactMethod
public void district(String requestId, String name) {
DistrictSearcher searcher = new DistrictSearcher(requestId, this.getReactApplicationContext());
searcher.search(name);
}
@Override
public String getName() {
return "RNGeocodeManager";
}
}
package io.terminus.rnamap.service;
import android.support.v7.appcompat.BuildConfig;
import android.util.Log;
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.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import javax.annotation.Nullable;
import io.terminus.rnamap.AMapUtils;
import io.terminus.rnamap.model.ErrorDO;
import io.terminus.rnamap.model.LocationDO;
import io.terminus.rnamap.model.ReactResultDO;
/**
* io.terminus.rnamap
* Created by Allen.Chiang on 19/01/2017.
*/
public class LocationManager extends ReactContextBaseJavaModule implements AMapLocationListener {
private static final String REACT_EVENT_NAME = "AMapLocationResultEvent";
public LocationManager(ReactApplicationContext reactContext) {
super(reactContext);
}
private AMapLocationClient aMapLocationClient = null;
@Override
public String getName() {
return "RNLocationManager";
}
/**
* 开始定位
*
* @param locationListener 可以外部传入定位结果的接收者,
* 用于poisearch自动获取一次定位的citycode
*/
public void location(AMapLocationListener locationListener) {
// if(ContextCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION)
// != PackageManager.PERMISSION_GRANTED){
// ReactResultDO resultDO = new ReactResultDO();
// resultDO.setError(new ErrorDO("", 2));
// sendEvent(this.getReactApplicationContext(), REACT_EVENT_NAME, resultDO.writableMap());
// return;
// }
AMapLocationClient locationClient = initAMapLocationClient();
aMapLocationClient = locationClient;
//设置定位回调监听
locationClient.setLocationListener(locationListener == null ? this : locationListener);
locationClient.startLocation();
}
/**
* 开始定位
*/
@ReactMethod
public void location() {
location(null);
}
@ReactMethod
public void stopLocation() {
if (aMapLocationClient != null) {
aMapLocationClient.stopLocation();
}
}
private AMapLocationClient initAMapLocationClient() {
//声明AMapLocationClient类对象
AMapLocationClient mLocationClient = new AMapLocationClient(getReactApplicationContext());
//声明AMapLocationClientOption对象
AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
mLocationOption.setOnceLocation(true); // 仅单次定位
mLocationOption.setOnceLocationLatest(true); // 获取最近3s内精度最高的一次定位结果
mLocationOption.setNeedAddress(true); // 设置是否返回地址信息(默认返回地址信息)
mLocationOption.setMockEnable(BuildConfig.DEBUG); // Debug模式允许mock gps
mLocationClient.setLocationOption(mLocationOption);
return mLocationClient;
}
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (aMapLocation == null) {
Log.e("AMapLocation error", "return null");
ReactResultDO resultDO = new ReactResultDO();
resultDO.setError(new ErrorDO("AMap return nothing", 0));
sendEvent(this.getReactApplicationContext(), REACT_EVENT_NAME, resultDO.writableMap());
} else if (aMapLocation.getErrorCode() != 0) {
Log.e("AMapLocation error", "Code:" + aMapLocation.getErrorCode() + ", Message:" + aMapLocation.getErrorInfo());
ReactResultDO resultDO = new ReactResultDO();
// 去掉sdk返回的一堆错误说明,只去空格前面一段字符串
String errorInfo = (aMapLocation.getErrorInfo()==null)?"":aMapLocation.getErrorInfo().split(" ")[0];
resultDO.setError(new ErrorDO(errorInfo, aMapLocation.getErrorCode()));
sendEvent(this.getReactApplicationContext(), REACT_EVENT_NAME, resultDO.writableMap());
} else {
LocationDO locationDO = AMapUtils.createLocationDO(aMapLocation);
ReactResultDO resultDO = new ReactResultDO(null, locationDO);
sendEvent(resultDO);
}
}
private void sendEvent(@Nullable ReactResultDO resultDO) {
sendEvent(this.getReactApplicationContext(), REACT_EVENT_NAME,
resultDO == null ? null : resultDO.writableMap());
}
private void sendEvent(ReactContext reactContext,
String eventName,
@Nullable WritableMap params) {
if (reactContext != null) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
}
}
package io.terminus.rnamap.service;
import android.widget.Toast;
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 io.terminus.rnamap.AMapUtils;
/**
* User : yh
* Date : 17/8/3
*/
public class MapNavigationManager extends ReactContextBaseJavaModule {
private static final String REACT_MODULE_NAME = "RNMapNavigationManager";
private static final String SNAME = "sname";
private static final String SLAT = "slat";
private static final String SLON = "slon";
private static final String DNAME = "dname";
private static final String DLAT = "dlat";
private static final String DLON = "dlon";
public MapNavigationManager(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return REACT_MODULE_NAME;
}
@ReactMethod
public void mapNavigation(ReadableMap params){
String sname,dname;
double slat,slon,dlat,dlon;
if(!params.hasKey(SNAME)){
return;
}
if(!params.hasKey(DNAME)){
return;
}
if(!params.hasKey(SLAT)){
return;
}
if(!params.hasKey(SLON)){
return;
}
if(!params.hasKey(DLAT)){
return;
}
if(!params.hasKey(DLON)){
return;
}
sname = params.getString(SNAME);
dname = params.getString(DNAME);
slat = params.getDouble(SLAT);
slon = params.getDouble(SLON);
dlat = params.getDouble(DLAT);
dlon = params.getDouble(DLON);
AMapUtils.navigation(this.getReactApplicationContext(),
sname,
slat,
slon,
dname,
dlat,
dlon);
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
buildscript {
ext.kotlin_version = '1.2.41'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 22
}
}
dependencies {
provided 'com.facebook.react:react-native:+'
compile 'com.amap.api:map2d:5.2.0'
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.qiuxiang.react.amap3d">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>
package cn.qiuxiang.react.amap3d
import cn.qiuxiang.react.amap3d.maps.*
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class AMap3DPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf()
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return listOf(
AMapViewManager(),
AMapMarkerManager(),
AMapInfoWindowManager(),
AMapPolylineManager(),
AMapPolygonManager(),
AMapCircleManager()
)
}
}
package cn.qiuxiang.react.amap3d
import android.content.res.Resources
import com.amap.api.maps2d.model.LatLng
import com.amap.api.maps2d.model.LatLngBounds
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
fun Float.toPx(): Int {
return (this * Resources.getSystem().displayMetrics.density).toInt()
}
fun ReadableMap.toLatLng(): LatLng {
return LatLng(this.getDouble("latitude"), this.getDouble("longitude"))
}
fun ReadableArray.toLatLngList(): ArrayList<LatLng> {
return ArrayList((0..(this.size() - 1)).map { this.getMap(it).toLatLng() })
}
fun LatLng.toWritableMap(): WritableMap {
val map = Arguments.createMap()
map.putDouble("latitude", this.latitude)
map.putDouble("longitude", this.longitude)
return map
}
fun ReadableMap.toLatLngBounds(): LatLngBounds {
val latitude = this.getDouble("latitude")
val longitude = this.getDouble("longitude")
val latitudeDelta = this.getDouble("latitudeDelta")
val longitudeDelta = this.getDouble("longitudeDelta")
return LatLngBounds(
LatLng(latitude - latitudeDelta / 2, longitude - longitudeDelta / 2),
LatLng(latitude + latitudeDelta / 2, longitude + longitudeDelta / 2)
)
}
\ No newline at end of file
package cn.qiuxiang.react.amap3d.maps
import android.content.Context
import android.graphics.Color
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.model.Circle
import com.amap.api.maps2d.model.CircleOptions
import com.amap.api.maps2d.model.LatLng
import com.facebook.react.views.view.ReactViewGroup
class AMapCircle(context: Context) : ReactViewGroup(context), AMapOverlay {
private var circle: Circle? = null
var center: LatLng? = null
set(value) {
field = value
circle?.center = value
}
var radius: Double = 0.0
set(value) {
field = value
circle?.radius = value
}
var strokeWidth: Float = 1f
set(value) {
field = value
circle?.strokeWidth = value
}
var strokeColor: Int = Color.BLACK
set(value) {
field = value
circle?.strokeColor = value
}
var fillColor: Int = Color.BLACK
set(value) {
field = value
circle?.fillColor = value
}
var zIndex: Float = 0f
set(value) {
field = value
circle?.zIndex = value
}
override fun add(map: AMap) {
circle = map.addCircle(CircleOptions()
.center(center)
.radius(radius)
.strokeColor(strokeColor)
.strokeWidth(strokeWidth)
.fillColor(fillColor)
.zIndex(zIndex))
}
override fun remove() {
circle?.remove()
}
}
package cn.qiuxiang.react.amap3d.maps
import cn.qiuxiang.react.amap3d.toLatLng
import cn.qiuxiang.react.amap3d.toPx
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
@Suppress("unused")
internal class AMapCircleManager : SimpleViewManager<AMapCircle>() {
override fun getName(): String {
return "AMapCircle"
}
override fun createViewInstance(reactContext: ThemedReactContext): AMapCircle {
return AMapCircle(reactContext)
}
@ReactProp(name = "coordinate")
fun setCoordinate(circle: AMapCircle, coordinate: ReadableMap) {
circle.center = coordinate.toLatLng()
}
@ReactProp(name = "radius")
fun setRadius(circle: AMapCircle, radius: Double) {
circle.radius = radius
}
@ReactProp(name = "fillColor", customType = "Color")
fun setFillColor(circle: AMapCircle, fillColor: Int) {
circle.fillColor = fillColor
}
@ReactProp(name = "strokeColor", customType = "Color")
fun setStrokeColor(circle: AMapCircle, strokeColor: Int) {
circle.strokeColor = strokeColor
}
@ReactProp(name = "strokeWidth")
fun setStrokeWidth(circle: AMapCircle, strokeWidth: Float) {
circle.strokeWidth = strokeWidth.toPx().toFloat()
}
@ReactProp(name = "zIndex")
fun setZIndez(circle: AMapCircle, zIndex: Float) {
circle.zIndex = zIndex
}
}
package cn.qiuxiang.react.amap3d.maps
import android.content.Context
import com.facebook.react.views.view.ReactViewGroup
class AMapInfoWindow(context: Context) : ReactViewGroup(context) {
init {
addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
val layoutParams = this.layoutParams
if (layoutParams == null || layoutParams.width != this.width || layoutParams.height != this.height) {
this.layoutParams = LayoutParams(this.width, this.height)
}
}
}
}
\ No newline at end of file
package cn.qiuxiang.react.amap3d.maps
import android.content.Context
import android.graphics.Color
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.model.Marker
class AMapInfoWindowAdapter(
private val context: Context,
private val markers: HashMap<String, AMapMarker>
) : AMap.InfoWindowAdapter {
val paddingTop = context.resources.displayMetrics.density
override fun getInfoWindow(marker: Marker): View? {
return markers[marker.id]?.infoWindow
}
override fun getInfoContents(marker: Marker): View? {
val layout = LinearLayout(context)
layout.orientation = LinearLayout.VERTICAL
val titleView = TextView(context)
titleView.text = marker.title
titleView.setTextColor(Color.parseColor("#212121"))
layout.addView(titleView)
val snippet = marker.snippet
if (!snippet.isEmpty()) {
val snippetView = TextView(context)
snippetView.text = snippet
snippetView.maxEms = 12
snippetView.setPadding(0, paddingTop.toInt(), 0, 0)
snippetView.setTextColor(Color.parseColor("#757575"))
layout.addView(snippetView)
}
return layout
}
}
package cn.qiuxiang.react.amap3d.maps
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
class AMapInfoWindowManager : ViewGroupManager<AMapInfoWindow>() {
override fun getName(): String {
return "AMapInfoWindow"
}
override fun createViewInstance(reactContext: ThemedReactContext): AMapInfoWindow {
return AMapInfoWindow(reactContext)
}
}
\ No newline at end of file
package cn.qiuxiang.react.amap3d.maps
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.view.View
import cn.qiuxiang.react.amap3d.toPx
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.model.*
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.views.view.ReactViewGroup
class AMapMarker(context: Context) : ReactViewGroup(context), AMapOverlay {
companion object {
private val COLORS = mapOf(
"AZURE" to BitmapDescriptorFactory.HUE_AZURE,
"BLUE" to BitmapDescriptorFactory.HUE_BLUE,
"CYAN" to BitmapDescriptorFactory.HUE_CYAN,
"GREEN" to BitmapDescriptorFactory.HUE_GREEN,
"MAGENTA" to BitmapDescriptorFactory.HUE_MAGENTA,
"ORANGE" to BitmapDescriptorFactory.HUE_ORANGE,
"RED" to BitmapDescriptorFactory.HUE_RED,
"ROSE" to BitmapDescriptorFactory.HUE_ROSE,
"VIOLET" to BitmapDescriptorFactory.HUE_VIOLET,
"YELLOW" to BitmapDescriptorFactory.HUE_YELLOW
)
}
private var icon: View? = null
private var bitmapDescriptor: BitmapDescriptor? = null
private var anchorU: Float = 0.5f
private var anchorV: Float = 1f
var infoWindow: AMapInfoWindow? = null
var marker: Marker? = null
private set
var position: LatLng? = null
set(value) {
field = value
marker?.position = value
}
var zIndex: Float = 0.0f
set(value) {
field = value
marker?.zIndex = value
}
var title = ""
set(value) {
field = value
marker?.title = value
}
var snippet = ""
set(value) {
field = value
marker?.snippet = value
}
var draggable: Boolean = false
set(value) {
field = value
marker?.isDraggable = value
}
var active: Boolean = false
set(value) {
field = value
if (value) {
marker?.showInfoWindow()
} else {
marker?.hideInfoWindow()
}
}
override fun addView(child: View, index: Int) {
super.addView(child, index)
icon = child
icon?.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> updateIcon() }
}
override fun add(map: AMap) {
marker = map.addMarker(MarkerOptions()
.icon(bitmapDescriptor)
.draggable(draggable)
.position(position)
.anchor(anchorU, anchorV)
.title(title)
.snippet(snippet)
.zIndex(zIndex))
this.active = active
}
override fun remove() {
marker?.destroy()
}
fun setIconColor(icon: String) {
bitmapDescriptor = COLORS[icon.toUpperCase()]?.let {
BitmapDescriptorFactory.defaultMarker(it)
}
marker?.setIcon(bitmapDescriptor)
}
fun updateIcon() {
icon?.let {
if (it.width != 0 && it.height != 0) {
val bitmap = Bitmap.createBitmap(
it.width, it.height, Bitmap.Config.ARGB_8888)
it.draw(Canvas(bitmap))
bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap)
marker?.setIcon(bitmapDescriptor)
}
}
}
fun setImage(name: String) {
val drawable = context.resources.getIdentifier(name, "drawable", context.packageName)
bitmapDescriptor = BitmapDescriptorFactory.fromResource(drawable)
marker?.setIcon(bitmapDescriptor)
}
fun setAnchor(x: Double, y: Double) {
anchorU = x.toFloat()
anchorV = y.toFloat()
marker?.setAnchor(anchorU, anchorV)
}
fun lockToScreen(args: ReadableArray?) {
if (args != null) {
val x = args.getDouble(0).toFloat().toPx()
val y = args.getDouble(1).toFloat().toPx()
marker?.setPositionByPixels(x, y)
}
}
}
package cn.qiuxiang.react.amap3d.maps
import android.view.View
import cn.qiuxiang.react.amap3d.toLatLng
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.annotations.ReactProp
@Suppress("unused")
internal class AMapMarkerManager : ViewGroupManager<AMapMarker>() {
override fun getName(): String {
return "AMapMarker"
}
override fun createViewInstance(reactContext: ThemedReactContext): AMapMarker {
return AMapMarker(reactContext)
}
override fun addView(marker: AMapMarker, view: View, index: Int) {
when (view) {
is AMapInfoWindow -> marker.infoWindow = view
else -> super.addView(marker, view, index)
}
}
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
return MapBuilder.of(
"onPress", MapBuilder.of("registrationName", "onPress"),
"onDragStart", MapBuilder.of("registrationName", "onDragStart"),
"onDrag", MapBuilder.of("registrationName", "onDrag"),
"onDragEnd", MapBuilder.of("registrationName", "onDragEnd"),
"onInfoWindowPress", MapBuilder.of("registrationName", "onInfoWindowPress")
)
}
companion object {
val UPDATE = 1
val ACTIVE = 2
val LOCK_TO_SCREEN = 3
}
override fun getCommandsMap(): Map<String, Int> {
return mapOf(
"update" to UPDATE,
"active" to ACTIVE,
"lockToScreen" to LOCK_TO_SCREEN
)
}
override fun receiveCommand(marker: AMapMarker, commandId: Int, args: ReadableArray?) {
when (commandId) {
UPDATE -> marker.updateIcon()
ACTIVE -> marker.active = true
LOCK_TO_SCREEN -> marker.lockToScreen(args)
}
}
@ReactProp(name = "title")
fun setTitle(marker: AMapMarker, title: String) {
marker.title = title
}
@ReactProp(name = "description")
fun setSnippet(marker: AMapMarker, description: String) {
marker.snippet = description
}
@ReactProp(name = "coordinate")
fun setCoordinate(view: AMapMarker, coordinate: ReadableMap) {
view.position = coordinate.toLatLng()
}
@ReactProp(name = "draggable")
fun setDraggable(marker: AMapMarker, draggable: Boolean) {
marker.draggable = draggable
}
@ReactProp(name = "active")
fun setSelected(marker: AMapMarker, active: Boolean) {
marker.active = active
}
@ReactProp(name = "color")
fun setIcon(marker: AMapMarker, icon: String) {
marker.setIconColor(icon)
}
@ReactProp(name = "image")
fun setImage(marker: AMapMarker, image: String) {
marker.setImage(image)
}
@ReactProp(name = "zIndex")
fun setZIndez(marker: AMapMarker, zIndex: Float) {
marker.zIndex = zIndex
}
@ReactProp(name = "anchor")
fun setAnchor(view: AMapMarker, coordinate: ReadableMap) {
view.setAnchor(coordinate.getDouble("x"), coordinate.getDouble("y"))
}
}
package cn.qiuxiang.react.amap3d.maps
import com.amap.api.maps2d.AMap
interface AMapOverlay {
fun add(map: AMap)
fun remove()
}
\ No newline at end of file
package cn.qiuxiang.react.amap3d.maps
import android.content.Context
import android.graphics.Color
import cn.qiuxiang.react.amap3d.toLatLngList
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.model.LatLng
import com.amap.api.maps2d.model.Polygon
import com.amap.api.maps2d.model.PolygonOptions
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.views.view.ReactViewGroup
class AMapPolygon(context: Context) : ReactViewGroup(context), AMapOverlay {
private var polygon: Polygon? = null
private var coordinates: ArrayList<LatLng> = ArrayList()
var strokeWidth: Float = 1f
set(value) {
field = value
polygon?.strokeWidth = value
}
var strokeColor: Int = Color.BLACK
set(value) {
field = value
polygon?.strokeColor = value
}
var fillColor: Int = Color.BLACK
set(value) {
field = value
polygon?.fillColor = value
}
var zIndex: Float = 0f
set(value) {
field = value
polygon?.zIndex = value
}
fun setCoordinates(coordinates: ReadableArray) {
this.coordinates = coordinates.toLatLngList()
polygon?.points = this.coordinates
}
override fun add(map: AMap) {
polygon = map.addPolygon(PolygonOptions()
.addAll(coordinates)
.strokeColor(strokeColor)
.strokeWidth(strokeWidth)
.fillColor(fillColor)
.zIndex(zIndex))
}
override fun remove() {
polygon?.remove()
}
}
package cn.qiuxiang.react.amap3d.maps
import cn.qiuxiang.react.amap3d.toPx
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
@Suppress("unused")
internal class AMapPolygonManager : SimpleViewManager<AMapPolygon>() {
override fun getName(): String {
return "AMapPolygon"
}
override fun createViewInstance(reactContext: ThemedReactContext): AMapPolygon {
return AMapPolygon(reactContext)
}
@ReactProp(name = "coordinates")
fun setCoordinate(polygon: AMapPolygon, coordinates: ReadableArray) {
polygon.setCoordinates(coordinates)
}
@ReactProp(name = "fillColor", customType = "Color")
fun setFillColor(polygon: AMapPolygon, fillColor: Int) {
polygon.fillColor = fillColor
}
@ReactProp(name = "strokeColor", customType = "Color")
fun setStrokeColor(polygon: AMapPolygon, strokeColor: Int) {
polygon.strokeColor = strokeColor
}
@ReactProp(name = "strokeWidth")
fun setStrokeWidth(polygon: AMapPolygon, strokeWidth: Float) {
polygon.strokeWidth = strokeWidth.toPx().toFloat()
}
@ReactProp(name = "zIndex")
fun setZindex(polygon: AMapPolygon, zIndex: Float) {
polygon.zIndex = zIndex
}
}
package cn.qiuxiang.react.amap3d.maps
import android.content.Context
import android.graphics.Color
import cn.qiuxiang.react.amap3d.toLatLngList
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.model.LatLng
import com.amap.api.maps2d.model.Polyline
import com.amap.api.maps2d.model.PolylineOptions
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.views.view.ReactViewGroup
class AMapPolyline(context: Context) : ReactViewGroup(context), AMapOverlay {
var polyline: Polyline? = null
private set
private var coordinates: ArrayList<LatLng> = ArrayList()
private var colors: ArrayList<Int> = ArrayList()
var width: Float = 1f
set(value) {
field = value
polyline?.width = value
}
var color: Int = Color.BLACK
set(value) {
field = value
polyline?.color = value
}
var zIndex: Float = 0f
set(value) {
field = value
polyline?.zIndex = value
}
var geodesic: Boolean = false
set(value) {
field = value
polyline?.isGeodesic = value
}
var dashed: Boolean = false
set(value) {
field = value
polyline?.isDottedLine = value
}
var gradient: Boolean = false
fun setCoordinates(coordinates: ReadableArray) {
this.coordinates = coordinates.toLatLngList()
polyline?.points = this.coordinates
}
fun setColors(colors: ReadableArray) {
this.colors = ArrayList((0 until colors.size()).map { colors.getInt(it) })
}
override fun add(map: AMap) {
polyline = map.addPolyline(PolylineOptions()
.addAll(coordinates)
.color(color)
.width(width)
.geodesic(geodesic)
.setDottedLine(dashed)
.zIndex(zIndex))
}
override fun remove() {
polyline?.remove()
}
}
package cn.qiuxiang.react.amap3d.maps
import cn.qiuxiang.react.amap3d.toPx
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
@Suppress("unused")
internal class AMapPolylineManager : SimpleViewManager<AMapPolyline>() {
override fun getName(): String {
return "AMapPolyline"
}
override fun createViewInstance(reactContext: ThemedReactContext): AMapPolyline {
return AMapPolyline(reactContext)
}
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
return mapOf("onPress" to mapOf("registrationName" to "onPress"))
}
@ReactProp(name = "coordinates")
fun setCoordinate(polyline: AMapPolyline, coordinates: ReadableArray) {
polyline.setCoordinates(coordinates)
}
@ReactProp(name = "colors")
fun setColors(polyline: AMapPolyline, colors: ReadableArray) {
polyline.setColors(colors)
}
@ReactProp(name = "color", customType = "Color")
fun setColor(polyline: AMapPolyline, color: Int) {
polyline.color = color
}
@ReactProp(name = "width")
fun setWidth(polyline: AMapPolyline, width: Float) {
polyline.width = width.toPx().toFloat()
}
@ReactProp(name = "zIndex")
fun setZIndex_(polyline: AMapPolyline, zIndex: Float) {
polyline.zIndex = zIndex
}
@ReactProp(name = "geodesic")
fun setGeodesic(polyline: AMapPolyline, geodesic: Boolean) {
polyline.geodesic = geodesic
}
@ReactProp(name = "dashed")
fun setDashed(polyline: AMapPolyline, dashed: Boolean) {
polyline.dashed = dashed
}
@ReactProp(name = "gradient")
fun setGradient(polyline: AMapPolyline, gradient: Boolean) {
polyline.gradient = gradient
}
}
package cn.qiuxiang.react.amap3d.maps
import android.content.Context
import android.view.MotionEvent
import android.view.View
import cn.qiuxiang.react.amap3d.toLatLng
import cn.qiuxiang.react.amap3d.toLatLngBounds
import cn.qiuxiang.react.amap3d.toWritableMap
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.CameraUpdateFactory
import com.amap.api.maps2d.MapView
import com.amap.api.maps2d.model.BitmapDescriptorFactory
import com.amap.api.maps2d.model.CameraPosition
import com.amap.api.maps2d.model.Marker
import com.amap.api.maps2d.model.MyLocationStyle
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.events.RCTEventEmitter
class AMapView(context: Context) : MapView(context) {
private val eventEmitter: RCTEventEmitter = (context as ThemedReactContext).getJSModule(RCTEventEmitter::class.java)
private val markers = HashMap<String, AMapMarker>()
private val lines = HashMap<String, AMapPolyline>()
var touchEnable: Boolean = true
private val locationStyle by lazy {
val locationStyle = MyLocationStyle()
locationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER)
locationStyle
}
init {
super.onCreate(null)
map.setOnMapClickListener { latLng ->
for (marker in markers.values) {
marker.active = false
}
emit(id, "onMapPress", latLng.toWritableMap())
}
map.setOnMapLongClickListener { latLng ->
emit(id, "onLongPress", latLng.toWritableMap())
}
map.setOnMyLocationChangeListener { location ->
val event = Arguments.createMap()
event.putDouble("latitude", location.latitude)
event.putDouble("longitude", location.longitude)
event.putDouble("accuracy", location.accuracy.toDouble())
event.putDouble("altitude", location.altitude)
event.putDouble("speed", location.speed.toDouble())
event.putInt("timestamp", location.time.toInt())
emit(id, "onLocation", event)
}
map.setOnMarkerClickListener { marker ->
markers[marker.id]?.let {
it.active = true
emit(it.id, "onPress")
}
true
}
map.setOnMarkerDragListener(object : AMap.OnMarkerDragListener {
override fun onMarkerDragStart(marker: Marker) {
emit(markers[marker.id]?.id, "onDragStart")
}
override fun onMarkerDrag(marker: Marker) {
emit(markers[marker.id]?.id, "onDrag")
}
override fun onMarkerDragEnd(marker: Marker) {
emit(markers[marker.id]?.id, "onDragEnd", marker.position.toWritableMap())
}
})
map.setOnCameraChangeListener(object : AMap.OnCameraChangeListener {
override fun onCameraChangeFinish(position: CameraPosition?) {
emitCameraChangeEvent("onStatusChangeComplete", position)
}
override fun onCameraChange(position: CameraPosition?) {
emitCameraChangeEvent("onStatusChange", position)
}
})
map.setOnInfoWindowClickListener { marker ->
emit(markers[marker.id]?.id, "onInfoWindowPress")
}
map.setInfoWindowAdapter(AMapInfoWindowAdapter(context, markers))
}
fun emitCameraChangeEvent(event: String, position: CameraPosition?) {
position?.let {
val data = it.target.toWritableMap()
data.putDouble("zoomLevel", it.zoom.toDouble())
data.putDouble("tilt", it.tilt.toDouble())
data.putDouble("rotation", it.bearing.toDouble())
if (event == "onStatusChangeComplete") {
val southwest = map.projection.visibleRegion.latLngBounds.southwest
val northeast = map.projection.visibleRegion.latLngBounds.northeast
data.putDouble("latitudeDelta", Math.abs(southwest.latitude - northeast.latitude))
data.putDouble("longitudeDelta", Math.abs(southwest.longitude - northeast.longitude))
}
emit(id, event, data)
}
}
fun emit(id: Int?, name: String, data: WritableMap = Arguments.createMap()) {
id?.let { eventEmitter.receiveEvent(it, name, data) }
}
fun add(child: View) {
if (child is AMapOverlay) {
child.add(map)
if (child is AMapMarker) {
markers[child.marker?.id!!] = child
}
if (child is AMapPolyline) {
lines[child.polyline?.id!!] = child
}
}
}
fun remove(child: View) {
if (child is AMapOverlay) {
child.remove()
if (child is AMapMarker) {
markers.remove(child.marker?.id)
}
if (child is AMapPolyline) {
lines.remove(child.polyline?.id)
}
}
}
private val animateCallback = object : AMap.CancelableCallback {
override fun onCancel() {
emit(id, "onAnimateCancel")
}
override fun onFinish() {
emit(id, "onAnimateFinish")
}
}
fun animateTo(args: ReadableArray?) {
val currentCameraPosition = map.cameraPosition
val target = args?.getMap(0)!!
val duration = args.getInt(1)
var coordinate = currentCameraPosition.target
var zoomLevel = currentCameraPosition.zoom
var tilt = currentCameraPosition.tilt
var rotation = currentCameraPosition.bearing
if (target.hasKey("coordinate")) {
coordinate = target.getMap("coordinate").toLatLng()
}
if (target.hasKey("zoomLevel")) {
zoomLevel = target.getDouble("zoomLevel").toFloat()
}
if (target.hasKey("tilt")) {
tilt = target.getDouble("tilt").toFloat()
}
if (target.hasKey("rotation")) {
rotation = target.getDouble("rotation").toFloat()
}
val cameraUpdate = CameraUpdateFactory.newCameraPosition(
CameraPosition(coordinate, zoomLevel, tilt, rotation))
map.animateCamera(cameraUpdate, duration.toLong(), animateCallback)
}
fun setRegion(region: ReadableMap) {
map.moveCamera(CameraUpdateFactory.newLatLngBounds(region.toLatLngBounds(), 0))
}
fun setLocationEnabled(enabled: Boolean) {
map.isMyLocationEnabled = enabled
map.setMyLocationStyle(locationStyle)
}
fun setLocationInterval(interval: Long) {
locationStyle.interval(interval)
}
fun setLocationStyle(style: ReadableMap) {
if (style.hasKey("fillColor")) {
locationStyle.radiusFillColor(style.getInt("fillColor"))
}
if (style.hasKey("strokeColor")) {
locationStyle.strokeColor(style.getInt("strokeColor"))
}
if (style.hasKey("strokeWidth")) {
locationStyle.strokeWidth(style.getDouble("strokeWidth").toFloat())
}
if (style.hasKey("image")) {
val drawable = context.resources.getIdentifier(
style.getString("image"), "drawable", context.packageName)
locationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(drawable))
}
}
fun setLocationType(type: Int) {
locationStyle.myLocationType(type)
map.setMyLocationStyle(locationStyle)
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return !touchEnable
}
}
package cn.qiuxiang.react.amap3d.maps
import android.view.View
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.CameraUpdateFactory
import com.amap.api.maps2d.model.LatLng
import com.amap.api.maps2d.model.MyLocationStyle
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.annotations.ReactProp
@Suppress("unused")
internal class AMapViewManager : ViewGroupManager<AMapView>() {
companion object {
val ANIMATE_TO = 1
}
override fun getName(): String {
return "AMapView"
}
override fun createViewInstance(reactContext: ThemedReactContext): AMapView {
return AMapView(reactContext)
}
override fun onDropViewInstance(view: AMapView) {
super.onDropViewInstance(view)
view.onDestroy()
}
override fun getCommandsMap(): Map<String, Int> {
return mapOf("animateTo" to ANIMATE_TO)
}
override fun receiveCommand(overlay: AMapView, commandId: Int, args: ReadableArray?) {
when (commandId) {
ANIMATE_TO -> overlay.animateTo(args)
}
}
override fun addView(mapView: AMapView, child: View, index: Int) {
mapView.add(child)
super.addView(mapView, child, index)
}
override fun removeViewAt(parent: AMapView, index: Int) {
parent.remove(parent.getChildAt(index))
super.removeViewAt(parent, index)
}
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
return MapBuilder.of(
"onMapPress", MapBuilder.of("registrationName", "onMapPress"),
"onLongPress", MapBuilder.of("registrationName", "onLongPress"),
"onAnimateCancel", MapBuilder.of("registrationName", "onAnimateCancel"),
"onAnimateFinish", MapBuilder.of("registrationName", "onAnimateFinish"),
"onStatusChange", MapBuilder.of("registrationName", "onStatusChange"),
"onStatusChangeComplete", MapBuilder.of("registrationName", "onStatusChangeComplete"),
"onLocation", MapBuilder.of("registrationName", "onLocation")
)
}
@ReactProp(name = "locationEnabled")
fun setMyLocationEnabled(view: AMapView, enabled: Boolean) {
view.setLocationEnabled(enabled)
}
@ReactProp(name = "showsCompass")
fun setCompassEnabled(view: AMapView, show: Boolean) {
view.map.uiSettings.isCompassEnabled = show
}
@ReactProp(name = "showsZoomControls")
fun setZoomControlsEnabled(view: AMapView, enabled: Boolean) {
view.map.uiSettings.isZoomControlsEnabled = enabled
}
@ReactProp(name = "showsScale")
fun setScaleControlsEnabled(view: AMapView, enabled: Boolean) {
view.map.uiSettings.isScaleControlsEnabled = enabled
}
@ReactProp(name = "showsLocationButton")
fun setMyLocationButtonEnabled(view: AMapView, enabled: Boolean) {
view.map.uiSettings.isMyLocationButtonEnabled = enabled
}
@ReactProp(name = "showsTraffic")
fun setTrafficEnabled(view: AMapView, enabled: Boolean) {
view.map.isTrafficEnabled = enabled
}
@ReactProp(name = "zoomLevel")
fun setZoomLevel(view: AMapView, zoomLevel: Float) {
view.map.moveCamera(CameraUpdateFactory.zoomTo(zoomLevel))
}
@ReactProp(name = "mapType")
fun setMapType(view: AMapView, mapType: String) {
when (mapType) {
"standard" -> view.map.mapType = AMap.MAP_TYPE_NORMAL
"satellite" -> view.map.mapType = AMap.MAP_TYPE_SATELLITE
}
}
@ReactProp(name = "zoomEnabled")
fun setZoomGesturesEnabled(view: AMapView, enabled: Boolean) {
view.map.uiSettings.isZoomGesturesEnabled = enabled
}
@ReactProp(name = "scrollEnabled")
fun setScrollGesturesEnabled(view: AMapView, enabled: Boolean) {
view.map.uiSettings.isScrollGesturesEnabled = enabled
}
@ReactProp(name = "coordinate")
fun moveToCoordinate(view: AMapView, coordinate: ReadableMap) {
view.map.moveCamera(CameraUpdateFactory.changeLatLng(LatLng(
coordinate.getDouble("latitude"),
coordinate.getDouble("longitude"))))
}
@ReactProp(name = "region")
fun setRegion(view: AMapView, region: ReadableMap) {
view.setRegion(region)
}
@ReactProp(name = "locationInterval")
fun setLocationInterval(view: AMapView, interval: Int) {
view.setLocationInterval(interval.toLong())
}
@ReactProp(name = "locationStyle")
fun setLocationStyle(view: AMapView, style: ReadableMap) {
view.setLocationStyle(style)
}
@ReactProp(name = "touchEnable")
fun setViewTouchEnable(view: AMapView, enabled: Boolean){
view.touchEnable = enabled
}
@ReactProp(name = "locationType")
fun setLocationStyle(view: AMapView, type: String) {
when (type) {
"show" -> view.setLocationType(MyLocationStyle.LOCATION_TYPE_SHOW)
"locate" -> view.setLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE)
"follow" -> view.setLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW)"follow_no_center" -> view.setLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER)
}
}
}
/**
* 基础组件,包含一些公共方法
*
* @flow
*/
import { PureComponent } from 'react'
import { findNodeHandle, UIManager } from 'react-native'
export default class Component<T> extends PureComponent<T> {
/**
* 原生组件名称
*/
name: string
/**
* 调用原生方法
*
* @private
*/
sendCommand(command: string, params?: any[]) {
UIManager.dispatchViewManagerCommand(
findNodeHandle(this),
UIManager[this.name].Commands[command],
params,
)
}
}
import PropTypes from 'prop-types'
const LatLng = PropTypes.shape({
latitude: PropTypes.number.isRequired,
longitude: PropTypes.number.isRequired,
})
const Region = PropTypes.shape({
latitude: PropTypes.number.isRequired,
longitude: PropTypes.number.isRequired,
latitudeDelta: PropTypes.number.isRequired,
longitudeDelta: PropTypes.number.isRequired,
})
const Point = PropTypes.shape({
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
})
export { LatLng, Region, Point }
import MapView from './maps/MapView'
import Marker from './maps/Marker'
import Polygon from './maps/Polygon'
import Circle from './maps/Circle'
MapView.Marker = Marker
MapView.Polygon = Polygon
MapView.Circle = Circle
export default MapView
export {
MapView,
Marker,
Polygon,
Circle,
}
// import MapView from './maps/MapView'
// import Marker from './maps/Marker'
// import Polygon from './maps/Polygon'
// import Circle from './maps/Circle'
import { Map, Marker as RMarker } from 'react-amap';
const MapView = (props) => {
return <Map {...props} center={props.coordinate}></Map>
}
const Marker = (props) => {
return <RMarker {...props} center={props.coordinate} />
}
MapView.Marker = Marker
export default MapView
export {
MapView,
Marker,
}
import PropTypes from 'prop-types'
import { ColorPropType, requireNativeComponent, ViewPropTypes } from 'react-native'
import { LatLng } from '../PropTypes'
export default requireNativeComponent('AMapCircle', {
propTypes: {
...ViewPropTypes,
/**
* 圆点坐标
*/
coordinate: LatLng.isRequired,
/**
* 半径(米)
*/
radius: PropTypes.number.isRequired,
/**
* 边线宽度
*/
strokeWidth: PropTypes.number,
/**
* 边线颜色
*/
strokeColor: ColorPropType,
/**
* 填充颜色
*/
fillColor: ColorPropType,
/**
* 层级
*/
zIndex: PropTypes.number,
},
})
// @flow
import React from 'react'
import PropTypes from 'prop-types'
import { processColor, requireNativeComponent, ViewPropTypes, Platform } from 'react-native'
import { LatLng, Region } from '../PropTypes'
import Component from '../Component'
export type MapStatus = {
zoomLevel?: number,
coordinate?: LatLng,
titl?: number,
rotation?: number,
}
export const LocationStyle = PropTypes.shape({
image: PropTypes.string,
fillColor: PropTypes.string,
strokeColor: PropTypes.string,
strokeWidth: PropTypes.number,
})
const isIos = Platform.OS === 'ios'
export default class MapView extends Component<any> {
static propTypes = {
...ViewPropTypes,
/**
* 地图类型
*
* - standard: 标准地图
* - satellite: 卫星地图
* - navigation: 导航地图
* - night: 夜间地图
* - bus: 公交地图
*/
mapType: PropTypes.oneOf(['standard', 'satellite', 'navigation', 'night', 'bus']),
/**
* 是否启用跟踪模式
* 0: 不跟踪
* 1: 跟踪用户定位
* 2: 跟踪用户定位和方向
*/
userTrackingMode: PropTypes.oneOf(0, 1, 2),
/**
* 是否跟踪用户位置
*/
showsUserLocation: PropTypes.bool,
/**
* 缩放尺寸,范围是:[3-19]
*/
zoomLevel: PropTypes.number,
/**
* 设置定位图标的样式
*/
locationStyle: LocationStyle,
/**
* 设置定位模式 默认 LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER
*
* @platform android
*/
locationType: PropTypes.oneOf(['show', 'locate', 'follow', 'map_rotate', 'location_rotate',
'location_rotate_no_center', 'follow_no_center', 'map_rotate_no_center']),
/**
* 是否启用定位
*/
locationEnabled: PropTypes.bool,
/**
* 定位间隔(ms),默认 2000
*
* @platform android
*/
locationInterval: PropTypes.number,
/**
* 定位的最小更新距离
*
* @platform ios
*/
distanceFilter: PropTypes.number,
/**
* 是否显示室内地图
*/
showsIndoorMap: PropTypes.bool,
/**
* 是否显示室内地图楼层切换控件
*
* TODO: 似乎并不能正常显示
*/
showsIndoorSwitch: PropTypes.bool,
/**
* 是否显示3D建筑
*/
showsBuildings: PropTypes.bool,
/**
* 是否显示文本标签
*/
showsLabels: PropTypes.bool,
/**
* 是否显示指南针
*/
showsCompass: PropTypes.bool,
/**
* 是否显示放大缩小按钮
*
* @platform android
*/
showsZoomControls: PropTypes.bool,
/**
* 是否显示比例尺
*/
showsScale: PropTypes.bool,
/**
* 是否显示定位按钮
*
* @platform android
*/
showsLocationButton: PropTypes.bool,
/**
* 是否显示路况
*/
showsTraffic: PropTypes.bool,
/**
* 最大缩放级别
*/
maxZoomLevel: PropTypes.number,
/**
* 最小缩放级别
*/
minZoomLevel: PropTypes.number,
/**
* 当前缩放级别,取值范围 [3, 20]
*/
zoomLevel: PropTypes.number,
/**
* 中心坐标
*/
coordinate: LatLng,
/**
* 显示区域
*/
region: Region,
/**
* 限制地图只能显示某个矩形区域
*/
limitRegion: Region,
/**
* 倾斜角度,取值范围 [0, 60]
*/
tilt: PropTypes.number,
/**
* 旋转角度
*/
rotation: PropTypes.number,
/**
* 是否启用缩放手势,用于放大缩小
*/
zoomEnabled: PropTypes.bool,
/**
* 是否启用滑动手势,用于平移
*/
scrollEnabled: PropTypes.bool,
/**
* 是否启用旋转手势,用于调整方向
*/
rotateEnabled: PropTypes.bool,
/**
* 是否启用倾斜手势,用于改变视角
*/
tiltEnabled: PropTypes.bool,
/**
* 是否可以触摸
*/
touchEnable: PropTypes.bool,
/**
* 是否启用定位
*/
showsUserLocation: PropTypes.bool,
/**
* 中心坐标
*/
centerLocation: LatLng,
/**
* 点击事件
*
* @param {{ nativeEvent: LatLng }}
*/
onMapPress: PropTypes.func,
/**
* 长按事件
*
* @param {{ nativeEvent: LatLng }}
*/
onLongPress: PropTypes.func,
/**
* 定位事件
*
* @param {{
* nativeEvent: {
* timestamp: number,
* speed: number,
* accuracy: number,
* altitude: number,
* longitude: number,
* latitude: number,
* }
* }}
*/
onLocation: PropTypes.func,
/**
* 动画完成事件
*/
onAnimateFinish: PropTypes.func,
/**
* 动画取消事件
*/
onAnimateCancel: PropTypes.func,
/**
* 地图状态变化事件
*
* @param {{
* nativeEvent: {
* longitude: number,
* latitude: number,
* rotation: number,
* zoomLevel: number,
* tilt: number,
* }
* }}
*/
onStatusChange: PropTypes.func,
/**
* 地图状态变化完成事件
*
* @param {{
* nativeEvent: {
* longitude: number,
* latitude: number,
* longitudeDelta: number,
* latitudeDelta: number,
* rotation: number,
* zoomLevel: number,
* tilt: number,
* }
* }}
*/
onStatusChangeComplete: PropTypes.func,
}
name = 'AMapView'
isMapFirstLoaded = false
_isMoveByUser = true
lastCompleteTime = 0
_onMoveComplete = (event) => {
const oldLastCompleteTime = this.lastCompleteTime
this.lastCompleteTime = new Date().getTime()
if ((this.lastCompleteTime - oldLastCompleteTime) < 700) {
this._isMoveByUser = true
return
}
if (isIos && !this.isMapFirstLoaded) {
this.isMapFirstLoaded = true
this._isMoveByUser = true
return
}
this.props.onStatusChangeComplete && this.props.onStatusChangeComplete(event, this._isMoveByUser)
this._isMoveByUser = true
}
componentWillReceiveProps({ coordinate }) {
const oldCoordinate = this.props.coordinate
if (coordinate && oldCoordinate) {
const { latitude, longitude } = coordinate
const oldLatitude = oldCoordinate.latitude
const oldLongitude = oldCoordinate.longitude
if ((latitude != oldLatitude) && (longitude != oldLongitude)) {
this._isMoveByUser = false
}
} else if (coordinate) {
this._isMoveByUser = false
}
}
_onMovingChange = (event) => {
if (isIos && !this.isMapFirstLoaded) {
return
}
this.props.onStatusChange && this.props.onStatusChange(event, this._isMoveByUser)
}
/**
* 动画过渡到某个状态(坐标、缩放级别、倾斜度、旋转角度)
*/
animateTo(target: MapStatus, duration?: number = 500) {
this.sendCommand('animateTo', [target, duration])
}
onMapPress = (event) => {
if (this.props.onMapPress) {
this.props.onMapPress(event)
}
}
render() {
const props = { ...this.props }
const { centerLocation } = this.props
if (centerLocation) {
delete props.centerLocation
props.coordinate = centerLocation
}
if (props.locationStyle) {
if (props.locationStyle.strokeColor) {
props.locationStyle.strokeColor = processColor(props.locationStyle.strokeColor)
}
if (props.locationStyle.fillColor) {
props.locationStyle.fillColor = processColor(props.locationStyle.fillColor)
}
}
return <AMapView {...props} onMapPress={this.onMapPress} onStatusChange={this._onMovingChange} onStatusChangeComplete={this._onMoveComplete} />
}
}
const AMapView = requireNativeComponent('AMapView', MapView)
// @flow
import React from 'react'
import PropTypes from 'prop-types'
import { Platform, requireNativeComponent, StyleSheet, ViewPropTypes, View } from 'react-native'
import { LatLng, Point } from '../PropTypes'
import Component from '../Component'
const style = StyleSheet.create({
overlay: {
position: 'absolute',
},
})
export default class Marker extends Component<any> {
static propTypes = {
...ViewPropTypes,
/**
* key
*/
markKey: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
/**
* 坐标
*/
coordinate: LatLng.isRequired,
/**
* 标题,作为默认的选中弹出显示
*/
title: PropTypes.string,
/**
* 描述,显示在标题下方
*/
description: PropTypes.string,
/**
* 默认图标颜色
*/
color: Platform.select({
android: PropTypes.oneOf([
'azure',
'blue',
'cyan',
'green',
'magenta',
'orange',
'red',
'rose',
'violet',
'yellow',
]),
ios: PropTypes.oneOf([
'red',
'green',
'purple',
]),
}),
/**
* 自定义图标
*/
icon: PropTypes.func,
/**
* 自定义图片,对应原生图片名称
*/
image: PropTypes.string,
/**
* 透明度 [0, 1]
*/
opacity: PropTypes.number,
/**
* 是否可拖拽
*/
draggable: PropTypes.bool,
/**
* 是否平贴地图
*/
flat: PropTypes.bool,
/**
* 层级
*/
zIndex: PropTypes.number,
/**
* 覆盖物锚点比例
*
* @link http://a.amap.com/lbs/static/unzip/Android_Map_Doc/3D/com/amap/api/maps/model/Marker.html#setAnchor-float-float-
* @platform android
*/
anchor: Point,
/**
* 覆盖物偏移位置
*
* @link http://a.amap.com/lbs/static/unzip/iOS_Map_Doc/AMap_iOS_API_Doc_3D/interface_m_a_annotation_view.html#a78f23c1e6a6d92faf12a00877ac278a7
* @platform ios
*/
centerOffset: Point,
/**
* 是否选中,选中时将显示信息窗体,一个地图只能有一个正在选中的 marker
*/
active: PropTypes.bool,
/**
* 是否禁用点击,默认不禁用
*/
clickDisabled: PropTypes.bool,
/**
* 是否禁用弹出窗口,默认不禁用
*/
infoWindowDisabled: PropTypes.bool,
/**
* 点击事件
*/
onPress: PropTypes.func,
/**
* 拖放开始事件
*/
onDragStart: PropTypes.func,
/**
* 拖放进行事件,类似于 mousemove,在结束之前会不断调用
*/
onDrag: PropTypes.func,
/**
* 拖放结束事件,最终坐标将传入参数
*/
onDragEnd: PropTypes.func,
/**
* 信息窗体点击事件
*
* 注意,对于自定义信息窗体,该事件是无效的
*/
onInfoWindowPress: PropTypes.func,
}
componentDidUpdate() {
if (this.icon && Platform.OS === 'android') {
setTimeout(() => this.sendCommand('update'), 0)
}
}
name = 'AMapMarker'
icon: View = null
onMarkPress = () => {
if (this.props.onPress) {
this.props.onPress(this.props.markKey)
}
}
active() {
this.sendCommand('active')
}
lockToScreen(x: number, y: number) {
this.sendCommand('lockToScreen', [x, y])
}
renderCustomMarker(icon: () => View) {
if (icon) {
this.icon = <View style={style.overlay}>{icon()}</View>
return this.icon
}
return null
}
/* eslint-disable class-methods-use-this */
renderInfoWindow(view: View) {
if (view) {
return <InfoWindow style={style.overlay}>{view}</InfoWindow>
}
return null
}
render() {
return (
<AMapMarker {...this.props} onPress={this.onMarkPress}>
{this.renderCustomMarker(this.props.icon)}
{this.renderInfoWindow(this.props.children)}
</AMapMarker>
)
}
}
const AMapMarker = requireNativeComponent('AMapMarker', Marker)
const InfoWindow = requireNativeComponent('AMapInfoWindow', {
propTypes: {
...ViewPropTypes,
},
})
import PropTypes from 'prop-types'
import { ColorPropType, requireNativeComponent, ViewPropTypes } from 'react-native'
import { LatLng } from '../PropTypes'
export default requireNativeComponent('AMapPolygon', {
propTypes: {
...ViewPropTypes,
/**
* 节点坐标
*/
coordinates: PropTypes.arrayOf(LatLng).isRequired,
/**
* 边线宽度
*/
strokeWidth: PropTypes.number,
/**
* 边线颜色
*/
strokeColor: ColorPropType,
/**
* 填充颜色
*/
fillColor: ColorPropType,
/**
* 层级
*/
zIndex: PropTypes.number,
},
})
import { NativeModules, NativeEventEmitter, DeviceEventEmitter, Platform } from 'react-native';
const locationManager = NativeModules.RNLocationManager;
const geocodeManager = NativeModules.RNGeocodeManager;
const mapNavigationManager = NativeModules.RNMapNavigationManager;
const geocodeManagerEmitter = new NativeEventEmitter(geocodeManager)
let lastId = "", promiseQueue = {}
const requestIdGenerator = (type = "geocode") => {
let requestId = `${type}-${+new Date}-${Math.ceil(Math.random() * 100000)}`
if (requestId == lastId) {
return requestIdGenerator(type)
}
lastId = requestId;
return lastId;
}
const searchRequestFactory = (type) => (...args) => {
if (geocodeManager[type]) {
let resolve, reject, promise = new Promise((res, rej) => {
resolve = res, reject = rej
}),
requestId = requestIdGenerator(type)
args = [requestId, ...args]
geocodeManager[type].apply(null, args)
promiseQueue[requestId] = { resolve, reject }
return promise
}
}
// const emitter = Platform.OS == 'ios' ? NativeAppEventEmitter : DeviceEventEmitter
geocodeManagerEmitter.addListener(
'geocode',
(reminder) => {
let {data, error, requestId} = reminder
if (requestId && promiseQueue[requestId]) {
let promise = promiseQueue[requestId];
if (error) {
promise.reject(error)
} else {
promise.resolve(data)
}
delete promiseQueue[requestId];
}
}
)
const fetchLocation = (handler) => {
if (Platform.OS === 'ios') {
locationManager.location().then(handler, (error) => {
handler(null, error);
})
}
else if (Platform.OS === 'android') {
locationManager.location();
var locationListener = DeviceEventEmitter.addListener(
'AMapLocationResultEvent',
(data) => {
var error = data.error || {}
if(error.code === 12){
// 和iOS统一`没有权限`的错误码返回
data.error.code = 'authorized_deny'
}
if (typeof handler === 'function') {
handler(data, data.error);
}
locationManager.stopLocation();
locationListener.remove();
}
);
}
}
const mapNavigation = (info)=>{
mapNavigationManager.mapNavigation(info)
}
module.exports.fetchLocation = fetchLocation;
module.exports.searchRequestFactory = searchRequestFactory;
module.exports.mapNavigation = mapNavigation;
\ No newline at end of file
let src = null;
const setAmapKey = (key, plugin = 'AMap.Geocoder') => {
src = `//webapi.amap.com/maps?v=1.3&key=${key}&plugin=${plugin}`;
}
const fetchLocation = (callback) => {
const located = () => {
let map, geolocation;
//加载地图,调用浏览器定位服务
map = new AMap.Map('map-container', { // 'map-container' 可以不存在,即不加载地图
resizeEnable: true
});
map.plugin('AMap.Geolocation', function() {
geolocation = new AMap.Geolocation({
enableHighAccuracy: true,//是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位,默认:无穷大
buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
zoomToAccuracy: true, //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
buttonPosition:'RB'
});
map.addControl(geolocation);
geolocation.getCurrentPosition();
AMap.event.addListener(geolocation, 'complete', (data) => typeof callback === 'function' && callback(transData(data)));//返回定位信息
AMap.event.addListener(geolocation, 'error', (error) => typeof callback === 'function' && callback(null, error)); //返回定位出错信息
});
}
if (!window.AMap) {
if (src) {
inserScript(located);
} else {
console.error('please use setAmapKey to set key');
}
} else if (AMap && !AMap.Map) {
console.error('please use plugin AMap.Geocoder');
} else if (AMap && AMap.Map){
located();
}
}
const inserScript = (cb) => {
const attr = {
name: 'amap_terminus',
src,
type: 'text/javascript'
};
let parent = document.querySelector('body'); // 容器
let script = parent && parent.querySelector(`[name=${attr.name}]`);
if (script) {
if (typeof cb === 'function') {
cb();
}
} else {
script = document.createElement('script');
Object.getOwnPropertyNames(attr).map(name => {
script.setAttribute(name, attr[name]);//暂时只支持一层object
});
parent.appendChild(script).addEventListener('load', () => {
if (typeof cb === 'function') {
cb();
}
}, false);
}
}
const transData = (data) => {
const { addressComponent, formattedAddress, pois, position, POIName, AOIName } = data;
return {
latitude: `${position.lat}`, // 转为string,统一格式
longitude: `${position.lng}`,
formattedAddress,
pois,
province: addressComponent.province,
city: addressComponent.city,
district: addressComponent.district,
citycode: addressComponent.citycode,
adcode: addressComponent.adcode,
street: addressComponent.street,
number: addressComponent.number || addressComponent.streetNumber, // 没有number,存在streetNumber,与rn不一样
country: addressComponent.country, // 没有,与rn不一样
POIName, // 没有,与rn不一样
AOIName, // 没有,与rn不一样
}
}
module.exports.setAmapKey = setAmapKey;
module.exports.fetchLocation = fetchLocation;
import { searchRequestFactory, fetchLocation, mapNavigation } from './app/location';
export const AMapGeocode = searchRequestFactory('geocode')
export const AMapReGeocode = searchRequestFactory('reGeocode')
export const AMapReGeocodeByAmap = searchRequestFactory('reGeocodeByAmap')
export const AMapPOISearch = searchRequestFactory('poiSearch')
export const AMapPOISearchPage = searchRequestFactory('poiSearchWithPage')
export const AMapDistrict = searchRequestFactory('district')
module.exports.fetchLocation = fetchLocation
module.exports.mapNavigation = mapNavigation
export * from './app/amap3d'
import { fetchLocation, setAmapKey } from './app/location';
module.exports.setAmapKey = setAmapKey;
module.exports.fetchLocation = fetchLocation;
//
// Created by Allen Chiang on 17/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface RNAMConfig : NSObject
/**
* 当前app的scheme,用于高德导航唤起以后的回调
*/
@property(nonatomic, copy) NSString *appScheme;
/**
* 高德的appKey
* @param appKey
*/
+ (void)setAppKey:(NSString *)appKey;
+ (instancetype)shareInstance;
@end
\ No newline at end of file
//
// Created by Allen Chiang on 17/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <AMapFoundationKit/AMapFoundationKit.h>
#import "RNAMConfig.h"
@implementation RNAMConfig
+ (void)setAppKey:(NSString *)appKey {
[AMapServices sharedServices].enableHTTPS = YES;
NSAssert(appKey, @"RNAMConfig.setAppKey appKey can not be nil");
[AMapServices sharedServices].apiKey = appKey;
}
+ (instancetype)shareInstance {
static dispatch_once_t once_t;
static RNAMConfig *shareInstance;
dispatch_once(&once_t, ^{
if (!shareInstance) {
shareInstance = [[RNAMConfig alloc] init];
}
});
return shareInstance;
}
@end
//
// Created by Allen Chiang on 17/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <React/RCTEventEmitter.h>
@interface RNAMGeocodeManager : RCTEventEmitter <RCTBridgeModule>
/**
* 地理编码查询,根据地址信息查询GPS
* @param requestId 请求id
* @param address 详细地址
* @param city 城市名称,中文,英文,或者城市编码均可,非必填项
*/
- (void)requestGeocode:(NSString *)requestId
withAddress:(NSString *)address
withCity:(NSString *)city;
/**
* 逆地理编码查询,根据GPS查询详细地址信息
* @param requestId 请求id
* @param latitude 维度
* @param longitude 经度
*/
- (void)requestReGeocode:(NSString *)requestId
withLatitude:(NSString *)latitude
withLongitude:(NSString *)longitude;
/**
* 检索POI信息
* @param requestId 请求id
* @param keywords POI的搜索关键字
* @param cityCode 城市编码,如果不传会自动获取当前定位所在的citycode
*/
- (void)requestPOISearch:(NSString *)requestId
withKeywords:(NSString *)keywords
withCity:(NSString *)cityCode;
/**
* 获取行政区划数据
* @param requestId 请求id
* @param name 地区名称
*/
- (void)requestDistrictSearch:(NSString *)requestId
name:(nullable NSString *)name;
@end
This diff is collapsed.
//
// Created by Allen Chiang on 17/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <React/RCTEventEmitter.h>
@interface RNAMLocationManager : NSObject <RCTBridgeModule>
/**
* 初始化一个AMapLocationManager
* @return AMapLocationManager
*/
- (AMapLocationManager *)locationManager;
/**
* 定位当前位置
*/
- (void)requestLocationResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject;
@end
//
// Created by Allen Chiang on 17/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <AMapLocationKit/AMapLocationKit.h>
#import "RCTBridgeModule.h"
#import "RNAMLocationManager.h"
#import "RNAMLocationDO.h"
#import "RNAMResultDO.h"
NSString *const kRNAMLocationErrorCode_AuthorizeDeny = @"authorized_deny";
NSString *const kRNAMLocationErrorMessage_AuthorizeDeny = @"请开启定位权限";
@implementation RNAMLocationManager {
AMapLocationManager *_locationManager;
}
@synthesize bridge = _bridge;
- (instancetype)init {
self = [super init];
if (self) {
[self locationManager];
}
return self;
}
- (AMapLocationManager *)locationManager {
if (!_locationManager) {
AMapLocationManager *locationManager = [[AMapLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyHundredMeters];
[locationManager setLocationTimeout:2]; // timeout 2 seconds
[locationManager setReGeocodeTimeout:2]; // 逆地理位置 timeout 2 seconds
_locationManager = locationManager;
}
return _locationManager;
}
- (BOOL)hasAuthorized {
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
return (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse
|| status == kCLAuthorizationStatusNotDetermined);
}
- (void)requestLocationResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject {
// 判断定位权限
if (![self hasAuthorized]) {
reject(kRNAMLocationErrorCode_AuthorizeDeny, kRNAMLocationErrorMessage_AuthorizeDeny,
[NSError errorWithDomain:kRNAMLocationErrorCode_AuthorizeDeny code:0 userInfo:nil]);
return;
}
RCTPromiseResolveBlock resolveCopy = [resolve copy];
RCTPromiseRejectBlock rejectCopy = [reject copy];
[_locationManager requestLocationWithReGeocode:YES
completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {
if (error) {
NSLog(@"locError:{%ld - %@};", (long) error.code, error.localizedDescription);
if (rejectCopy) {
rejectCopy([NSString stringWithFormat:@"%d", error.code], error.localizedDescription, error);
}
return;
}
RNAMLocationDO *locationDO = [[RNAMLocationDO alloc] initWithCLLocation:location
withReGeocode:regeocode];
RNAMResultDO *resultDO = [[RNAMResultDO alloc] init];
[resultDO setData:[locationDO dictionary]];
if (resolveCopy) {
resolveCopy([resultDO dictionary]);
}
}];
}
#pragma mark - Export to React Native
RCT_EXPORT_MODULE(RNLocationManager);
RCT_REMAP_METHOD(location,
resolver:
(RCTPromiseResolveBlock) resolve
rejecter:
(RCTPromiseRejectBlock) reject) {
[self requestLocationResolver:resolve rejecter:reject];
}
@end
#import <Foundation/Foundation.h>
#import <React/RCTEventEmitter.h>
@interface RNMapNavigation :NSObject<RCTBridgeModule>
@end
#import "RNAMNavigationManager.h"
#import <MapKit/MapKit.h>
#import "RNAMConfig.h"
@interface RNMapNavigation()
@property(nonatomic,strong) NSString *sname;
@property(nonatomic,strong) NSString *dname;
@property(nonatomic) double slat;
@property(nonatomic) double slon;
@property(nonatomic) double dlat;
@property(nonatomic) double dlon;
@end
@implementation RNMapNavigation
RCT_EXPORT_MODULE(RNMapNavigationManager);
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_METHOD(mapNavigation:(id)data)
{
if(![data isKindOfClass:[NSDictionary class]]){
return;
}
NSDictionary *params = data;
if([params objectForKey:@"sname"] == nil){
return;
}
if([params objectForKey:@"dname"] == nil){
return;
}
if([params objectForKey:@"slat"] == nil){
return;
}
if([params objectForKey:@"slon"] == nil){
return;
}
if([params objectForKey:@"dlat"] == nil){
return;
}
if([params objectForKey:@"dlon"] == nil){
return;
}
_sname = params[@"sname"];
_dname = params[@"dname"];
_slat = [(NSNumber *) params[@"slat"] doubleValue];
_slon = [(NSNumber *) params[@"slon"] doubleValue];
_dlat = [(NSNumber *) params[@"dlat"] doubleValue];
_dlon = [(NSNumber *) params[@"dlon"] doubleValue];
[self navigationSelect];
}
- (void)navigationSelect {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"请选择导航软件"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"高德地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self navigationAMap];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"苹果地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self navigationApple];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
[[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController:alertController
animated:YES
completion:nil];
}
- (void)navigationApple {
CLLocationCoordinate2D locationCoordinate2D = CLLocationCoordinate2DMake(_dlat, _dlon);
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:locationCoordinate2D
addressDictionary:nil]];
toLocation.name = _dname;
CLLocationCoordinate2D currentCoordinate2D = CLLocationCoordinate2DMake(_slat,_slon);
MKMapItem *currentLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:currentCoordinate2D postalAddress:nil]];
currentLocation.name = _sname;
[MKMapItem openMapsWithItems:@[currentLocation, toLocation]
launchOptions:@{MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsShowsTrafficKey: [NSNumber numberWithBool:YES]}];
}
- (void)navigationAMap {
NSString *appName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"];
NSString *appScheme = [[RNAMConfig shareInstance] appScheme];
NSString *urlString = [NSString stringWithFormat:@"iosamap://path?sourceApplication=%@&sid=BGVIS1&slat=%f&slon=%f&sname=%@&did=BGVIS2&dlat=%f&dlon=%f&dname=%@&dev=0&t=0", appName,_slat,_slon,_sname,_dlat,_dlon,_dname];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url
options:@{}
completionHandler:nil];
} else {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil
message:@"请先安装高德APP"
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"确定"
style:UIAlertActionStyleDefault
handler:nil]];
[[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController:alertController
animated:YES
completion:nil];
return;
}
}
@end
//
// Created by Allen Chiang on 18/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AMapSearchKit/AMapSearchKit.h>
@interface AMapSearchObject (RNAMRequest)
@property(nonatomic, strong) NSString *requestId;
@end
//
// Created by Allen Chiang on 18/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <objc/runtime.h>
#import "AMapSearchObject+RNAMRequest.h"
@implementation AMapSearchObject (RNAMRequest)
- (void)setRequestId:(NSString *)requestId
{
objc_setAssociatedObject(self, @selector(requestId), requestId, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)requestId
{
return objc_getAssociatedObject(self, @selector(requestId));
}
@end
\ No newline at end of file
//
// RNAMDistrictSearchReultDO.h
// Pods
//
// Created by Wenbo Li on 2017/7/11.
//
//
#import <Foundation/Foundation.h>
#import <AMapSearchKit/AMapSearchKit.h>
@interface RNAMDistrictSearchReultDO : NSObject
@property(nonatomic, assign) double latitude;
@property(nonatomic, assign) double longitude;
@property(nonatomic, copy) NSString *adCode;
- (instancetype)initWithAMapDistrictSearchResponse:(AMapDistrict *)district;
- (NSDictionary *)dictionary;
@end
//
// RNAMDistrictSearchReultDO.m
// Pods
//
// Created by Wenbo Li on 2017/7/11.
//
//
#import "RNAMDistrictSearchReultDO.h"
@implementation RNAMDistrictSearchReultDO
- (instancetype)initWithAMapDistrictSearchResponse:(AMapDistrict *)district {
self = [super init];
if (self) {
id adcode = district.adcode;
id center = district.center;
if ([adcode isKindOfClass:[NSString class]]) {
self.adCode = adcode;
}
if ([center isKindOfClass:[AMapGeoPoint class]]) {
self.latitude = [(AMapGeoPoint *)center latitude];
self.longitude = [(AMapGeoPoint *)center longitude];
}
}
return self;
}
- (NSDictionary *)dictionary {
if (self.adCode) {
return @{
@"adCode": self.adCode?self.adCode:@"",
@"latitude": @(self.latitude),
@"longitude": @(self.longitude),
};
}
return @{};
}
@end
//
// Created by Allen Chiang on 17/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AMapSearchKit/AMapSearchKit.h>
#import <AMapLocationKit/AMapLocationKit.h>
@class CLLocation;
@interface RNAMLocationDO : NSObject
//// gps坐标信息
@property(nonatomic, assign) double latitude;
@property(nonatomic, assign) double longitude;
///格式化地址
@property(nonatomic, copy) NSString *formattedAddress;
///国家
@property(nonatomic, copy) NSString *country;
///省/直辖市
@property(nonatomic, copy) NSString *province;
///市
@property(nonatomic, copy) NSString *city;
///区
@property(nonatomic, copy) NSString *district;
///城市编码
@property(nonatomic, copy) NSString *citycode;
///区域编码
@property(nonatomic, copy) NSString *adcode;
///街道名称
@property(nonatomic, copy) NSString *street;
///门牌号
@property(nonatomic, copy) NSString *number;
///兴趣点名称
@property(nonatomic, copy) NSString *POIName;
///所属兴趣点名称
@property(nonatomic, copy) NSString *AOIName;
// poi列表
@property(nonatomic, copy) NSArray *pois;
@property(nonatomic, copy) NSArray *aois;
- (id)initWithCLLocation:(CLLocation *)location
withReGeocode:(AMapLocationReGeocode *)reGeocode;
- (id)initWithGeocode:(AMapGeocode *)mapGeocode;
- (id)initWithReGeocode:(AMapReGeocode *)mapReGeocode;
- (NSDictionary *)dictionary;
@end
//
// Created by Allen Chiang on 17/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <AMapLocationKit/AMapLocationKit.h>
#import <AMapSearchKit/AMapSearchKit.h>
#import "RNAMLocationDO.h"
#import "RNAMPOISearchResultDO.h"
@implementation RNAMLocationDO
- (instancetype)initWithCLLocation:(CLLocation *)location
withReGeocode:(AMapLocationReGeocode *)reGeocode {
self = [super init];
if (self) {
_latitude = location.coordinate.latitude;
_longitude = location.coordinate.longitude;
if (reGeocode) {
_formattedAddress = reGeocode.formattedAddress;
_country = reGeocode.country;
_province = reGeocode.province;
_city = reGeocode.city;
_district = reGeocode.district;
_citycode = reGeocode.citycode;
_adcode = reGeocode.adcode;
_street = reGeocode.street;
_number = reGeocode.number;
_POIName = reGeocode.POIName;
_AOIName = reGeocode.AOIName;
}
}
return self;
}
- (id)initWithGeocode:(AMapGeocode *)mapGeocode {
self = [super init];
if(self){
_formattedAddress = mapGeocode.formattedAddress;
_country = mapGeocode.township;
_province = mapGeocode.province;
_city = mapGeocode.city;
_district = mapGeocode.district;
_citycode = mapGeocode.citycode;
_adcode = mapGeocode.adcode;
_latitude = mapGeocode.location.latitude;
_longitude = mapGeocode.location.longitude;
}
return self;
}
- (id)initWithReGeocode:(AMapReGeocode *)mapReGeocode {
self = [super init];
if (self) {
_formattedAddress = mapReGeocode.formattedAddress;
AMapAddressComponent *addressComponent = mapReGeocode.addressComponent;
AMapStreetNumber *streetNumber = addressComponent.streetNumber;
_country = addressComponent.township;
_province = addressComponent.province;
_citycode = addressComponent.citycode;
_city = addressComponent.city;
_district = addressComponent.district;
_adcode = addressComponent.adcode;
_street = streetNumber.street;
_number = streetNumber.number;
_latitude = streetNumber.location.latitude;
_longitude = streetNumber.location.longitude;
if(mapReGeocode.pois){
NSMutableArray *pois = [[NSMutableArray alloc] init];
[mapReGeocode.pois enumerateObjectsUsingBlock:^(AMapPOI * _Nonnull aMapPOI, NSUInteger idx, BOOL * _Nonnull stop) {
if(aMapPOI.adcode){
aMapPOI.adcode = addressComponent.adcode;
}
RNAMPOI *poiDO = [[RNAMPOI alloc] initWithAMapPOI:aMapPOI];
[pois addObject:[poiDO dictionary]];
}];
_pois = pois;
}
if(mapReGeocode.aois){
NSMutableArray *aois = [[NSMutableArray alloc] init];
[mapReGeocode.aois enumerateObjectsUsingBlock:^(AMapAOI * _Nonnull aMapPOI, NSUInteger idx, BOOL * _Nonnull stop) {
[aois addObject: [aMapPOI name]];
}];
_aois = aois;
}
}
return self;
}
- (NSDictionary *)dictionary {
return @{
@"latitude": [NSString stringWithFormat:@"%f", _latitude],
@"longitude": [NSString stringWithFormat:@"%f", _longitude],
@"formattedAddress": _formattedAddress?:@"",
@"country": _country?:@"",
@"province": _province?:@"",
@"city": _city?:@"",
@"district": _district?:@"",
@"cityCode": _citycode?:@"",
@"adCode": _adcode?:@"",
@"street": _street?:@"",
@"number": _number?:@"",
@"POIName": _POIName?:@"",
@"AOIName": _AOIName?:@"",
@"pois": _pois?:@{},
@"aois": _aois?:@{}
};
}
@end
//
// Created by Allen Chiang on 18/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AMapSearchKit/AMapSearchKit.h>
@interface RNAMPOI : NSObject
- (instancetype)initWithAMapPOI:(AMapPOI *)aMapPOI;
- (NSDictionary *)dictionary;
@end
@interface RNAMPOISuggestion : NSObject
- (instancetype)initWithAMapSuggestion:(AMapSuggestion *)suggestion;
- (NSDictionary *)dictionary;
@end
@interface RNAMPOISearchResultDO : NSObject
@property(nonatomic, copy) NSArray *pois;
@property(nonatomic, assign) NSInteger count;
@property(nonatomic, copy) RNAMPOISuggestion *suggestions;
- (instancetype)initWithAMapPOISearchResponse:(AMapPOISearchResponse *)searchResponse;
- (NSDictionary *)dictionary;
@end
\ No newline at end of file
//
// Created by Allen Chiang on 18/01/2017.
// Copyright (c) 2017 Facebook. All rights reserved.
//
#import <AMapSearchKit/AMapSearchKit.h>
#import "RNAMPOISearchResultDO.h"
@implementation RNAMPOI {
AMapPOI *_aMapPOI;
}
- (instancetype)initWithAMapPOI:(AMapPOI *)aMapPOI {
self = [super init];
if (self) {
_aMapPOI = [aMapPOI copy];
}
return self;
}
- (NSDictionary *)dictionary {
if (_aMapPOI) {
return @{
@"uid": _aMapPOI.uid ?: @"",
@"name": _aMapPOI.name ?: @"",
@"type": _aMapPOI.type ?: @"",
@"address": _aMapPOI.address ?: @"",
@"adcode": _aMapPOI.adcode ?: @"",
@"latitude": _aMapPOI.location.latitude?[NSString stringWithFormat:@"%f",_aMapPOI.location.latitude]:@"",
@"longitude": _aMapPOI.location.longitude?[NSString stringWithFormat:@"%f",_aMapPOI.location.longitude]:@""
};
}
return @{};
}
@end
@implementation RNAMPOISuggestion {
AMapSuggestion *_suggestion;
}
- (instancetype)initWithAMapSuggestion:(AMapSuggestion *)suggestion {
self = [super init];
if (self) {
_suggestion = [suggestion copy];
}
return self;
}
- (NSDictionary *)dictionary {
if (_suggestion) {
return @{
@"keywords": _suggestion.keywords ?: @[]
};
}
return @{};
}
@end
@implementation RNAMPOISearchResultDO
- (instancetype)initWithAMapPOISearchResponse:(AMapPOISearchResponse *)searchResponse {
self = [super init];
if (self) {
_count = searchResponse.count;
NSMutableArray *pois = [[NSMutableArray alloc] init];
[searchResponse.pois enumerateObjectsUsingBlock:^(AMapPOI *aMapPOI, NSUInteger idx, BOOL *stop) {
[pois addObject:[[[RNAMPOI alloc] initWithAMapPOI:aMapPOI] dictionary]];
}];
_pois = pois;
_suggestions = [[RNAMPOISuggestion alloc] initWithAMapSuggestion:searchResponse.suggestion];
}
return self;
}
- (NSDictionary *)dictionary {
return @{
@"count": @(_count),
@"pois": _pois ?: @[],
@"suggestions": [_suggestions dictionary] ?: @{}
};
}
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment