项目作者: amap-demo

项目描述 :
高德定位SDK在React Native中的使用示例
高级语言: Objective-C
项目地址: git://github.com/amap-demo/amap-location-react-native.git
创建时间: 2018-08-13T12:19:27Z
项目社区:https://github.com/amap-demo/amap-location-react-native

开源协议:

下载


前述

  1. 高德官网申请Key.
  2. 阅读开发指南.Android
  3. 基于React Native 版本:0.56.0
  4. 本工程是基于React Native环境创建,并不是创建了一个library,如需要修改成library请参考官网

React-Native 环境搭建

参考官网介绍:https://facebook.github.io/react-native/docs/getting-started.html
中文地址:https://reactnative.cn/docs/getting-started/

  1. 本文只介绍MAC上的安装,Windows上的安装请参考官网介绍
  1. 安装 Node 和 Watchman

    1. //node需要8.3及以上版本,如果低于该版本请进行升级
    2. brew install node
    3. brew install watchman
  2. Yarn、React Native 的命令行工具(react-native-cli)
    1. npm install -g yarn react-native-cli
  3. 创建新项目
    1. //如果需要指定版本,可以在末尾加上--version指定版本
    2. react-native init amap-location-react-native

    配置AndroidManifest.xml

  4. 注册定位SDK需求的权限
  1. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
  2. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
  3. <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
  4. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
  5. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
  6. <uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
  7. <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
  8. <uses-permission android:name="android.permission.INTERNET"></uses-permission>
  9. <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
  10. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
  11. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses-permission>
  12. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
  1. 填写您的key

    注意此处的key是测试使用的key,在使用过程中请使用自己的key

  1. <meta-data
  2. android:name="com.amap.api.v2.apikey"
  3. android:value="78ed9fba3da4ec7ae3eeac7e9d8ae34e"/>
  1. 注册定位service
  1. <service android:name="com.amap.api.location.APSService"></service>

关键代码

编写模块

AMapLocationModule.java

重写getName()方法

  1. @Override
  2. public String getName() {
  3. return "AMapLocation";
  4. }

通过@ReactMethod暴露方法给js

  1. /**
  2. * 开始定位
  3. * @param locationParams 定位参数
  4. * <p>
  5. * 示例中只传了3个参数,实际开发中可以根据需求自行控制传入的参数
  6. * </p>
  7. */
  8. @ReactMethod
  9. public void startLocation(String locationParams){
  10. if(null == locationOption){
  11. locationOption = new AMapLocationClientOption();
  12. }
  13. if(null == eventEmitter){
  14. eventEmitter = getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
  15. }
  16. /**
  17. * 设置定位模式为高精度模式,实际开发中可以根据需要自行设置
  18. */
  19. locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
  20. if(null != locationParams){
  21. try {
  22. JSONObject json = new JSONObject(locationParams);
  23. /**
  24. * 是否单次定位
  25. */
  26. locationOption.setOnceLocation(json.optBoolean("onceLocation", false));
  27. /**
  28. * 是否需要逆地理信息
  29. */
  30. locationOption.setNeedAddress(json.optBoolean("needAddress", true));
  31. /**
  32. * 定位间隔,单位毫秒
  33. */
  34. locationOption.setInterval(json.optInt("interval", 2000));
  35. } catch (Throwable e){
  36. }
  37. }
  38. if(null == locationClient){
  39. locationClient = new AMapLocationClient(getReactApplicationContext());
  40. }
  41. locationClient.setLocationOption(locationOption);
  42. locationClient.setLocationListener(locationListener);
  43. locationClient.startLocation();
  44. }
  45. /**
  46. * 停止定位
  47. */
  48. @ReactMethod
  49. public void stopLocation() {
  50. if (null != locationClient) {
  51. locationClient.stopLocation();
  52. }
  53. }
  54. /**
  55. * 销毁
  56. */
  57. @ReactMethod
  58. public void destroyLocation() {
  59. if (null != locationClient) {
  60. locationClient.stopLocation();
  61. locationClient.unRegisterLocationListener(locationListener);
  62. locationClient.onDestroy();
  63. }
  64. locationClient = null;
  65. }
  66. /**
  67. * 定位监听
  68. */
  69. AMapLocationListener locationListener = new AMapLocationListener() {
  70. @Override
  71. public void onLocationChanged(AMapLocation location) {
  72. if (null != locationClient) {
  73. int errorCode = location.getErrorCode();
  74. WritableMap resultMap = Arguments.createMap();
  75. resultMap.putString("callbackTime", formatUTC(System.currentTimeMillis(), null));
  76. if (errorCode == AMapLocation.LOCATION_SUCCESS) {
  77. resultMap.putInt("code", 0);
  78. resultMap.putDouble("lat", location.getLatitude());
  79. resultMap.putDouble("lon", location.getLongitude());
  80. resultMap.putString("addr", location.getAddress());
  81. resultMap.putString("locTime", formatUTC(location.getTime(), null));
  82. } else {
  83. resultMap.putInt("code", location.getErrorCode());
  84. resultMap.putString("errorInfo", location.getErrorInfo());
  85. resultMap.putString("errorDetail", location.getLocationDetail());
  86. }
  87. if(null != eventEmitter){
  88. /**
  89. * 发送事件到JavaScript
  90. * 使用此种方式回调可以持续回调
  91. */
  92. eventEmitter.emit("locationChanged", resultMap);
  93. }
  94. }
  95. }
  96. };

