AGC地理位置服务:在鸿蒙5应用中获取用户位置
前言
鸿蒙5(HarmonyOS 5)结合AppGallery Connect(AGC)地理位置服务,为开发者提供了强大的位置获取和地理围栏能力。本文将全面介绍如何在鸿蒙5应用中集成AGC地理位置服务,实现精准定位、位置更新监听和地理围栏等功能,包含完整的代码实现和最佳实践。
一、地理位置服务核心功能
精准定位:获取设备当前位置(GPS、Wi-Fi、基站多源融合)
持续追踪:实时监听位置变化
地理围栏:设置兴趣区域,进出触发事件
位置解析:坐标与地址信息互转
二、环境准备
2.1 开通AGC地理位置服务
登录AGC控制台
进入项目 > 选择应用 > 选择"地理位置服务"
点击"立即开通"
2.2 配置DevEco Studio项目
在build.gradle中添加依赖:
dependencies {
// AGC地理位置核心库
implementation 'com.huawei.agconnect:agconnect-location-harmony:1.8.0.300'
// 网络定位库
implementation 'com.huawei.hms:network-location-harmony:6.12.0.300'
// 地理编码库
implementation 'com.huawei.hms:location-harmony:6.12.0.300'
}
三、权限配置
3.1 声明权限
// config.json 配置
{
"reqPermissions": [
{
"name": "ohos.permission.LOCATION",
"reason": "获取位置信息",
"usedScene": {
"ability": ["com.example.myapp.MainAbility"],
"when": "always"
}
},
{
"name": "ohos.permission.LOCATION_IN_BACKGROUND",
"reason": "后台获取位置",
"usedScene": {
"ability": ["com.example.myapp.MainAbility"],
"when": "always"
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "获取大致位置"
}
]
}
3.2 动态权限申请
// PermissionHelper.java - 权限助手
import ohos.app.Context;
import ohos.security.SystemPermission;
public class PermissionHelper {
private static final String[] LOCATION_PERMISSIONS = {
SystemPermission.LOCATION,
SystemPermission.LOCATION_IN_BACKGROUND,
SystemPermission.APPROXIMATELY_LOCATION
};
public static boolean checkLocationPermissions(Context context) {
for (String permission : LOCATION_PERMISSIONS) {
if (context.verifySelfPermission(permission) != 0) {
return false;
}
}
return true;
}
public static void requestLocationPermissions(Context context, int requestCode) {
context.requestPermissionsFromUser(LOCATION_PERMISSIONS, requestCode);
}
}
四、获取当前位置
4.1 初始化位置服务
// LocationService.ts - 位置服务封装
import agconnect from '@agconnect/api-harmony';
import '@agconnect/location-harmony';
export default class LocationService {
private static instance: LocationService;
private locationClient: any;
private constructor() {
// 创建位置服务实例
this.locationClient = agconnect.location().createLocationClient();
// 配置定位参数
this.locationClient.setLocationOption({
priority: agconnect.location.LocationRequest.PRIORITY_HIGH_ACCURACY, // 高精度模式
interval: 10000, // 10秒更新间隔
needAddress: true // 需要地址信息
});
}
public static getInstance(): LocationService {
if (!LocationService.instance) {
LocationService.instance = new LocationService();
}
return LocationService.instance;
}
// 获取当前位置
public async getCurrentLocation(): Promise<any> {
try {
return await this.locationClient.getLastLocation();
} catch (error) {
console.error('获取位置失败:', error);
throw error;
}
}
}
4.2 获取单次位置
// LocationManager.java - 位置管理
import com.huawei.agconnect.location.AGConnectLocation;
import com.huawei.agconnect.location.LocationRequest;
import ohos.app.Context;
import java.util.concurrent.Executors;
public class LocationManager {
private AGConnectLocation locationClient;
public LocationManager(Context context) {
// 初始化位置客户端
locationClient = AGConnectLocation.getInstance(context);
}
// 获取一次当前位置
public void getSingleLocation(LocationCallback callback) {
LocationRequest request = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10000)
.setNeedAddress(true);
locationClient.requestLocationUpdates(request,
Executors.newSingleThreadExecutor(),
new AGConnectLocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
// 获取到位置后立即移除监听
locationClient.removeLocationUpdates(this);
callback.onLocationReceived(locationResult.getLastLocation());
}
@Override
public void onLocationAvailability(boolean isLocationAvailable) {
if (!isLocationAvailable) {
callback.onError(new Exception("Location not available"));
}
}
});
}
public interface LocationCallback {
void onLocationReceived(Location location);
void onError(Exception e);
}
}
五、持续位置更新
5.1 注册位置监听
// LocationTracker.js - 持续位置追踪
import LocationService from './LocationService';
export default class LocationTracker {
static startTracking(callback) {
const locationClient = LocationService.getInstance().locationClient;
// 注册位置监听
const listener = locationClient.onLocationChange((location) => {
callback(location);
});
// 返回停止监听的方法
return () => {
locationClient.removeLocationUpdates(listener);
};
}
}
// 使用示例
const stopTracking = LocationTracker.startTracking((location) => {
console.log('位置更新:', location);
});
// 停止监听时调用
// stopTracking();
5.2 后台位置服务
// BackgroundLocationService.java - 后台位置服务
import com.huawei.agconnect.location.AGConnectLocation;
import com.huawei.agconnect.location.LocationRequest;
import ohos.app.Ability;
import ohos.app.Context;
import ohos.app.Environment;
import java.io.File;
public class BackgroundLocationService extends Ability {
private AGConnectLocation locationClient;
private static final String LOCATION_FILE = "locations.txt";
@Override
public void onStart(Intent intent) {
super.onStart(intent);
// 初始化位置客户端
locationClient = AGConnectLocation.getInstance(this);
// 配置后台定位参数
LocationRequest request = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setInterval(300000) // 5分钟
.setNeedAddress(false);
// 启动后台定位
locationClient.requestLocationUpdates(request,
Executors.newSingleThreadExecutor(),
new AGConnectLocationCallback() {
@Override
public void onLocationResult(LocationResult result) {
saveLocationToFile(result.getLastLocation());
}
});
}
private void saveLocationToFile(Location location) {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), LOCATION_FILE);
String record = String.format("%s,%.6f,%.6f\n",
new Date().toString(),
location.getLatitude(),
location.getLongitude());
try (FileWriter writer = new FileWriter(file, true)) {
writer.append(record);
} catch (IOException e) {
Log.error("保存位置失败", e.getMessage());
}
}
@Override
public void onStop() {
super.onStop();
locationClient.removeLocationUpdates();
}
}
六、地理围栏功能
6.1 创建地理围栏
// GeoFenceManager.ts - 地理围栏管理
import agconnect from '@agconnect/api-harmony';
import '@agconnect/location-harmony';
export default class GeoFenceManager {
private static instance: GeoFenceManager;
private geofenceClient: any;
private constructor() {
this.geofenceClient = agconnect.location().createGeoFenceClient();
}
public static getInstance(): GeoFenceManager {
if (!GeoFenceManager.instance) {
GeoFenceManager.instance = new GeoFenceManager();
}
return GeoFenceManager.instance;
}
// 添加地理围栏
public async addGeoFence(
id: string,
latitude: number,
longitude: number,
radius: number,
triggers: number
): Promise<boolean> {
const request = {
id: id,
latitude: latitude,
longitude: longitude,
radius: radius,
triggers: triggers, // 1-进入 2-退出 3-进出都触发
loiteringDelay: 5000 // 停留延迟(毫秒)
};
try {
await this.geofenceClient.createGeoFence(request);
return true;
} catch (error) {
console.error('创建地理围栏失败:', error);
throw error;
}
}
// 移除地理围栏
public async removeGeoFence(id: string): Promise<boolean> {
try {
await this.geofenceClient.deleteGeoFence(id);
return true;
} catch (error) {
console.error('移除地理围栏失败:', error);
throw error;
}
}
}
6.2 监听围栏事件
// GeoFenceHandler.java - 围栏事件处理
import com.huawei.agconnect.location.GeoFence;
import com.huawei.agconnect.location.GeoFenceClient;
import com.huawei.agconnect.location.GeoFenceEvent;
import ohos.app.Context;
public class GeoFenceHandler {
private GeoFenceClient geoFenceClient;
public GeoFenceHandler(Context context) {
geoFenceClient = AGConnectLocation.getInstance(context).createGeoFenceClient();
}
public void registerGeoFenceListener(GeoFenceListener listener) {
geoFenceClient.addGeoFenceEvent(
Executors.newSingleThreadExecutor(),
new GeoFenceEvent.Listener() {
@Override
public void onEvent(GeoFenceEvent event) {
switch (event.getEventType()) {
case GeoFenceEvent.ENTER_GEOFENCE:
listener.onEnter(event.getGeoFence());
break;
case GeoFenceEvent.EXIT_GEOFENCE:
listener.onExit(event.getGeoFence());
break;
case GeoFenceEvent.DWELL_GEOFENCE:
listener.onDwell(event.getGeoFence());
break;
}
}
});
}
public interface GeoFenceListener {
void onEnter(GeoFence geoFence);
void onExit(GeoFence geoFence);
void onDwell(GeoFence geoFence);
}
}
七、位置与地址转换
7.1 地理编码(地址→坐标)
// GeocodingService.js - 地理编码服务
import agconnect from '@agconnect/api-harmony';
import '@agconnect/location-harmony';
export default class GeocodingService {
static async addressToLocation(address) {
try {
const geocoder = agconnect.location().createGeocoder();
const results = await geocoder.getFromLocationName(address, 1);
if (results && results.length > 0) {
return {
latitude: results[0].latitude,
longitude: results[0].longitude
};
}
throw new Error('未找到匹配的位置');
} catch (error) {
console.error('地理编码失败:', error);
throw error;
}
}
}
7.2 逆地理编码(坐标→地址)
// ReverseGeocoding.java - 逆地理编码
import com.huawei.agconnect.location.Geocoder;
import com.huawei.agconnect.location.GeocoderResult;
import ohos.app.Context;
import java.util.List;
import java.util.Locale;
public class ReverseGeocoding {
private Geocoder geocoder;
public ReverseGeocoding(Context context) {
geocoder = AGConnectLocation.getInstance(context).createGeocoder(Locale.getDefault());
}
public void getAddressFromLocation(double latitude, double longitude,
GeocodeCallback callback) {
geocoder.getFromLocation(latitude, longitude, 1)
.addOnSuccessListener(results -> {
if (results != null && !results.isEmpty()) {
callback.onSuccess(results.get(0));
} else {
callback.onError(new Exception("No address found"));
}
})
.addOnFailureListener(callback::onError);
}
public interface GeocodeCallback {
void onSuccess(GeocoderResult result);
void onError(Exception e);
}
}
八、最佳实践与优化
8.1 定位策略选择
// LocationStrategy.java - 定位策略
public class LocationStrategy {
public static LocationRequest getOptimalRequest(boolean highAccuracy, long interval) {
LocationRequest request = new LocationRequest()
.setInterval(interval)
.setNeedAddress(false);
if (highAccuracy) {
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
} else if (BatteryManager.isPowerSaveMode()) {
request.setPriority(LocationRequest.PRIORITY_LOW_POWER);
} else {
request.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
return request;
}
}
8.2 位置数据缓存
// LocationCache.ts - 位置缓存
import ohos.data.preferences from '@ohos.data.preferences';
export default class LocationCache {
private static prefs: any = null;
static async init() {
this.prefs = await ohos.data.preferences.getPreferences(
ohos.app.Context.getApplicationContext(),
'location_cache'
);
}
static async saveLocation(location: any) {
await this.prefs.putString('last_location', JSON.stringify(location));
await this.prefs.flush();
}
static async getLastLocation(): Promise<any | null> {
const json = await this.prefs.getString('last_location', '');
return json ? JSON.parse(json) : null;
}
}
8.3 位置更新节流
// LocationThrottle.js - 位置更新节流
export default class LocationThrottle {
constructor(minInterval = 5000) {
this.lastUpdate = 0;
this.minInterval = minInterval;
this.pendingLocation = null;
}
shouldUpdate(timestamp) {
const now = Date.now();
if (now - this.lastUpdate >= this.minInterval) {
this.lastUpdate = now;
return true;
}
this.pendingLocation = timestamp;
return false;
}
checkPending() {
if (this.pendingLocation &&
Date.now() - this.lastUpdate >= this.minInterval) {
this.lastUpdate = Date.now();
const location = this.pendingLocation;
this.pendingLocation = null;
return location;
}
return null;
}
}
九、常见问题解决
定位权限被拒绝:
// 优雅处理权限拒绝
public static void handlePermissionDenied(Context context) {
new ToastDialog(context)
.setText("位置服务被禁用,部分功能将受限")
.setAlignment(LayoutAlignment.CENTER)
.show();
// 使用IP定位等备用方案
fallbackToIPLocation();
}
定位不准确:
// 提高定位精度
function improveAccuracy() {
const locationClient = agconnect.location().createLocationClient();
locationClient.setLocationOption({
priority: agconnect.location.LocationRequest.PRIORITY_HIGH_ACCURACY,
interval: 10000,
smallestDisplacement: 10 // 最小位移(米)
});
}
后台定位限制:
// 添加后台服务声明
{
"abilities": [
{
"name": "BackgroundLocationService",
"type": "service",
"backgroundModes": ["location"]
}
]
}
电量优化:
// 根据电量状态调整定位策略
if (BatteryManager.isPowerSaveMode()) {
request.setPriority(LocationRequest.PRIORITY_LOW_POWER)
.setInterval(600000); // 10分钟
}
结语
通过集成AGC地理位置服务,您的鸿蒙5应用可以实现:
精准定位:获取用户当前位置信息
智能围栏:基于位置触发业务逻辑
地址解析:实现坐标与地址互转
持续追踪:实时监控位置变化
建议在实际项目中:
根据场景选择合适的定位精度
实现完善的权限处理流程
考虑电量消耗优化
提供位置不可用时的备用方案
掌握AGC地理位置服务后,您可以为用户打造更智能、更贴心的位置感知应用,显著提升用户体验和应用价值。

浙公网安备 33010602011771号