鸿蒙App位置服务获取(GPS定位当前城市)详解
【摘要】 引言位置服务是现代移动应用的核心功能之一,从导航应用到本地生活服务,都离不开精准的定位能力。鸿蒙操作系统(HarmonyOS)提供了强大的位置服务框架,支持GPS、北斗等多种定位方式,并能通过逆地理编码获取城市信息。本文将深入探讨鸿蒙App中获取位置信息并解析当前城市的完整实现方案,帮助开发者快速集成位置服务功能。技术背景位置服务的重要性用户体验:提供基于位置的服务增强用户体验商业价值:本地...
引言
技术背景
位置服务的重要性
-
用户体验:提供基于位置的服务增强用户体验 -
商业价值:本地化推荐提升转化率 -
安全合规:遵循位置数据隐私保护法规 -
系统整合:与地图、天气等服务无缝集成
鸿蒙位置服务架构
-
应用层:调用位置API实现业务功能 -
框架层:提供LocationManager、GeoConvert等核心类 -
服务层:Location Service管理位置提供者 -
硬件层:GPS/北斗/WiFi/基站等定位源
权限分类
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
应用使用场景
-
社交应用:显示附近好友或活动 -
电商应用:定位附近商店和配送范围 -
出行应用:实时导航和路线规划 -
旅游应用:景点推荐和导览服务 -
天气应用:自动获取当地天气预报 -
新闻应用:推送本地相关新闻 -
广告系统:基于位置的精准投放
不同场景下详细代码实现
场景1:基础位置权限申请
// LocationPermissionHelper.java
package com.example.locationdemo;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.app.Context;
import ohos.bundle.IBundleManager;
import ohos.security.SystemPermission;
import java.util.ArrayList;
import java.util.List;
public class LocationPermissionHelper {
private static final int PERMISSION_REQUEST_CODE = 1001;
private Ability ability;
private PermissionCallback callback;
public interface PermissionCallback {
void onPermissionGranted();
void onPermissionDenied(List<String> deniedPermissions);
}
public LocationPermissionHelper(Ability ability) {
this.ability = ability;
}
public void requestLocationPermissions(PermissionCallback callback) {
this.callback = callback;
List<String> permissionsToRequest = new ArrayList<>();
// 检查并收集需要的权限
if (!ability.verifySelfPermission(SystemPermission.LOCATION)) {
permissionsToRequest.add(SystemPermission.LOCATION);
}
if (!ability.verifySelfPermission(SystemPermission.APPROXIMATELY_LOCATION)) {
permissionsToRequest.add(SystemPermission.APPROXIMATELY_LOCATION);
}
if (permissionsToRequest.isEmpty()) {
// 已有所有权限
callback.onPermissionGranted();
} else {
// 请求缺失的权限
ability.requestPermissionsFromUser(
permissionsToRequest.toArray(new String[0]),
PERMISSION_REQUEST_CODE
);
}
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode != PERMISSION_REQUEST_CODE) return;
List<String> deniedPermissions = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] != IBundleManager.PERMISSION_GRANTED) {
deniedPermissions.add(permissions[i]);
}
}
if (deniedPermissions.isEmpty()) {
callback.onPermissionGranted();
} else {
callback.onPermissionDenied(deniedPermissions);
}
}
}
场景2:获取当前位置坐标
// LocationService.java
package com.example.locationdemo;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.location.Location;
import ohos.location.LocationCallback;
import ohos.location.LocationRequest;
import ohos.location.Locator;
import ohos.location.LocatorRange;
import ohos.location.provider.LocationProvider;
import ohos.rpc.RemoteException;
import java.util.ArrayList;
import java.util.List;
public class LocationService {
private static final String TAG = "LocationService";
private Locator locator;
private LocationCallback locationCallback;
private Context context;
private LocationResultCallback resultCallback;
public interface LocationResultCallback {
void onLocationReceived(double latitude, double longitude);
void onLocationFailed(int errorCode);
}
public LocationService(Context context) {
this.context = context;
initLocator();
}
private void initLocator() {
// 创建定位器实例
locator = new Locator(context);
// 配置定位参数
LocatorRange range = new LocatorRange();
range.setAccuracy(LocatorRange.COARSE); // 精度设置
range.setPowerRequirement(LocatorRange.POWER_LOW); // 功耗设置
range.setAltitudeRequired(false); // 不需要高度
range.setSpeedRequired(false); // 不需要速度
range.setCostAllowed(true); // 允许产生费用
// 设置定位模式
locator.setLocatorRange(range);
}
public void requestSingleLocation(LocationResultCallback callback) {
this.resultCallback = callback;
try {
// 单次定位请求
LocationRequest request = new LocationRequest();
request.setInterval(0); // 立即返回一次位置
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// 注册位置回调
locationCallback = new LocationCallback() {
@Override
public void onLocationReport(Location location) {
if (location != null) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
resultCallback.onLocationReceived(latitude, longitude);
} else {
resultCallback.onLocationFailed(-1);
}
}
@Override
public void onLocationStatusChanged(int status) {
if (status != Locator.STATUS_AVAILABLE) {
resultCallback.onLocationFailed(status);
}
}
};
locator.requestLocationUpdates(request, locationCallback);
// 设置超时处理
new Handler().postDelayed(() -> {
if (resultCallback != null) {
resultCallback.onLocationFailed(-2); // 超时错误码
stopLocationUpdates();
}
}, 30000); // 30秒超时
} catch (SecurityException e) {
resultCallback.onLocationFailed(-3); // 权限错误
}
}
public void stopLocationUpdates() {
if (locator != null && locationCallback != null) {
locator.releaseLocationUpdates(locationCallback);
locationCallback = null;
}
}
// 内部Handler类
private static class Handler extends EventHandler {
public Handler() {
super(EventRunner.current());
}
@Override
protected void processEvent(InnerEvent event) {
// 处理事件
}
}
}
场景3:逆地理编码获取城市信息
// GeocodeService.java
package com.example.locationdemo;
import ohos.app.Context;
import ohos.data.distributed.common.KvManager;
import ohos.data.distributed.common.KvManagerConfig;
import ohos.data.distributed.common.KvStoreType;
import ohos.geo.GeoConvert;
import ohos.geo.LocationInfo;
import ohos.geo.ReverseGeoCodeRequest;
import ohos.geo.ReverseGeoCodeResult;
import ohos.rpc.RemoteException;
import java.util.List;
public class GeocodeService {
private static final String TAG = "GeocodeService";
private GeoConvert geoConvert;
private Context context;
public GeocodeService(Context context) {
this.context = context;
initGeoConverter();
}
private void initGeoConverter() {
try {
// 初始化地理编码器
geoConvert = GeoConvert.getInstance(context);
} catch (RemoteException e) {
// 处理异常
}
}
public void getCityFromCoordinates(double latitude, double longitude, CityResultCallback callback) {
if (geoConvert == null) {
callback.onFailure(-1); // 服务不可用
return;
}
try {
// 创建逆地理编码请求
ReverseGeoCodeRequest request = new ReverseGeoCodeRequest();
request.setLocation(new LocationInfo(latitude, longitude));
request.setLanguage("zh_CN"); // 中文结果
request.setMaxItems(1); // 只返回一个结果
// 执行逆地理编码
ReverseGeoCodeResult result = geoConvert.getReverseGeoCode(request);
if (result != null && result.getLocations() != null && !result.getLocations().isEmpty()) {
// 提取城市信息
ReverseGeoCodeResult.Location location = result.getLocations().get(0);
String city = extractCityName(location);
callback.onSuccess(city);
} else {
callback.onFailure(-2); // 无结果
}
} catch (RemoteException e) {
callback.onFailure(-3); // 服务异常
}
}
private String extractCityName(ReverseGeoCodeResult.Location location) {
// 从不同级别的行政区划中提取城市名称
if (location.getCity() != null && !location.getCity().isEmpty()) {
return location.getCity();
} else if (location.getTown() != null && !location.getTown().isEmpty()) {
return location.getTown();
} else if (location.getDistrict() != null && !location.getDistrict().isEmpty()) {
return location.getDistrict();
} else if (location.getProvince() != null && !location.getProvince().isEmpty()) {
return location.getProvince();
}
return "未知位置";
}
public interface CityResultCallback {
void onSuccess(String cityName);
void onFailure(int errorCode);
}
}
原理解释
-
权限申请: -
应用声明位置权限 -
运行时动态请求用户授权 -
处理权限拒绝情况
-
-
位置获取: -
初始化定位器(Locator) -
配置定位参数(精度、功耗等) -
发起单次定位请求 -
接收位置回调(经纬度坐标)
-
-
逆地理编码: -
使用GeoConvert服务 -
提交经纬度坐标 -
获取包含地址信息的结构化数据 -
从结果中提取城市名称
-
-
结果处理: -
解析城市信息 -
处理异常情况(无结果、服务错误) -
返回最终城市名称
-
核心特性
-
多源定位融合:GPS+北斗+WiFi+基站混合定位 -
高精度模式:支持米级精确定位 -
低功耗模式:优化电池消耗 -
室内定位:结合WiFi和蓝牙信标 -
逆地理编码:坐标转地址服务 -
位置监听:持续位置更新能力 -
地理围栏:进出区域提醒
原理流程图及解释
graph TD
A[应用启动] --> B[检查位置权限]
B --> C{权限已授予?}
C -- 是 --> D[初始化定位服务]
C -- 否 --> E[申请位置权限]
E --> F{用户同意?}
F -- 是 --> D
F -- 否 --> G[显示权限拒绝提示]
D --> H[配置定位参数]
H --> I[发起单次定位请求]
I --> J{定位成功?}
J -- 是 --> K[获取经纬度坐标]
J -- 否 --> L[处理定位失败]
K --> M[初始化地理编码服务]
M --> N[提交逆地理编码请求]
N --> O{编码成功?}
O -- 是 --> P[解析城市名称]
O -- 否 --> Q[处理编码失败]
P --> R[显示当前城市]
Q --> R
L --> R
R --> S[结束]
-
应用启动后检查位置权限 -
有权限则初始化定位服务,否则申请权限 -
用户同意后继续,拒绝则提示 -
配置定位参数(精度、功耗等) -
发起单次定位请求 -
定位成功获取经纬度坐标 -
初始化地理编码服务 -
提交逆地理编码请求 -
解析返回的城市名称 -
显示当前城市信息 -
处理各环节可能出现的失败情况
环境准备
开发环境要求
-
操作系统:Windows 10/macOS/Linux -
开发工具:DevEco Studio 3.0+ -
SDK版本:API Version 7+ -
设备要求:HarmonyOS 2.0+真机或模拟器(支持定位)
安装步骤
-
下载安装DevEco Studio https://developer.harmonyos.com/cn/develop/deveco-studio -
配置开发环境 # 设置环境变量 export HARMONY_HOME=/path/to/harmonyos/sdk export PATH=$PATH:$HARMONY_HOME/tools -
创建新项目 # 使用命令行工具创建项目 hpm init -p org.example.locationdemo -
添加权限配置 // config.json { "module": { "reqPermissions": [ { "name": "ohos.permission.LOCATION", "reason": "$string:location_permission_reason" }, { "name": "ohos.permission.APPROXIMATELY_LOCATION", "reason": "$string:approx_location_permission_reason" } ] } } -
添加字符串资源 // resources/base/element/string.json { "string": [ { "name": "location_permission_reason", "value": "需要位置权限以获取您的位置" }, { "name": "approx_location_permission_reason", "value": "需要大致位置权限以定位您所在城市" } ] }
实际详细应用代码示例实现
// MainAbilitySlice.java
package com.example.locationdemo;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Text;
import ohos.agp.components.componentproviders.MainFormAbilityProvider;
import ohos.agp.components.layout.DirectionalLayout;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.location.Location;
import ohos.location.LocationCallback;
import ohos.location.LocationRequest;
import ohos.location.Locator;
import ohos.location.LocatorRange;
import java.util.concurrent.atomic.AtomicBoolean;
public class MainAbilitySlice extends AbilitySlice {
private Text cityText;
private Button getLocationButton;
private LocationPermissionHelper permissionHelper;
private LocationService locationService;
private GeocodeService geocodeService;
private Context context;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
context = getContext();
initUI();
initServices();
}
private void initUI() {
DirectionalLayout layout = new DirectionalLayout(this);
layout.setOrientation(Component.VERTICAL);
layout.setPadding(32, 32, 32, 32);
// 城市显示文本
cityText = new Text(this);
cityText.setText("点击下方按钮获取当前城市");
cityText.setTextSize(32);
cityText.setLayoutConfig(DirectionalLayout.LayoutConfig.MATCH_CONTENT,
DirectionalLayout.LayoutConfig.MATCH_CONTENT);
layout.addComponent(cityText);
// 获取位置按钮
getLocationButton = new Button(this);
getLocationButton.setText("获取当前城市");
getLocationButton.setTextSize(24);
getLocationButton.setLayoutConfig(DirectionalLayout.LayoutConfig.MATCH_CONTENT,
DirectionalLayout.LayoutConfig.MATCH_CONTENT);
getLocationButton.setMargins(0, 40, 0, 0);
getLocationButton.setClickedListener(component -> getCityFromLocation());
layout.addComponent(getLocationButton);
super.setUIContent(layout);
}
private void initServices() {
permissionHelper = new LocationPermissionHelper(this);
locationService = new LocationService(context);
geocodeService = new GeocodeService(context);
}
private void getCityFromLocation() {
// 检查权限
permissionHelper.requestLocationPermissions(new LocationPermissionHelper.PermissionCallback() {
@Override
public void onPermissionGranted() {
getLocationButton.setEnabled(false);
cityText.setText("定位中...");
// 获取位置
locationService.requestSingleLocation(new LocationService.LocationResultCallback() {
@Override
public void onLocationReceived(double latitude, double longitude) {
// 获取城市信息
geocodeService.getCityFromCoordinates(latitude, longitude,
new GeocodeService.CityResultCallback() {
@Override
public void onSuccess(String cityName) {
getUITaskDispatcher().asyncDispatch(() -> {
cityText.setText("当前城市: " + cityName);
getLocationButton.setEnabled(true);
});
}
@Override
public void onFailure(int errorCode) {
getUITaskDispatcher().asyncDispatch(() -> {
cityText.setText("获取城市失败,错误码: " + errorCode);
getLocationButton.setEnabled(true);
});
}
});
}
@Override
public void onLocationFailed(int errorCode) {
getUITaskDispatcher().asyncDispatch(() -> {
cityText.setText("定位失败,错误码: " + errorCode);
getLocationButton.setEnabled(true);
});
}
});
}
@Override
public void onPermissionDenied(List<String> deniedPermissions) {
getUITaskDispatcher().asyncDispatch(() -> {
cityText.setText("需要位置权限才能获取城市");
showPermissionExplanation();
});
}
});
}
private void showPermissionExplanation() {
new ToastDialog(this)
.setText("请前往设置开启位置权限")
.setAlignment(LayoutAlignment.CENTER)
.show();
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onInactive() {
super.onInactive();
// 停止位置更新
if (locationService != null) {
locationService.stopLocationUpdates();
}
}
}
运行结果
-
显示"获取当前城市"按钮和城市提示文本 -
点击按钮请求位置权限 -
权限授予后获取当前位置坐标 -
通过逆地理编码获取城市名称 -
在界面上显示当前城市
当前城市: 北京市海淀区
定位失败,错误码: 3
获取城市失败,错误码: -2
测试步骤以及详细代码
测试步骤
-
创建鸿蒙应用项目 -
添加上述代码文件 -
配置config.json权限 -
连接鸿蒙设备或启动模拟器 -
运行应用并授权位置权限 -
点击按钮测试定位功能 -
检查城市信息是否正确显示 -
模拟不同位置测试准确性
完整测试代码
// LocationTestAbility.java
package com.example.locationdemo.test;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.app.Context;
import ohos.bundle.IBundleManager;
import ohos.location.Location;
import ohos.location.Locator;
import ohos.location.LocatorRange;
import ohos.geo.GeoConvert;
import ohos.geo.LocationInfo;
import ohos.geo.ReverseGeoCodeRequest;
import ohos.geo.ReverseGeoCodeResult;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class LocationTestAbility extends Ability {
private Context context;
@Before
public void setUp() {
context = getContext();
}
@Test
public void testLocationPermission() {
// 检查位置权限状态
int result = verifySelfPermission("ohos.permission.LOCATION");
assertTrue("应具备位置权限", result == IBundleManager.PERMISSION_GRANTED);
}
@Test
public void testLocatorAvailability() {
Locator locator = new Locator(context);
assertNotNull("定位器实例不应为空", locator);
LocatorRange range = new LocatorRange();
range.setAccuracy(LocatorRange.COARSE);
locator.setLocatorRange(range);
// 测试定位状态
int status = locator.getLocatorState();
assertTrue("定位服务应可用", status == Locator.STATUS_AVAILABLE);
}
@Test
public void testGeoConvertService() {
GeoConvert geoConvert = GeoConvert.getInstance(context);
assertNotNull("地理编码服务不应为空", geoConvert);
// 测试北京天安门坐标的逆地理编码
ReverseGeoCodeRequest request = new ReverseGeoCodeRequest();
request.setLocation(new LocationInfo(39.9075, 116.3972));
request.setLanguage("zh_CN");
request.setMaxItems(1);
try {
ReverseGeoCodeResult result = geoConvert.getReverseGeoCode(request);
assertNotNull("逆地理编码结果不应为空", result);
assertFalse("应包含位置信息", result.getLocations().isEmpty());
ReverseGeoCodeResult.Location location = result.getLocations().get(0);
assertTrue("应包含城市信息", location.getCity() != null && !location.getCity().isEmpty());
} catch (Exception e) {
fail("逆地理编码失败: " + e.getMessage());
}
}
}
部署场景
-
智能手机和平板电脑: -
直接部署到HarmonyOS设备 -
针对不同屏幕尺寸优化UI -
考虑不同定位能力设备(GPS/北斗)
-
-
智能穿戴设备: -
优化小屏幕显示 -
简化位置获取流程 -
低功耗模式支持
-
-
车机系统: -
驾驶时简化操作 -
语音播报位置信息 -
与车载导航集成
-
-
电视设备: -
遥控器友好的控制 -
大字体显示位置信息 -
家庭位置共享
-
-
企业级应用: -
集中管理位置策略 -
审计位置访问日志 -
远程配置参数
-
疑难解答
常见问题1:定位失败或超时
-
GPS信号弱(室内环境) -
定位服务未开启 -
权限未正确授予 -
设备定位模块故障
// 增强定位可靠性
public void requestEnhancedLocation(LocationResultCallback callback) {
// 尝试多种定位方式
requestLocationWithMode(LocationRequest.PRIORITY_HIGH_ACCURACY, callback);
// 5秒后尝试低功耗模式
new Handler().postDelayed(() -> {
if (!locationReceived.get()) {
requestLocationWithMode(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY, callback);
}
}, 5000);
// 10秒后尝试仅网络定位
new Handler().postDelayed(() -> {
if (!locationReceived.get()) {
requestLocationWithMode(LocationRequest.PRIORITY_LOW_POWER, callback);
}
}, 10000);
}
private AtomicBoolean locationReceived = new AtomicBoolean(false);
private void requestLocationWithMode(int priority, LocationResultCallback callback) {
if (locationReceived.get()) return;
LocationRequest request = new LocationRequest();
request.setPriority(priority);
// ...其余代码与之前相同
}
常见问题2:逆地理编码返回错误城市
-
坐标位于边界地区 -
地理编码数据库过时 -
请求参数设置不当
// 提高逆地理编码准确性
public void getAccurateCity(double latitude, double longitude, CityResultCallback callback) {
// 尝试不同语言设置
tryCodingWithLanguage(latitude, longitude, "zh_CN", callback);
}
private void tryCodingWithLanguage(double lat, double lon, String lang, CityResultCallback callback) {
ReverseGeoCodeRequest request = new ReverseGeoCodeRequest();
request.setLocation(new LocationInfo(lat, lon));
request.setLanguage(lang);
request.setMaxItems(3); // 获取多个结果
try {
ReverseGeoCodeResult result = geoConvert.getReverseGeoCode(request);
if (result != null && !result.getLocations().isEmpty()) {
// 选择最匹配的结果
ReverseGeoCodeResult.Location bestMatch = selectBestMatch(result.getLocations());
callback.onSuccess(extractCityName(bestMatch));
} else {
// 尝试英文结果
if ("zh_CN".equals(lang)) {
tryCodingWithLanguage(lat, lon, "en_US", callback);
} else {
callback.onFailure(-2);
}
}
} catch (Exception e) {
callback.onFailure(-3);
}
}
private ReverseGeoCodeResult.Location selectBestMatch(List<ReverseGeoCodeResult.Location> locations) {
// 简单策略:选择第一个结果
// 实际项目中可根据置信度等选择
return locations.get(0);
}
常见问题3:后台定位耗电过快
-
持续高精度定位 -
频繁位置更新 -
未合理使用休眠策略
// 优化后台定位功耗
public void configureBackgroundLocation() {
LocatorRange range = new LocatorRange();
range.setAccuracy(LocatorRange.COARSE); // 降低精度
range.setPowerRequirement(LocatorRange.POWER_LOW); // 低功耗
range.setInterval(300000); // 5分钟更新一次
locator.setLocatorRange(range);
}
// 使用地理围栏代替持续定位
public void setupGeofence(double centerLat, double centerLon, float radius, GeofenceCallback callback) {
GeofenceRequest request = new GeofenceRequest();
request.setCenter(new LocationInfo(centerLat, centerLon));
request.setRadius(radius);
request.setExpirationDuration(GeofenceRequest.EXPIRATION_NEVER);
request.setTransitionTypes(GeofenceRequest.GEOFENCE_TRANSITION_ENTER |
GeofenceRequest.GEOFENCE_TRANSITION_EXIT);
locator.addGeofence(request, new GeofenceCallback() {
@Override
public void onEnterGeofence(int geofenceId) {
callback.onEnter();
}
@Override
public void onExitGeofence(int geofenceId) {
callback.onExit();
}
});
}
未来展望
-
室内定位增强:蓝牙信标与WiFi指纹定位 -
语义化位置:返回"家"、"公司"等语义位置 -
轨迹分析:行程习惯学习与预测 -
AR位置叠加:实景导航与信息标注 -
隐私计算:联邦学习下的位置数据处理 -
星基增强:高精度定位服务集成
技术趋势与挑战
趋势
-
多模态融合定位:视觉+惯性导航+GNSS -
情境感知定位:结合时间、场景的智能定位 -
边缘计算定位:本地化处理减少云端依赖 -
5G定位:利用5G基站实现高精度定位 -
数字孪生位置:虚拟世界与现实位置映射
挑战
-
隐私保护:位置数据的匿名化处理 -
能耗优化:延长设备续航时间 -
复杂环境适应:城市峡谷、室内定位 -
标准化:跨平台位置服务接口统一 -
安全威胁:位置欺骗与中间人攻击
总结
-
核心技术: -
位置权限申请流程 -
高精度定位实现 -
逆地理编码解析 -
错误处理与优化
-
-
实现方案: -
权限管理封装 -
定位服务集成 -
地理编码服务调用 -
结果解析与展示
-
-
最佳实践: -
权限请求时机 -
多模式定位策略 -
功耗优化技巧 -
用户体验设计
-
-
未来方向: -
室内外无缝定位 -
语义化位置服务 -
隐私增强技术 -
与AIoT设备联动
-
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)