HarmonyOS 鸿蒙Next中实现地图实时定位,拯救“路痴”

HarmonyOS 鸿蒙Next中实现地图实时定位,拯救“路痴” 实时定位,已经成为应用必备能力之一,尤其是导航应用,更需要快速准确定位用户实时位置。

华为定位服务能够赋予应用程序快速、精准地获取用户位置信息的能力,同时定位服务助力全球开发者实现个性化地图呈现与交互,全面提升应用的LBS体验。

下面为您详细解析,华为定位服务与地图服务如何实现应用实时定位。

预期功能

获取实时定位,并且在地图上显示位置点,首次启动跳转当前位置点,并且位置改变当前位置点和地图视角随之改变。

使用能力

  • 华为定位服务 : 基础定位
  • 华为地图服务:地图显示

实现原理

使用华为定位服务获取实时位置,在地图上显示“我的位置”按钮,在位置变化时,跳转地图到当前定位。

准备工作

AGC账号注册,项目创建

  1. 注册成为开发者

  2. 创建应用,添加sha256,开启map/site开关,下载json文件

  3. 配置Android Studio工程

    1. 将“agconnect-services.json”文件拷贝到应用级根目录下
      • 在“allprojects > repositories”中配置HMS Core SDK的Maven仓地址。
      • 在“buildscript > repositories”中配置HMS Core SDK的Maven仓地址。
      • 如果App中添加了“agconnect-services.json”文件则需要在“buildscript > dependencies”中增加agcp配置。
    buildscript {
        repositories {
            maven { url 'https://developer.huawei.com/repo/' }
            google()
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:3.3.2'
            classpath 'com.huawei.agconnect:agcp:1.3.1.300'
        }
    }
    
    allprojects {
        repositories {
            maven { url 'https://developer.huawei.com/repo/' }
            google()
            jcenter()
        }
    }
    
    1. 在“dependencies”中添加如下编译依赖
    dependencies {
        implementation 'com.huawei.hms:maps:{version}'
        implementation 'com.huawei.hms:location:{version}'
    }
    
    1. 在文件头添加配置
    apply plugin: 'com.huawei.agconnect'
    
    1. 在android中配置签名。将生成签名证书指纹生成的签名文件复制到您工程的app目录下,并在“build.gradle”文件中配置签名
    signingConfigs {
        release {
            // 签名证书
            storeFile file("**.**")
            // 密钥库口令
            storePassword "******"
            // 别名
            keyAlias "******"
            // 密钥口令
            keyPassword "******"
            v2SigningEnabled true
        }
    }
    
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            debuggable true
        }
        debug {
            debuggable true
        }
    }
    

