【HarmonyOS Next】地图使用详解(一)

背景


这系列文章主要讲解鸿蒙地图的使用,当前可以免费使用,并提供了丰富的SDK给开发者去自定义控件开发。目前可以实现个性化显示地图、位置搜索和路径规划等功能,轻松完成地图构建工作。需要注意的是,现在测试只能使用实体手机去做调试,模拟器和预览器是没有办法做测试和使用的

地图开发环境搭建


1. AGC中创建项目

在AGC中新建项目,并复制AGC项目中的Client ID 填写到工程中的entry模块的module.json5文件中,新增metadata,配置name为client_id,value为AGC项目中的Client ID。

请添加图片描述

{"module": {"name": "entry","type": "entry","description": "$string:module_desc","mainElement": "EntryAbility","deviceTypes": ["phone","tablet","2in1"],"deliveryWithInstall": true,"installationFree": false,"pages": "$profile:main_pages","abilities": [{"name": "EntryAbility","srcEntry": "./ets/entryability/EntryAbility.ets","description": "$string:EntryAbility_desc","icon": "$media:layered_image","label": "$string:EntryAbility_label","startWindowIcon": "$media:startIcon","startWindowBackground": "$color:start_window_background","exported": true,"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}]}],"extensionAbilities": [{"name": "EntryBackupAbility","srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets","type": "backup","exported": false,"metadata": [{"name": "ohos.extension.backup","resource": "$profile:backup_config"}],}],"metadata": [{"name": "client_id","value": "6917564776665168777"}]}
}

2.AGC中开通地图服务

在API管理界面,打开地图服务

在这里插入图片描述

3.AGC中创建APP

在证书、APP ID和Profile中,APP ID中创建之前项目中的App

4.在项目文件中生成密钥请求文件

这个密钥文件比较重要,务必妥善保存。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里的Alias需要记住,后面需要用到
在这里插入图片描述

保存csr文件

在这里插入图片描述

查看生成的csr文件

在这里插入图片描述

5.AGC项目中创建证书和设备

新建调试证书,并把证书下载到本地。

在这里插入图片描述

在这里插入图片描述

6.AGC项目中创建Profile

选择对应的调试证书,完成Profile的创建

在这里插入图片描述

在这里插入图片描述

7.把生成的证书和调试文件添加到项目结构中

在这里插入图片描述

在这里插入图片描述

8.确保当前IDE已经登陆了你的华为账号

在这里插入图片描述

地图组件(MapComponent)

  • 示例代码使用MVVM架构来配置

1、MapComponent组件初始化

  • 提供了两个必填参数,mapOptions和mapCallback
属性名称属性类型属性备注是否必填
mapOptionsmapCommon.MapOptions初始化参数,提供了地图类型、相机位置、地图边界等属性
mapCallbackAsyncCallback<map.MapComponentController>地图主要功能类map.MapComponentController的回调函数,提供了地图各种操作的API
  • 项目初始化框架
import { MapViewModel } from '../ViewModels/MapViewModel';
import { MapComponent } from '@kit.MapKit';@Entry
@ComponentV2
struct FirstPage {@Local MapVM: MapViewModel = new MapViewModel();aboutToAppear(): void {this.MapVM.Init();}build() {RelativeContainer() {MapComponent({mapOptions: this.MapVM.MapOption,mapCallback: this.MapVM.MapCallBack}).width("100%").height("100%").id("Map")}.height('100%').width('100%')}
}
  • VM中的MapOption赋值
this.MapOption = {//相机位置position: {target: {latitude: this.LocationLatitude,longitude: this.LocationLongitude},zoom: 10},//地图类型mapType: mapCommon.MapType.STANDARD,//地图最小图层,默认值为2minZoom: 2,//地图最大图层,默认值为20maxZoom: 20,//是否支持旋转手势rotateGesturesEnabled: true,//是否支持滑动手势scrollGesturesEnabled: true,//是否支持缩放手势zoomGesturesEnabled: true,//是否支持倾斜手势tiltGesturesEnabled: true,//是否展示缩放控件zoomControlsEnabled: true,//是否展示定位按钮myLocationControlsEnabled: true,//是否展示指南针控件compassControlsEnabled: false,//是否展示比例尺scaleControlsEnabled: true,//是否一直显示比例尺,只有比例尺启用时该参数才生效。alwaysShowScaleEnabled: true
};
  • VM中的MapCallBack赋值
this.MapCallBack = async (err, mapController) => {if (!err) {this.MapController = mapController;//启用我的位置图层mapController.setMyLocationEnabled(true);//设置我的位置跟随设备移动mapController.setMyLocationStyle({displayType: mapCommon.MyLocationDisplayType.LOCATE})//启用我的位置按钮mapController.setMyLocationControlsEnabled(true);//地图监听时间管理器this.MapEventManager = this.MapController.getEventManager();}
}
  • 权限申请(在VM中封装申请)
/*** 所需要得权限*/
MapPermissions: Permissions[] =['ohos.permission.INTERNET','ohos.permission.LOCATION','ohos.permission.APPROXIMATELY_LOCATION']
/*** 初始化方法*/
public async Init() {//识别权限是否赋予if (!PermissionUtils.CheckPermissions(this.MapPermissions)) {const perResult: boolean = await PermissionUtils.RequestPermissions(this.MapPermissions);if (!perResult) {return;}}
}

权限方法封装

import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';/***权限封装类*/
export class PermissionUtils {/*** 检查权限是否授权(完全授权)* @param permissionsArr 权限集合* @returns true:已经全部授权;false:没有全部授权*/public static CheckPermissions(permissionsArr: Permissions[]): boolean {const atManager = abilityAccessCtrl.createAtManager();//获取bundle信息const bundleInfo =bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);// 拿到当前应用的tokenID 标识const tokenID = bundleInfo.appInfo.accessTokenId//校验应用是否被授予权限let result: boolean = true;permissionsArr.forEach((x: Permissions, index: number) => {if (!(atManager.checkAccessTokenSync(tokenID, x) === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)) {result = false;return;}})return result;}/*** 申请授权(首次弹窗申请)* @param permissionList 权限集合* @returns true:权限完全加载;false:有权限没有加载*/public static async RequestPermissions(permissionList: Permissions[]): Promise<boolean> {// 程序访问控制管理const atManager = abilityAccessCtrl.createAtManager();// 拉起弹框请求用户授权const grantStatus = await atManager.requestPermissionsFromUser(getContext(), permissionList)// 获取请求权限的结果const isAuth = grantStatus.authResults.every(v => v === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)// 返回 Promise 授权结果return isAuth ? Promise.resolve(true) : Promise.reject(false)}/*** 打开系统设置的权限管理页面*/public static OpenPermissionSettingsPage() {// 获取上下文const context = getContext() as common.UIAbilityContext// 获取包信息const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)// 打开系统设置页context.startAbility({bundleName: 'com.huawei.hmos.settings',abilityName: 'com.huawei.hmos.settings.MainAbility',uri: 'application_info_entry',parameters: {// 按照包名打开对应设置页pushParams: bundleInfo.name}})}
}
  • 项目加载时,先进行VM的初始化
aboutToAppear(): void {this.MapVM.Init();
}
  • 界面初始化展示

在这里插入图片描述

2、地图初始化类(MapOptions)

属于mapCommon类

  • 常用属性
名称类型可选说明
mapTypeMapType地图类型,默认值为MapType.STANDARD,异常值按默认值处理。
positionCameraPosition地图相机位置。
boundsLatLngBounds地图展示边界,异常值根据无边界处理。说明西南角纬度不能大于东北角纬度。
minZoomnumber地图最小图层,有效范围:[2, 20],默认值为2,异常值按默认值处理。如果设置的最小缩放级别小于2,minZoom会取2。
maxZoomnumber地图最大图层,有效范围:[2, 20],默认值为20,异常值按默认值处理。如果设置的最大缩放级别大于20,maxZoom会取20。
rotateGesturesEnabledboolean是否支持旋转手势,默认值为true,异常值按默认值处理。true:支持false:不支持
scrollGesturesEnabledboolean是否支持滑动手势,默认值为true,异常值按默认值处理。true:支持false:不支持
zoomGesturesEnabledboolean是否支持缩放手势,默认值为true,异常值按默认值处理。true:支持false:不支持
tiltGesturesEnabledboolean是否支持倾斜手势,默认值为true,异常值按默认值处理。true:支持false:不支持
zoomControlsEnabledboolean是否展示缩放控件,默认值为true,异常值按默认值处理。true:展示false:不展示
myLocationControlsEnabledboolean是否展示定位按钮,默认值为false,异常值按默认值处理。true:展示false:不展示
compassControlsEnabledboolean是否展示指南针控件,默认值为true,异常值按默认值处理。true:展示false:不展示
scaleControlsEnabledboolean是否展示比例尺,默认值为false,异常值按默认值处理。true:展示false:不展示
paddingPadding设置地图和边界的距离,默认值为{ left: 0 , top: 0 , right: 0 , bottom: 0 }。
styleIdstring自定义样式ID。
dayNightModeDayNightMode日间夜间模式,默认值为DayNightMode.DAY(日间模式)
alwaysShowScaleEnabledboolean是否一直显示比例尺,只有比例尺启用时该参数才生效。
  • 在VM类中,需要在类初始化的时候把MapOption初始化。
constructor() {this.MapOption = {//相机位置position: {target: {latitude: this.LocationLatitude,longitude: this.LocationLongitude},zoom: 10},//地图类型mapType: mapCommon.MapType.STANDARD,//地图最小图层,默认值为2minZoom: 2,//地图最大图层,默认值为20maxZoom: 20,//是否支持旋转手势rotateGesturesEnabled: true,//是否支持滑动手势scrollGesturesEnabled: true,//是否支持缩放手势zoomGesturesEnabled: true,//是否支持倾斜手势tiltGesturesEnabled: true,//是否展示缩放控件zoomControlsEnabled: true,//是否展示定位按钮myLocationControlsEnabled: true,//是否展示指南针控件compassControlsEnabled: false,//是否展示比例尺scaleControlsEnabled: true,//是否一直显示比例尺,只有比例尺启用时该参数才生效。alwaysShowScaleEnabled: true};this.MapCallBack = async (err, mapController) => {if (!err) {this.MapController = mapController;//启用我的位置图层mapController.setMyLocationEnabled(true);//设置我的位置跟随设备移动mapController.setMyLocationStyle({displayType: mapCommon.MyLocationDisplayType.LOCATE})//启用我的位置按钮mapController.setMyLocationControlsEnabled(true);//地图监听时间管理器this.MapEventManager = this.MapController.getEventManager();}}
}

3、获取手机用户当前位置

通过geoLocationManager的getCurrentLocation方法,获取用户的坐标经纬度,然后封装成更新用户定位的方法,在初始化的时候调用,就可以实现手机打开后会直接更新到用户的位置

/*** 更新用户定位*/
public async UpdateLocation() {// 获取用户位置坐标let location: geoLocationManager.Location = await geoLocationManager.getCurrentLocation();this.LocationLongitude = location.longitude;this.LocationLatitude = location.latitude;
}

完整代码

  • Page
import { MapViewModel } from '../ViewModels/MapViewModel';
import { MapComponent } from '@kit.MapKit';@Entry
@ComponentV2
struct FirstPage {@Local MapVM: MapViewModel = new MapViewModel();aboutToAppear(): void {this.MapVM.Init();}build() {RelativeContainer() {MapComponent({mapOptions: this.MapVM.MapOption,mapCallback: this.MapVM.MapCallBack}).width("100%").height("100%").id("Map")}.height('100%').width('100%')}
}
  • ViewModel
import { mapCommon, map, sceneMap } from '@kit.MapKit';
import { AsyncCallback } from '@kit.BasicServicesKit';
import { common, Permissions } from '@kit.AbilityKit';
import { PermissionUtils } from '../Utils/PermissionUtils';
import geoLocationManager from '@ohos.geoLocationManager';
import { image } from '@kit.ImageKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { MapMarkImage } from '../Utils/MapMarkImage';@ObservedV2
export class MapViewModel {/*** 地图初始化参数设置*/MapOption?: mapCommon.MapOptions/*** 地图回调方法*/MapCallBack?: AsyncCallback<map.MapComponentController>/*** 地图控制器*/MapController?: map.MapComponentController/*** 地图监听管理器*/MapEventManager?: map.MapEventManager/*** 地图标记集合*/Markers: map.Marker[] = []/*** 所需要得权限*/MapPermissions: Permissions[] =['ohos.permission.INTERNET','ohos.permission.LOCATION','ohos.permission.APPROXIMATELY_LOCATION']/*** 当前位置的维度*/public LocationLatitude: number = 39.9;/*** 当前位置的经度*/public LocationLongitude: number = 116.4;/*** 初始化方法*/public async Init() {//识别权限是否赋予if (!PermissionUtils.CheckPermissions(this.MapPermissions)) {const perResult: boolean = await PermissionUtils.RequestPermissions(this.MapPermissions);if (!perResult) {return;}}//标点初始化MapMarkImage.Init(getContext(this));}constructor() {this.UpdateLocation();this.MapOption = {//相机位置position: {target: {latitude: this.LocationLatitude,longitude: this.LocationLongitude},zoom: 10},//地图类型mapType: mapCommon.MapType.STANDARD,//地图最小图层,默认值为2minZoom: 2,//地图最大图层,默认值为20maxZoom: 20,//是否支持旋转手势rotateGesturesEnabled: true,//是否支持滑动手势scrollGesturesEnabled: true,//是否支持缩放手势zoomGesturesEnabled: true,//是否支持倾斜手势tiltGesturesEnabled: true,//是否展示缩放控件zoomControlsEnabled: true,//是否展示定位按钮myLocationControlsEnabled: true,//是否展示指南针控件compassControlsEnabled: false,//是否展示比例尺scaleControlsEnabled: true,//是否一直显示比例尺,只有比例尺启用时该参数才生效。alwaysShowScaleEnabled: true};this.MapCallBack = async (err, mapController) => {if (!err) {this.MapController = mapController;//启用我的位置图层mapController.setMyLocationEnabled(true);//设置我的位置跟随设备移动mapController.setMyLocationStyle({displayType: mapCommon.MyLocationDisplayType.LOCATE})//启用我的位置按钮mapController.setMyLocationControlsEnabled(true);//地图监听时间管理器this.MapEventManager = this.MapController.getEventManager();}}}/*** 更新用户定位*/public async UpdateLocation() {// 获取用户位置坐标let location: geoLocationManager.Location = await geoLocationManager.getCurrentLocation();this.LocationLongitude = location.longitude;this.LocationLatitude = location.latitude;}/*** 移动视图相机* @param latitude 维度* @param longitude 经度*/public async MoveCamera(latitude: number, longitude: number) {if (this.MapController) {//将视图移动到标点位置let nwPosition = map.newCameraPosition({target: {latitude: latitude,longitude: longitude},zoom: 10})// 以动画方式移动地图相机this.MapController.animateCamera(nwPosition, 1000);}}
}
  • PermissionUtils
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';/***权限封装类*/
export class PermissionUtils {/*** 检查权限是否授权(完全授权)* @param permissionsArr 权限集合* @returns true:已经全部授权;false:没有全部授权*/public static CheckPermissions(permissionsArr: Permissions[]): boolean {const atManager = abilityAccessCtrl.createAtManager();//获取bundle信息const bundleInfo =bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);// 拿到当前应用的tokenID 标识const tokenID = bundleInfo.appInfo.accessTokenId//校验应用是否被授予权限let result: boolean = true;permissionsArr.forEach((x: Permissions, index: number) => {if (!(atManager.checkAccessTokenSync(tokenID, x) === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)) {result = false;return;}})return result;}/*** 申请授权(首次弹窗申请)* @param permissionList 权限集合* @returns true:权限完全加载;false:有权限没有加载*/public static async RequestPermissions(permissionList: Permissions[]): Promise<boolean> {// 程序访问控制管理const atManager = abilityAccessCtrl.createAtManager();// 拉起弹框请求用户授权const grantStatus = await atManager.requestPermissionsFromUser(getContext(), permissionList)// 获取请求权限的结果const isAuth = grantStatus.authResults.every(v => v === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)// 返回 Promise 授权结果return isAuth ? Promise.resolve(true) : Promise.reject(false)}/*** 打开系统设置的权限管理页面*/public static OpenPermissionSettingsPage() {// 获取上下文const context = getContext() as common.UIAbilityContext// 获取包信息const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)// 打开系统设置页context.startAbility({bundleName: 'com.huawei.hmos.settings',abilityName: 'com.huawei.hmos.settings.MainAbility',uri: 'application_info_entry',parameters: {// 按照包名打开对应设置页pushParams: bundleInfo.name}})}
}

总结

上面的流程是地图组件的初始化的个人理解流程,看完这篇希望可以在地图开发上给你提供帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70609.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】 时间库chrono计算程序运行时间

C 时间库chrono计算程序运行时间 本文总结了chrono库的引入方法以及计算程序片段运行时间的方法 一、chrono库的引入方法&#xff08;注意事项&#xff09; 首先chrono是属于std命名空间的。 所以在程序中应该这样包含头文件&#xff1a; #include <chrono> using n…

计算机毕业设计SpringBoot+Vue.jst0甘肃非物质文化网站(源码+LW文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

EVM系区块链开发网节点搭建及测试详细文档

文章目录 一. 编写说明1.1 文档说明1.2 配置信息二. docker 方式部署区块链开发网2.1 centos7 部署docker环境2.1.1 卸载旧版本2.1.2 使用 yum 安装2.1.3 使用官方安装脚本自动安装2.1.4 启动并加入开机启动2.2 区块链节点镜像生成2.3 区块链开发网节点容器生成2.3.1 配置文件编…

第4章 4.1 Entity Framework Core概述

4.1.1 什么是ORM ORM (object tralstional mapping ,对象关系映射)中的“对象”指的就是C#中的对象&#xff0c;而“关系”是关系型数据库&#xff0c;“映射”指搭建数据库与C#对象之间的“桥梁”。 比如使用ORM &#xff0c;可以通过创建C#对象的方式把数据插入数据库而不需…

关于Yudao(芋道)和Ruoyi(若依)两个开源框架的发布时间、功能定位以及当前发展情况

根据现有信息&#xff0c;关于Yudao&#xff08;芋道&#xff09;和Ruoyi&#xff08;若依&#xff09;两个开源框架的发布时间、功能定位以及当前发展情况&#xff0c;可以综合如下分析&#xff1a; 一、发布时间与先后顺序 Ruoyi&#xff08;若依&#xff09; Ruoyi框架的公开…

JavaScript实现一个函数,找出数组中重复出现次数最多的元素。

JavaScript实现一个函数&#xff0c;找出数组中重复出现次数最多的元素。 实现思路 要找出数组里重复出现次数最多的元素&#xff0c;咱们可以这么干&#xff1a; 先弄个“小账本”&#xff08;也就是一个对象&#xff09;&#xff0c;用来记录数组里每个元素出现的次数。接…

10. 九转金丹炼矩阵 - 矩阵置零(标记优化)

哪吒在数据修仙界中继续他的修炼之旅。这一次,他来到了一片神秘的金丹谷,谷中有一座巨大的九转金丹炉,炉身闪烁着神秘的光芒。金丹炉的入口处有一块巨大的石碑,上面刻着一行文字:“欲破此炉,需以九转金丹之力,炼矩阵之零,标记优化定乾坤。” 哪吒定睛一看,石碑上还有…

PostgreSQL vs MongoDB:优劣分析及适用场景

PostgreSQL vs MongoDB&#xff1a;优劣分析及适用场景 PostgreSQL 和 MongoDB 是两种非常不同的数据库系统&#xff0c;它们各自具有独特的优势和适用场景。以下是对这两种数据库的优劣分析及适用场景&#xff1a; PostgreSQL 优势&#xff1a; ACID 兼容性&#xff1a;Po…

出行项目案例

spark和kafka主要通过Scala实现&#xff0c;Hadoop和HBase主要基于java实现。 通过该项目&#xff0c;主要达到以下目的&#xff1a; &#xff08;1&#xff09;通用的数据处理流程&#xff0c;入门大数据领域 &#xff08;2&#xff09;真实体验大数据开发工程师的工作 &a…

PyEcharts 数据可视化:从入门到实战

一、PyEcharts 简介 PyEcharts 是基于百度开源可视化库 ECharts 的 Python 数据可视化工具&#xff0c;支持生成交互式的 HTML 格式图表。相较于 Matplotlib 等静态图表库&#xff0c;PyEcharts 具有以下优势&#xff1a; 丰富的图表类型&#xff08;30&#xff09;动态交互功…

五、Three.js顶点UV坐标、纹理贴图

一部分来自1. 创建纹理贴图 | Three.js中文网 &#xff0c;一部分是自己的总结。 一、创建纹理贴图 注意&#xff1a;把一张图片贴在模型上就是纹理贴图 1、纹理加载器TextureLoader 注意&#xff1a;将图片加载到加载器中 通过纹理贴图加载器TextureLoader的load()方法加…

使用postman测试api接口基本步骤

测试一个已写好的 API 接口需要系统性地验证其功能、性能、安全性及异常处理能力。以下是使用 Postman 进行 API 接口测试的详细步骤和注意事项&#xff1a; 1. 确认接口文档 明确输入输出&#xff1a;了解接口的请求方法&#xff08;GET/POST/PUT/DELETE&#xff09;、URL、请…

綫性與非綫性泛函分析與應用_1.例題(下)-半母本

第1章 實分析與函數論:快速回顧(下) 五、基數;有限集和無限集相關例題 例題1:集合基數的判斷 判斷集合和集合B=\{a,b,c,d,e\}的基數關係。 解析: 可以構造一個雙射,例如,,,,。 所以,兩個集合具有相同的基數。 例題2:可數集的證明 證明整數集是可數集。 解析: …

Windows系统第一次运行C语言程序,环境配置,软件安装等遇到的坑及解决方法

明确需要编辑器和编译器&#xff0c;并选择自己要用什么&#xff08;我选的编辑器是VSCode&#xff1a;Visual Studio Code&#xff1b;编译器是gcc&#xff09;下载VSCode并配置环境变量&#xff08;这里没啥问题&#xff09;&#xff0c;安装C/C的拓展安装Cygwin&#xff0c;…

浅拷贝和深拷贝的区别?可以举例说明

在编程中&#xff0c;浅拷贝和深拷贝是用于复制对象的两种不同方式&#xff0c;它们的主要区别在于复制对象时对对象内部成员的处理方式。今天我们对此进行讨论。 目录 1 浅拷贝 2 深拷贝 1 浅拷贝 浅拷贝创建一个新对象&#xff0c;新对象的属性值会复制原始对象的属性值…

微信小程序实现拉卡拉支付

功能需求&#xff1a;拉卡拉支付&#xff08;通过跳转拉卡拉平台进行支付&#xff09;&#xff0c;他人支付&#xff08;通过链接进行平台跳转支付&#xff09; 1.支付操作 //支付 const onCanStartPay async (obj) > {uni.showLoading({mask: true})// 支付接口获取需要传…

使用ESP-IDF来驱动INMP441全向麦克风

之前的文章我们讲过了I2S。 I2S是什么通信协议&#xff1f;它如何传输音频数据&#xff1f;它和I2C是什么关系&#xff1f;_i2c接口和i2s-CSDN博客文章浏览阅读836次&#xff0c;点赞12次&#xff0c;收藏14次。这个可以参考ADC来理解&#xff0c;我们的ADC也是有左对齐和右对…

MobaXterm_Portable_v23.2 免费下载与使用教程(附安卓替代方案)

一、MobaXterm_Portable 简介 MobaXterm 是一款功能强大的全能终端工具&#xff0c;支持 SSH、SFTP、RDP、VNC、X11 转发 等多种协议&#xff0c;集成了终端、文件传输、远程桌面等功能。其便携版&#xff08;Portable Edition&#xff09;无需安装&#xff0c;解压即可使用&a…

【带你 langchain 双排系列教程】6.LangChain多模态输入与自定义输出实战指南

一、为什么需要多模态交互&#xff1f; 在真实业务场景中&#xff0c;数据从来都不是单一形式的。想象一个智能客服系统需要同时分析用户的文字描述、上传的产品图片和语音留言&#xff0c;或者一个内容审核系统需要检查文本、图像和视频的组合内容。传统单一模态的处理方式已…

【Bluedroid】AVRCP 连接源码分析(三)

接着上一篇【Bluedroid】AVRCP 连接源码分析&#xff08;一&#xff09;-CSDN博客&#xff0c;继续AVRCP连接的源码分析。 AVRC_OpenBrowse /packages/modules/Bluetooth/system/stack/avrc/avrc_api.cc /*****************************************************************…