注册模块

编写AMapLocationPackage类实现ReactPackage接口
  1. @Override
  2. public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
  3. List<NativeModule> modules = new ArrayList<NativeModule>();
  4. modules.add(new AMapLocationModule(reactContext));
  5. return modules;
  6. }
  7. @Override
  8. public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  9. return Collections.emptyList();
  10. }
注册package

在android/app/src/main/java/com/your-app-name/MainApplication.java中将AMapLocationPackage注册

  1. @Override
  2. protected List<ReactPackage> getPackages() {
  3. return Arrays.<ReactPackage>asList(
  4. new MainReactPackage(),
  5. new AMapLocationPackage()
  6. );
  7. }

Js中调用

  1. 为了调用方便在根目录新建一个js文件AMapLocation.js

    1. import {NativeModules} from 'react-native';
    2. module.exports = NativeModules.AMapLocation;
  2. App.js中引用AMapLocation

    1. import AMapLocation from './AMapLocation';
  3. 注册定位监听

  1. export default class App extends Component<Props> {
  2. state = {}
  3. //注册监听
  4. componentWillMount(){
  5. this.listener = DeviceEventEmitter.addListener('locationChanged', (result) => {
  6. console.log(result);
  7. this.setState(result);
  8. });
  9. }
  10. //移除监听
  11. componentWillUnMount(){
  12. this.listener.remove();
  13. AMapLocation.destroyLocation();
  14. }
  15. //....
  16. }
  1. Js调用Java接口
  1. //连续定位
  2. function startContinueLocation(){
  3. AMapLocation.startLocation("{'onceLocation':false, 'needAddress':true,'interval': 2000}");
  4. }
  5. //单次定位
  6. function startOnceLocation(){
  7. AMapLocation.startLocation("{'onceLocation':true, 'needAddress':true, 'interval': 2000}");
  8. }
  9. //停止定位
  10. function stopLocation(){
  11. AMapLocation.stopLocation();
  12. }

疑难杂症

Android 运行时出现“unable to load script from assets ‘index.android bundle’”错误的解决方法

  1. 先在工作目录创建:android/app/src/main 目录下创建一个 assets空文件夹
  2. 执行:react-native bundle —platform android —dev false —entry-file index.js —bundle-output
    android/app/src/main/assets/index.android.bundle —assets-dest android/app/src/main/res/
  3. 运行react-native run-android

容易遇到的坑

  1. 注册JS时间监听
    componentWillMount()和componentWillUnMount()需要写到“export default class App extends Component {…”内,否则各种错误。

运行

  1. //安装依赖包
  2. npm install
  3. //运行Android 示例
  4. react-native run-android
  5. //运行IOS示例
  6. react-native run-ios