关键代码实现

  1. 编写一个service获取实时定位。

    public class LocationService extends Service {
    
        private final String TAG = this.getClass().getSimpleName();
    
        List<ILocationChangedLister> locationChangedList = new ArrayList<>();
    
        // location
        private FusedLocationProviderClient fusedLocationProviderClient;
    
        private LocationRequest mLocationRequest;
    
        private final LocationCallback mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                locationResult.getLocations();
                Log.d(TAG, "onLocationResult:" + locationResult);
                Location location = locationResult.getLocations().get(0);
                Log.w(TAG, "onLocationResult:Latitude " + location.getLatitude());
                Log.w(TAG, "onLocationResult:Longitude " + location.getLongitude());
    
                for (ILocationChangedLister locationChanged : locationChangedList) {
                    locationChanged.locationChanged(new LatLng(location.getLatitude(), location.getLongitude()));
                }
            }
    
            @Override
            public void onLocationAvailability(LocationAvailability locationAvailability) {
                super.onLocationAvailability(locationAvailability);
                Log.d(TAG, "onLocationAvailability:" + locationAvailability.toString());
            }
        };
    
        private final MyBinder binder = new MyBinder();
    
        private final Random generator = new Random();
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        @Override
        public void onCreate() {
            Log.i("DemoLog", "TestService -> onCreate, Thread:" + Thread.currentThread().getName());
            super.onCreate();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i("DemoLog", "TestService -> onStartCommand, startId:" + startId + ", Thread:" + Thread.currentThread().getName());
            return START_NOT_STICKY;
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            Log.i("DemoLog", "TestService -> onUnbind, from:" + intent.getStringExtra("from"));
            return false;
        }
    
        @Override
        public void onDestroy() {
            Log.i("DemoLog", "TestService -> onDestroy, Thread:" + Thread.currentThread().getName());
            super.onDestroy();
        }
    
        public int getRandomNumber() {
            return generator.nextInt();
        }
    
        public void addLocationChangedlister(ILocationChangedLister iLocationChangedLister) {
            locationChangedList.add(iLocationChangedLister);
        }
    
        public void getMyLoction() {
            Log.d(TAG, "getMyLoction:");
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
    
            SettingsClient settingsClient = LocationServices.getSettingsClient(this);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
            mLocationRequest = new LocationRequest();
            builder.addLocationRequest(mLocationRequest);
            LocationSettingsRequest locationSettingsRequest = builder.build();
            // location setting
            settingsClient.checkLocationSettings(locationSettingsRequest)
                .addOnSuccessListener(locationSettingsResponse -> fusedLocationProviderClient
                    .requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper())
                    .addOnSuccessListener(aVoid -> Log.d(TAG, "onSuccess:" + aVoid)))
                .addOnFailureListener(Throwable::printStackTrace);
        }
    
        public class MyBinder extends Binder {
            public LocationService getService() {
                return LocationService.this;
            }
        }
    
        public interface ILocationChangedLister {
            /**
             * Update the location information
             *
             * @param latLng The new location information
             */
            public void locationChanged(LatLng latLng);
        }
    }
    
  2. 在Activity中绘制地图,监听实时位置

    Xml中添加地图:

    <com.huawei.hms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    activity地图绘制:

    mapView.onCreate(null);
    mapView.getMapAsync(this);
    

    绘制是打开我的位置 按钮显示

    @Override
    public void onMapReady(HuaweiMap huaweiMap) {
        hMap = huaweiMap;
        hMap.setMyLocationEnabled(true);
    }
    

    设置定位服务绑定监听

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            isBound = true;
            if (binder instanceof LocationService.MyBinder) {
                LocationService.MyBinder myBinder = (LocationService.MyBinder) binder;
                locationService = myBinder.getService();
                Log.i(TAG, "ActivityA onServiceConnected");
                locationService.addLocationChangedlister(iLocationChangedLister);
                locationService.getMyLoction();
            }
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBound = false;
            locationService = null;
            Log.i(TAG, "ActivityA onServiceDisconnected");
        }
    };
    

    绑定到LocationService:

    private void bindLocationService() {
        Intent intent = new Intent(mActivity, LocationService.class);
        intent.putExtra("from", "ActivityA");
        Log.i(TAG, "-------------------------------------------------------------");
        Log.i(TAG, "bindService to ActivityA");
        mActivity.bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }
    

    在位置变化监听中处理位置改变

    LocationService.ILocationChangedLister iLocationChangedLister = new LocationService.ILocationChangedLister() {
        @Override
        public void locationChanged(LatLng latLng) {
            Log.d(TAG, "locationChanged:" + latLng.latitude);
            Log.d(TAG, "locationChanged:" + latLng.longitude);
            updateLocation(latLng);
        }
    };
    

    更新地图经纬度视角

    private void updateLocation(LatLng latLng) {
        mLatLng = latLng;
        hMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 1));
    }
    

测试

使用模拟位置软件改变模拟位置,地图视角和我的位置按钮可以随之跳动。功能实现。

欲了解HMS Core更多详情,请参阅:


更多关于HarmonyOS 鸿蒙Next中实现地图实时定位,拯救“路痴”的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

请问这个源码的具体地址在哪里?文中https://gitee.com/hms-core没有找到。

更多关于HarmonyOS 鸿蒙Next中实现地图实时定位,拯救“路痴”的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中实现地图实时定位,可以通过以下步骤:

  1. 集成地图SDK:首先,集成华为地图服务(HMS Map Kit),确保在build.gradle中添加依赖。

  2. 获取定位权限:在config.json中声明定位权限,并在运行时动态请求用户授权。

  3. 初始化地图:在Activity或Ability中初始化地图,并设置地图类型和位置显示。

  4. 实时定位:使用LocationManager获取实时位置,并通过Map对象更新用户位置。

  5. 处理位置更新:通过LocationListener监听位置变化,实时更新地图上的标记。

  6. 优化用户体验:添加指南针、缩放控件等,帮助用户更好地导航。

通过这些步骤,你可以在鸿蒙Next中实现高效的地图实时定位功能,帮助用户轻松找到目的地。

回到顶部