《仿盒马》app开发技术分享-- 定位获取(25)


## 技术栈


Appgallery connect

## 开发准备


上一节我们实现了地址管理页面的数据查询和展示,接下来我们要实现的功能是地址添加相关的,我们想实现的功能是地图选点,那么在地图选点之前我们要做的就是先获取用户当前的定位。获取定位后我们拿到经纬度和其他信息,然后在对应的地图上展示。


## 功能分析

要想实现定位功能,首先我们需要给应用申请定位权限,然后我们每次进入页面之前需要先进行定位功能是否开启的判断,如果没有开启我们要提示用户去开启,之后我们才是对定位请求的开启判断,用户同意之后获取当前的定位,在返回值中拿到经纬度


## 代码实现

首先我们在model.json5中添加对应的权限

{

        "name": "ohos.permission.LOCATION",

        "reason": "$string:app_location",

        "usedScene": {

          "abilities": [

            "EntryAbility"

          ],

          "when":"inuse"

        }


      },

      {

        "name": "ohos.permission.APPROXIMATELY_LOCATION",

        "reason": "$string:app_reason_location",

        "usedScene": {

          "abilities": [

            "EntryAbility"

          ],

          "when":"inuse"

        }

      }

      添加完成后我们新建一个提交定位管理的页面,在生命周期中先进行手机是否开启定位的判断,并且新增两个变量来控制我们的定位触发

   @State  locationKey:boolean=false

  @State  addressSetting:boolean=false

  


aboutToAppear(): void {

    try {

      let locationEnabled = geoLocationManager.isLocationEnabled();

      if (locationEnabled) {

        this.addressSetting=true


      }else {

        this.addressSetting=false

      }

    } catch (err) {

      console.error("errCode:" + err.code + ", message:"  + err.message);

    }

  }


如果用户开启了定位,并且我们没有开启应用的定位权限,在当前页面的底部提醒用户,去开启定位



  build() {

    Column() {

      Stack({alignContent:Alignment.Bottom}){

        Column(){


        }

        .layoutWeight(1)


        if (this.addressSetting&&!this.locationKey){

          Row(){

            Text()

              .width(40)


            Text("定位未开启")

              .fontColor(Color.Black)


            Text("开启定位")

              .fontColor(Color.White)

              .backgroundColor(Color.Pink)

              .borderRadius(10)

              .padding(10)

              .onClick(()=>{

               

              })

          }

          .padding(10)

          .borderRadius(5)

          .margin({bottom:30})

          .backgroundColor('#33000000')

          .justifyContent(FlexAlign.SpaceAround)

          .width('90%')

        }


      }

      .backgroundColor(Color.White)

      .height('100%')

      .width('100%')


    }


  }

  因为在隐私合规的情况下,我们已经不能进入页面就执行权限的请求了,这一点很重要,我们执行代码看一下效果

  ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/5c481a8be5b74260841c8d53abfa30af.png)

当我们点击开启定位

 .onClick(()=>{

                this.reqPermissionsFromUser(permissions);

                this.permissionController.open();

              })

这里我们同步创建一个弹窗,当然你可以有多种选择来实现权限的同步说明,在这里我们两种方式都实现了

创建弹窗

@CustomDialog

export  default  struct PermissionDialogWidget{

  @State titleText:string='';

  @State contentText:string='';

  controller: CustomDialogController

  build(){

    Column(){

      Text(this.titleText).margin({top:10})

      Text(this.contentText).margin({top:20,bottom:10})

    }.justifyContent(FlexAlign.Start).padding({left:20,right:20})

  }

}


引用弹窗

 permissionController:CustomDialogController=new CustomDialogController({

    builder:PermissionDialogWidget({

      titleText:"权限说明",

      contentText: 'xxx想要申请位置权限,用于地址选择等功能。同意该权限后,选择地址时会复用此权限,不会重新申请,不授权上述权限,不影响APP其他功能使用。',

    }),

    alignment: DialogAlignment.Top,

  })

执行权限请求

  reqPermissionsFromUser(permissions: Array): void {

    let context = getContext(this) as common.UIAbilityContext;

    let atManager = abilityAccessCtrl.createAtManager();

    atManager.requestPermissionsFromUser(context, permissions).then((data) => {

      let grantStatus: Array = data.authResults;

      let length: number = grantStatus.length;

      for (let i = 0; i < length; i++) {

        if (grantStatus[i] === 0) {

          this.locationKey=true

          this.permissionController.close()

          let request: geoLocationManager.SingleLocationRequest = {

            'locatingPriority': geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,

            'locatingTimeoutMs': 10000

          }

          try {

            geoLocationManager.getCurrentLocation(request).then((result) => {

              console.log('current location: ' + JSON.stringify(result));

              let locationInfo:geoLocationManager.ReverseGeoCodeRequest=result;

              let reverseGeocodeRequest:geoLocationManager.ReverseGeoCodeRequest = {"latitude": locationInfo.latitude, "longitude": locationInfo.longitude, "maxItems": 1};

              try {

                geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, (err, data) => {

                  if (err) {

                    console.error('getAddressesFromLocation: err=' + JSON.stringify(err));

                  }

                  if (data) {

                    console.info('地址打印' + JSON.stringify(data));

                  }

                });

              } catch (err) {

                console.error("errCode:" + err.code + ", message:"  + err.message);

              }

            })

              .catch((error:BusinessError) => {

                console.error('promise, getCurrentLocation: error=' + JSON.stringify(error));

              });

          } catch (err) {

            console.error("errCode:" + JSON.stringify(err));

          }

        } else {

          this.locationKey=false

          this.permissionController.close()

          return;

        }

      }

    }).catch((err:Error) => {

      console.error(`requestPermissionsFromUser failed, code is ${err.name}, message is ${err.message}`);

    })

  }

  

在这里我们既实现了自定义弹窗的同步说明,同时也在model.json5中配置了reason进行说明,可以按需进行实现。


在请求定位的返回信息中我们拿到了经纬度的信息,到这里我们实现了定位获取功能


请使用浏览器的分享功能分享到微信等