基于 react-native-amap-geolocation 的 OpenHarmony 适配版,高德地图定位服务
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 20 天前 | ||
| 20 天前 | ||
| 1 个月前 | ||
| 9 个月前 | ||
| 20 天前 | ||
| 4 个月前 | ||
| 2 个月前 | ||
| 10 个月前 | ||
| 20 天前 | ||
| 20 天前 | ||
| 20 天前 | ||
| 3 年前 |
模板版本:v0.4.2
react-native-amap-geolocation
本项目基于 react-native-amap-geolocation 开发。
该第三方库的仓库已迁移至 Gitcode,并支持直接从 npm 下载,新包名为:@react-native-ohos/react-native-amap-geolocation。各版本归属关系如下:
| 三方库名称 | 三方库版本(npm 地址) | 发布信息 | 支持 RN 版本 | Autolink | 编译 API 版本 | 社区基线版本 | 源码地址 |
|---|---|---|---|---|---|---|---|
| @react-native-ohos/react-native-amap-geolocation | ~ 1.4.0 | GitCode Releases | 0.82./0.84. | 是 | API12+ | 1.2.3 | master |
| @react-native-ohos/react-native-amap-geolocation | ~ 1.3.0 | GitCode Releases | 0.77.* | 否 | API12+ | 1.2.3 | br_rnoh0.77 |
| @react-native-ohos/react-native-amap-geolocation | ~ 1.2.4 | GitCode Releases | 0.72.* | 是 | API12+ | 1.2.3 | br_rnoh0.72 |
| @react-native-oh-tpl/react-native-amap-geolocation | <= 1.2.3-0.0.5@deprecated | GitHub Releases(deprecated) | 0.72.* | 否 | API12+ | 1.2.3 | sig |
简介
一款基于高德 SDK 实现定位的 React Native 库。
1. 安装与使用
进入工程目录,并执行以下命令:
npm
npm install @react-native-ohos/react-native-amap-geolocation
yarn
yarn add @react-native-ohos/react-native-amap-geolocation
以下代码演示了该库的基本使用场景:
使用时,import 的库名保持不变。
import * as React from "react";
import {
Button,
Platform,
ScrollView,
StyleSheet,
Text,
View,
} from "react-native";
import {
Geolocation, setInterval, addLocationListener,
setGeoLanguage, setDistanceFilter, init, setNeedAddress, start,
stop, setLocationTimeout, setOnceLocation, GeoLanguage
} from "react-native-amap-geolocation";
const style = StyleSheet.create({
body: {
padding: 16,
paddingTop: Platform.OS === "ios" ? 48 : 16,
},
button: {
flexDirection: "column",
marginRight: 8,
marginBottom: 5,
marginTop: 5
},
result: {
fontFamily: Platform.OS === "ios" ? "menlo" : "monospace",
},
});
class AmapGeoLocationDemo extends React.Component {
state = {
location: null, needAddressText: "setNeedAddress(false)",
language: "setLanguage(chinese)", interval: "setInterval(默认2000)", onceText: "setOnceLocation(false) 设置单次定位",
startText: "start 持续定位", timeoutText: "setLocationTimeout 设置请求定位超时时间",distanceText:"setDistanceFilter(0) 设置定位的最小更新距离"
};
watchId = 0;
needAddress = true;
currLanguage = GeoLanguage.ZH;
currInterval = false;
onceLocationJudge = false;
timeout5000 = false;
distanseJudge = true;
init = () => {
console.log("rn AMapLocationManagerImpl init");
init("5f7389b845cbd89b1c32e24f526728f4").then(() => {
console.log("rn AMapLocationManagerImpl init success");
});
};
addLocationListener = () => {
console.log("rn AMapLocationManagerImpl addLocationListener");
addLocationListener((locationData) => {
console.log("rn AMapLocationManagerImpl callback success:" + JSON.stringify(locationData, null, 2));
let location = locationData;
this.setState({ location: location });
});
};
setDistanceFilter = () => {
console.log("rn AMapLocationManagerImpl setDistanceFilter");
this.distanseJudge = !this.distanseJudge;
if (this.distanseJudge) {
setDistanceFilter(0);
this.setState({ distanceText: "setDistanceFilter(0) 设置定位的最小更新距离" });
} else {
setDistanceFilter(1);
this.setState({ distanceText: "setDistanceFilter(1) 设置定位的最小更新距离" });
}
};
setLocationTimeout = () => {
console.log("rn AMapLocationManagerImpl setLocationTimeout");
this.timeout5000 = !this.timeout5000;
if (this.timeout5000) {
setLocationTimeout(5000);
this.setState({ timeoutText: "setLocationTimeout(5000) 设置请求定位超时时间" });
} else {
setLocationTimeout(10000);
this.setState({ timeoutText: "setLocationTimeout(10000) 设置请求定位超时时间" });
}
};
start = () => {
console.log("rn AMapLocationManagerImpl start");
start();
};
stop = () => {
console.log("rn AMapLocationManagerImpl stop");
stop();
}
onceLocation = () => {
this.onceLocationJudge = !this.onceLocationJudge;
if (this.onceLocationJudge) {
setOnceLocation(true);
this.setState({ onceText: "setOnceLocation(true) 设置单次定位", startText: "start 单次定位" });
} else {
setOnceLocation(false);
this.setState({ onceText: "setOnceLocation(false) 设置单次定位", startText: "start 持续定位" });
}
console.log("rn AMapLocationManagerImpl current onceLocation:" + this.onceLocationJudge);
};
setInterval = () => {
if (this.currInterval) {
setInterval(2000);
this.setState({ interval: "setInterval:2000" });
} else {
setInterval(10000);
this.setState({ interval: "setInterval:10000" });
}
this.currInterval = !this.currInterval;
}
setNeedAddress = () => {
this.needAddress = !this.needAddress;
console.log("rn AMapLocationManagerImpl setNeedAddress:" + this.needAddress);
if (this.needAddress) {
setNeedAddress(true);
this.setState({ needAddressText: "setNeedAddress(true)" });
} else {
setNeedAddress(false);
this.setState({ needAddressText: "setNeedAddress(false)" });
}
}
setLanguage = () => {
// default = 0,chinese = 1, engilish=2;
console.log("rn AMapLocationManagerImpl setLanguage");
if (this.currLanguage == GeoLanguage.ZH) {
this.currLanguage = GeoLanguage.EN;
setGeoLanguage(GeoLanguage.EN);
this.setState({ language: "setLanguage(engilish)" });
} else {
this.currLanguage = GeoLanguage.ZH;
setGeoLanguage(GeoLanguage.ZH);
this.setState({ language: "setLanguage(chinese)" });
}
}
updateLocationState(location: any) {
console.log("rn AMapLocationManagerImpl updateLocationState");
if (location) {
this.setState({ location: location });
console.log(location);
}
}
getCurrentPosition = () => {
Geolocation.getCurrentPosition(
(position) => this.updateLocationState(position),
(error) => this.updateLocationState(error)
);
};
watchPosition = () => {
if (!this.watchId) {
this.watchId = Geolocation.watchPosition(
(position) => this.updateLocationState(position),
(error) => this.updateLocationState(error)
);
console.log("rn AMapLocationManagerImpl watchPosition watchId:" + this.watchId);
}
};
clearWatch = () => {
if (this.watchId) {
console.log("rn AMapLocationManagerImpl clearWatch watchId:" + this.watchId);
Geolocation.clearWatch(this.watchId);
this.watchId = 0;
}
stop();
this.setState({ location: null });
};
render() {
const location = this.state.location;
const needAddressText = this.state.needAddressText;
const language = this.state.language;
const currInterval = this.state.interval;
const onceText = this.state.onceText;
const startText = this.state.startText;
const timeoutText = this.state.timeoutText;
const distanceText = this.state.distanceText;
return (
<ScrollView contentContainerStyle={style.body}>
<View style={style.button}>
<Button onPress={this.init} title="init 初始化接口" />
</View>
<View style={style.button}>
<Button onPress={this.addLocationListener} title="addLocationListener 设置监听回调,原生接口不设置监听回调,text不会显示数据" />
</View>
<View style={style.button}>
<Button onPress={this.setDistanceFilter} title={distanceText} />
</View>
<View style={style.button}>
<Button onPress={this.setLocationTimeout} title={timeoutText} />
</View>
<View style={style.button}>
<Button onPress={this.onceLocation} title={onceText} />
</View>
<View style={style.button}>
<Button onPress={this.start} title={startText} />
</View>
<View style={style.button}>
<Button onPress={this.stop} title="stop 结束持续定位" />
</View>
<View style={style.button}>
<Button onPress={this.setInterval} title={currInterval} />
</View>
<View style={style.button}>
<Button onPress={this.setNeedAddress} title={needAddressText} />
</View>
<View style={style.button}>
<Button onPress={this.setLanguage} title={language} />
</View>
<View style={style.button}>
<Button onPress={this.getCurrentPosition} title="Geolocation.getCurrentPosition 获取当前位置,相当于单次请求" />
</View>
<View style={style.button}>
<Button onPress={this.watchPosition} title="Geolocation.watchPosition 开启持续定位" />
</View>
<View style={style.button}>
<Button onPress={this.clearWatch} title="Geolocation.clearWatch 结束持续定位" />
</View>
<Text style={style.result}>{`${JSON.stringify(location, null, 2)}`}</Text>
</ScrollView>
);
}
}
export default AmapGeoLocationDemo;
2. 依赖链接
| 是否支持 Autolink | RN 框架版本 | |
|---|---|---|
| ~ 1.4.0 | 是 | 0.82./0.84. |
| ~ 1.3.0 | 否 | 0.77.* |
| ~ 1.2.4 | 是 | 0.72.* |
| <= 1.2.3-0.0.5@deprecated | 否 | 0.72.* |
使用 Autolink 的工程,请按照该文档进行配置。Autolink 框架指导文档:https://gitcode.com/CPF-RN/ohos_react_native/blob/master/docs/zh-cn/Autolinking.md
如果您使用的版本支持 Autolink,并且工程已接入 Autolink,则可跳过 ManualLink 配置。
本步骤用于手动配置原生依赖项。
首先,请使用 DevEco Studio 打开项目中的 HarmonyOS 工程 harmony。
2.1. 使用 Overrides 覆盖 RN SDK
为确保工程依赖同一版本的 RN SDK,需要在工程根目录的 oh-package.json5 中添加 overrides 字段,指定工程需要使用的 RN SDK 版本。可替换的版本既可以是具体版本号,也可以是模糊版本号,还可以是本地已存在的 HAR 包或源码目录。
关于该字段的作用,请参阅官方说明:
{
"overrides": {
"@rnoh/react-native-openharmony" : "./react_native_openharmony.har" // Path to local har package
// "@rnoh/react-native-openharmony" : "./react_native_openharmony" // Point to source code path
}
}
2.2. 引入原生端代码
目前有两种方法:
- 通过 har 包引入(在 IDE 完善相关功能后该方法会被遗弃,目前首选此方法);
- 直接链接源码。
方法一:通过 har 包引入(推荐)
har 包位于三方库安装路径的 `harmony` 文件夹下。
打开 entry/oh-package.json5,添加以下依赖
"dependencies": {
"@react-native-ohos/react-native-amap-geolocation": "file:../../node_modules/@react-native-ohos/react-native-amap-geolocation/harmony/amap_geolocation.har"
}
点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install
方式二:直接链接源码
如需使用直接链接源码,请参考[直接链接源码说明](https://gitcode.com/CPF-RN/usage-docs/blob/master/zh-cn/link-source-code.md)
2.3. 配置 CMakeLists 并引入 AMapGeolocationPackage
如果使用的是 <= 1.2.3-0.0.5 版本,请跳过本章。
打开 entry/src/main/cpp/CMakeLists.txt,添加:
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
# RNOH_BEGIN: manual_package_linking_1
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-amap-geolocation/src/main/cpp" ./amap_geolocation)
# RNOH_END: manual_package_linking_1
# RNOH_BEGIN: manual_package_linking_2
+ target_link_libraries(rnoh_app PUBLIC rnoh_amap_geolocation)
# RNOH_END: manual_package_linking_2
打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "AMapGeolocationPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
+ std::make_shared<AMapGeolocationPackage>(ctx),
};
}
2.4. 在 ArkTS 侧引入 AMapGeolocationPackage
打开 entry/src/main/ets/RNPackagesFactory.ts,添加:
...
+ import {AMapGeolocationPackage} from '@react-native-ohos/react-native-amap-geolocation/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new SamplePackage(ctx),
+ new AMapGeolocationPackage(ctx)
];
}
2.5. 运行
点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install
然后编译并运行即可。
3. 约束与限制
3.1. 兼容性
本文档内容已在以下环境中验证通过:
- RNOH: 0.72.96; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
- RNOH: 0.77.18; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
- RNOH:0.82.1; SDK: HarmonyOS 6.0.1 Release SDK; IDE: DevEco Studio 6.0.1 Release; ROM:6.0.0.120 SP7;
- RNOH:0.84.1; SDK: HarmonyOS 6.0.2 Release SDK; IDE: 6.0.2 Release; ROM:7.0.0.100 SP9;
3.2. 权限要求
在 entry 目录下的 module.json5 中添加权限
打开 entry/src/main/module.json5,添加:
...
"requestPermissions": [
{
"name": "ohos.permission.LOCATION",
"reason": "$string:Access_Location",
"usedScene": {
"when":"inuse"
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "$string:Access_AppRoximatelyLocation",
"usedScene": {
"when":"inuse"
}
},
{
"name": "ohos.permission.INTERNET",
}
]
在 entry 目录中配置位置权限的原因
打开 entry/src/main/resources/base/element/string.json,添加:
...
{
"string": [
{
"name": "Access_Location",
"value": "access Location"
},
{
"name": "Access_AppRoximatelyLocation",
"value": "access AppRoximatelyLocation"
}
]
}
4. 属性
“平台”列表示该属性在原第三方库中支持的平台。
“HarmonyOS 支持情况”列中,“支持”表示 HarmonyOS 平台支持该属性;“不支持”表示不支持;“部分支持”表示部分支持。跨平台使用方法一致,效果与 iOS 或 Android 对齐。
| 名称 | 描述 | 类型 | 是否必填 | 平台 | HarmonyOS 支持情况 |
|---|---|---|---|---|---|
| init | 初始化 SDK(参数为字符串 key) | Promise | 是 | iOS/Android | 支持 |
| addLocationListener | 添加定位监听函数 | EmitterSubscription | 是 | iOS/Android | 支持 |
| isStarted | 获取当前是否正在定位的状态(受平台限制,单次定位模式下返回 false) | boolean | 否 | Android | 支持 |
| setAllowsBackgroundLocationUpdates | 设置是否允许后台定位 | void | 否 | iOS | 不支持 |
| setDesiredAccuracy | 设置期望的定位精度(米) | void | 否 | iOS | 不支持 |
| setDistanceFilter | 设置定位的最小更新距离(米) | void | 否 | iOS | 支持 |
| setGeoLanguage | 设置逆地理信息的语言,当前支持中文和英文 | void | 否 | iOS/Android | 支持 |
| setGpsFirst | 设置首次定位时是否等待卫星定位结果 | void | 否 | Android | 不支持 |
| setGpsFirstTimeout | 设置优先返回卫星定位信息时等待卫星定位结果的超时时间(毫秒) | void | 否 | Android | 不支持 |
| setHttpTimeout | 设置联网超时时间(毫秒) | void | 否 | Android | 不支持 |
| setInterval | 设置发起定位请求的时间间隔(毫秒),默认 2000,最小值为 1000 | void | 否 | Android | 支持 |
| setLocatingWithReGeocode | 设置连续定位时是否返回逆地理编码信息 | void | 否 | iOS | 不支持 |
| setLocationCacheEnable | 设置是否启用缓存策略 | void | 否 | Android | 支持 |
| setLocationMode | 设置定位模式(参数为字符串枚举值) | void | 否 | Android | 支持 |
| setLocationPurpose | 设置定位场景 | void | 否 | Android | 不支持 |
| setLocationTimeout | 指定单次定位超时时间(秒) | void | 是 | iOS | 支持 |
| setMockEnable | 设置是否允许模拟位置 | void | 否 | Android | 不支持 |
| setNeedAddress | 设置是否返回地址信息,默认返回地址信息 | void | 是 | Android | 支持 |
| setOnceLocation | 设置是否单次定位 | void | 否 | Android | 支持 |
| setOnceLocationLatest | 设置定位时是否等待 WiFi 列表刷新 | void | 否 | Android | 不支持 |
| setOpenAlwaysScanWifi | 设置是否开启 WiFi 始终扫描 | void | 否 | Android | 不支持 |
| setPausesLocationUpdatesAutomatically | 指定定位是否会被系统自动暂停 | void | 否 | iOS | 不支持 |
| setReGeocodeTimeout | 指定单次定位逆地理编码超时时间(秒),最小值为 2 秒。注意:需在单次定位请求前设置。 | void | 否 | iOS | 不支持 |
| setSensorEnable | 设置是否使用设备传感器 | void | 否 | Android | 不支持 |
| setWifiScan | 设置是否允许调用 WiFi 刷新 | void | 否 | Android | 不支持 |
| start | 开始持续定位 | void | 否 | iOS/Android | 支持 |
| stop | 停止持续定位 | void | 否 | iOS/Android | 支持 |
| GeoLanguage | 逆地理信息语言枚举常量:ZH = 中文(1),EN = 英文(2) | GeoLanguage.ZH/GeoLanguage.EN | 否 | iOS/Android | 支持 |
| Geolocation.getCurrentPosition | 获取当前位置信息 | void | 否 | iOS/Android | 支持 |
| Geolocation.watchPosition | 注册监听器以进行持续定位 | number | 否 | iOS/Android | 支持 |
| Geolocation.clearWatch | 移除位置监听 | void | 否 | iOS/Android | 支持 |
setLocationMode 定位模式枚举值
setLocationMode(mode) 的 mode 参数支持以下三个枚举值,对应不同的定位优先级:
| 枚举值 | 含义 | 鸿蒙映射(LocationRequestPriority) |
|---|---|---|
LocationMode.Battery_Saving |
低功耗模式,仅使用网络定位(依赖基站、WLAN、蓝牙) | LOW_POWER |
LocationMode.Device_Sensors |
仅设备模式,以 GNSS 卫星定位为主,精度优先 | ACCURACY |
LocationMode.Hight_Accuracy |
高精度模式,同时使用 GNSS 定位和网络定位,优先返回首次定位结果(默认值) | FIRST_FIX |
修改定位模式后,需重新调用 `start()` 才能生效。
5. 遗留问题
6. 目录结构
/rntpc_react-native-amap-geolocation # 项目根目录
├── harmony # 鸿蒙适配代码
│ └─ amap_geolocation.har # har包
│ └─ amap_geolocation # 鸿蒙适配核心代码
│ └─ Index.ets # 鸿蒙适配代码入口
│ └─ src/main/ets
│ └─ AMapGeolocationModule # TurboModule接口
├── src # RN代码
│ └─ index.js # 入口文件
│ └─ NativeRNAMapGeolocation.ts 桥接TurboModule
├── README_en.md # 英文安装使用方法
├── README.md # 中文安装使用方法
7. 贡献代码
使用过程中如发现任何问题,都可以提交 Issue,当然,也非常欢迎提交 PR 。
8. 开源协议
本项目基于 The MIT License (MIT) ,请自由地享受并参与开源。