背景

在聊天软件中,发送相册中视频和照片、用相机拍摄视频和图片发送是很常用的功能。在Android和iOS端,大部分应用都通过API方式定义UI来实现相册选择照片、视频,相机拍摄照片、视频,它们一般都支持以下功能:

  1. 相册选择:
    1. 支持单选或多选;
    2. 对图片支持是否原图选择;
    3. 对于视频支持选择视频的文件大小、视频时长等过滤;
    4. 支持点击图像放大预览
  2. 对于相机拍摄
    1. 支持点击拍照,长按录制视频;
    2. 视频录制支持最大最小录制时长限制;
    3. 拍摄或录制结束后支持预览。

对于鸿蒙应用要实现上述功能,系统也提供了对应API,要实现上述功能需要几个系统权限:

3. 读取系统相册权限
4. 麦克风权限
5. 摄像头权限

HarmonyOS 权限系统介绍

与Android系统相比,HarmonyOS提供了更严谨的权限控制,这里不得不提HarmonyOS的应用权限管控策略。HarmonyOS 提供了一种允许应用访问系统资源(如:通讯录等)和系统能力(如:访问摄像头、麦克风等)的通用权限访问方式,来保护系统数据(包括用户个人数据)或功能,避免它们被不当或恶意使用,应用权限保护的对象可以分为数据和功能:

  • 数据包括个人数据(如照片、通讯录、日历、位置等)、设备数据(如设备标识、相机、麦克风等)。
  • 功能包括设备功能(如访问摄像头/麦克风、打电话、联网等)、应用功能(如弹出悬浮窗、创建快捷方式等)。

同时HarmonyOS 根据授权方式的不同,权限类型可分为system_grant(系统授权)和user_grant(用户授权):

  • system_grant(系统授权)指的是系统授权类型,在该类型的权限许可下,应用被允许访问的数据不会涉及到用户或设备的敏感信息,应用被允许执行的操作对系统或者其他应用产生的影响可控。如果在应用中申请了system_grant权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。
  • user_grant(用户授权)指的是用户授权类型,在该类型的权限许可下,应用被允许访问的数据将会涉及到用户或设备的敏感信息,应用被允许执行的操作可能对系统或者其他应用产生严重的影响。该类型权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。

例如,在应用权限列表中,麦克风和摄像头对应的权限都是属于用户授权权限,列表中给出了详细的权限使用理由。应用需要在应用商店的详情页面,向用户展示所申请的user_grant权限列表。

除了授权方式外还要了解另一个概念APL(Ability Privilege Level,元能力权限等级)等级。应用的等级可以分为以下三个等级,等级依次提高。

APL级别说明
normal默认情况下,应用的APL等级都为normal等级。
system_basic该等级的应用服务提供系统基础服务。
system_core该等级的应用服务提供操作系统核心能力。
应用APL等级不允许配置为system_core。

根据权限对于不同等级应用有不同的开放范围,权限类型对应分为以下三个等级,等级依次提高。

APL级别说明开放范围
normal允许应用访问超出默认规则外的普通系统资源,如配置Wi-Fi信息、调用相机拍摄等。这些系统资源的开放(包括数据和功能)对用户隐私以及其他应用带来的风险低。APL等级为normal及以上的应用。
system_basic允许应用访问操作系统基础服务(系统提供或者预置的基础功能)相关的资源,如系统设置、身份认证等。这些系统资源的开放对用户隐私以及其他应用带来的风险较高。1、APL等级为system_basic及以上的应用。2、部分权限对normal级别的应用受限开放,这部分权限在本指导中描述为“受限开放权限”。
system_core涉及开放操作系统核心资源的访问操作。这部分系统资源是系统最核心的底层服务,如果遭受破坏,操作系统将无法正常运行。1、 APL等级为system_core的应用。2、 仅对系统应用开放。

访问操作系统基础服务(系统提供或者预置的基础功能)相关的资源,如系统设置、身份认证等。这些系统资源的开放对用户隐私以及其他应用带来的风险较高。    1、APL等级为system_basic及以上的应用。2、部分权限对normal级别的应用受限开放,这部分权限在本指导中描述为“受限开放权限”。
system_core    涉及开放操作系统核心资源的访问操作。这部分系统资源是系统最核心的底层服务,如果遭受破坏,操作系统将无法正常运行。    1、 APL等级为system_core的应用。2、 仅对系统应用开放。
了解了授权方式和权限等级后,我们再来聊聊这个设计背后的原因。
首先聊聊授权方式,其中系统授权类似于Android中的普通权限申请,在清单文件声明即可,对于用户授权,类似于Android中的动态权限,需要触发弹窗让用户感知后决定是否授权。这个涉及背后的逻辑很清晰,对于数据不会涉及到用户或设备的敏感信息(比如使用网络、使用蓝牙等),默认声明后授权不会对系统产生什么破坏,如果也强制用户感知授权后才可以使用,对于开发者来说增加工作量,对用户体验也不是很友好;
其次,对于权限等级,HarmonyOS分成了三类,normal 级别的,即普通应用应用可以使用的权限,比如相机,麦克风等,只要说明使用的场景即可向用户申请;system_core级别的是只有系统应用可以使用,普通应用无法申请,如果普通应用使用可能会对系统造成不可修复的错误,比如类似Android的root权限,如果普通应用申请到后,删除了系统核心文件等,系统会遭到破坏;第三种是system_basic,主要对系统应用开发,对普通应用受限开放,什么是受限开放呢?比如说读取相册权限,如果授权给普通应用,用户赋予它这个权限后,它偷偷的将相册数据传送到应用服务端用户完全无法感知,但是对于一些应用,比如网盘、相册备份类应用,没有这个权限还无法工作,所以系统设计时考虑到这一点,对于特殊的应用向平台申请后,平台根据应用类型给特殊应用放开该权限。可能有人会疑惑,为什么读取相册的是受限,而相机、麦克风是normal权限,因为麦克风、相机无法在用户无感知时使用,而读取文件可以。

回到正题,选择图片视频需要system_basic 受限权限,麦克风相机也需要用户授权,为了减少授权导致的操作流程终端,HarmonyOS 提供了系统Picker,可以使用系统组件再不需要权限的情况下完成功能。
应用拉起系统Picker组件(文件选择器、照片选择器、联系人选择器等),由用户在Picker上选择对应的文件、照片、联系人等资源,应用即可获取到Picker的返回结果,系统Picker由系统独立进程实现,从系统Picker获取资源是一个跨进程调度过程。

为什么使用系统Picker获取资源不需要权限?因为从系统Picker获取资源需要用户操作,是用户可以感知的,所以不需要再申请权限。注意,此时应用获取到的读取资源的权限是临时的,受限的,只能临时受限访问对应的资源。我们从Picker里选择了1.jpeg,在我们应用进程可以操作这个文件,我们从系统相册中获取到另一个2.jpeg文件,在进程里直接访问是不可以的,而且对1.jpeg的访问也是有时效性的。

接下来介绍如何基于系统API,从相册选择照片和视频,以及从相机拍摄视频和照片。

从相册选择

HarmonyOS 提供了 photoAccessHelper.PhotoViewPicker() 获取系统相册中的图片,下面是使用PhotoViewPicker的示例:

import { BusinessError } from '@kit.BasicServicesKit';
async function example01() {try {let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;PhotoSelectOptions.maxSelectNumber = 5;let photoPicker = new photoAccessHelper.PhotoViewPicker();photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult) => {console.info('PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult));}).catch((err: BusinessError) => {console.error(`PhotoViewPicker.select failed with err: ${err.code}, ${err.message}`);});} catch (error) {let err: BusinessError = error as BusinessError;console.error(`PhotoViewPicker failed with err: ${err.code}, ${err.message}`);}
}

这里面涉及到两个对象PhotoSelectOptions和PhotoSelectResult,分别表示跳转到图片选择器的参数,和选择完返回的结果。
PhotoSelectOptions有一下三个参数:

名称类型必填说明
isEditSupported11+boolean是否支持编辑照片,true表示支持,false表示不支持,默认为true。
isOriginalSupported12+boolean是否显示选择原图按钮,true表示显示,false表示不显示,默认为true。

元服务API: 从API version 12开始,该接口支持在元服务中使用。
subWindowName12+string子窗窗口名称。

元服务API: 从API version 12开始,该接口支持在元服务中使用。


PhotoSelectOptions 继承自BaseSelectOptions,提供了以下配置:

名称类型必填说明
MIMEType10+PhotoViewMIMETypes可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。

元服务API: 从API version 11开始,该接口支持在元服务中使用。
maxSelectNumber10+number选择媒体文件数量的最大值(最大可设置的值为500,若不设置则默认为50)。

元服务API: 从API version 11开始,该接口支持在元服务中使用。
isPhotoTakingSupported11+boolean是否支持拍照,true表示支持,false表示不支持,默认为true。

元服务API: 从API version 11开始,该接口支持在元服务中使用。
isSearchSupported11+boolean是否支持搜索,true表示支持,false表示不支持,默认为true。

元服务API: 从API version 11开始,该接口支持在元服务中使用。
recommendationOptions11+RecommendationOptions图片推荐相关配置参数。

元服务API: 从API version 11开始,该接口支持在元服务中使用。
preselectedUris11+Array<string>预选择图片的uri数据。

元服务API: 从API version 11开始,该接口支持在元服务中使用。
isPreviewForSingleSelectionSupported12+boolean单选模式下是否需要进大图预览,true表示需要,false表示不需要,默认为true。

元服务API: 从API version 12开始,该接口支持在元服务中使用。


综合上述配置说明,通过PhotoViewPicker可以实现最开始我们提到的:

  1. 支持选择图片和视频
  2. 支持设置最多选择媒体数量
  3. 支持是否选择原图
    不支持选择视频的最大最小长度配置。

看到这如果还有不知道从哪里开始入手了解鸿蒙开发技术、想要更深的掌握鸿蒙开发技术知识点的朋友们,或者是转行求职人员还在为面试问题而犯难的,可以动动手指进来参考一下针对‌鸿蒙开发学习‌而设计的系统性学习方案,涵盖基础入门到进阶实战项目相关学习文档:【鸿蒙开发学习指南】https://docs.qq.com/doc/DSk9ZeU9RTUhETm53

PhotoSelectResult是返回图库选择后的结果集,结构如下:

名称类型可读可写说明
photoUrisArray<string>返回图库选择后的媒体文件的uri数组,此uri数组只能通过临时授权的方式调用photoAccessHelper.getAssets接口去使用,具体使用方式参见用户文件uri介绍中的媒体文件uri的使用方式。
isOriginalPhotoboolean返回图库选择后的媒体文件是否为原图。

返回用户选中的媒体列表和是否选中原图。这里产生一个问题,如果既有选择视频又有选择图片,如何根据一个uri判断是视频还是图片?
这里有用到photoAccessHelper 来解析媒体信息,下面是一个方法封装:

public async uriGetAssets(uri:string): Promise<photoAccessHelper.PhotoAsset|undefined> {  try {  let context = getContext(this) as common.UIAbilityContext;  let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);  let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();  // 配置查询条件,使用PhotoViewPicker选择图片返回的uri进行查询  predicates.equalTo('uri', uri);  let fetchOption: photoAccessHelper.FetchOptions = {  fetchColumns: [photoAccessHelper.PhotoKeys.WIDTH, photoAccessHelper.PhotoKeys.HEIGHT, photoAccessHelper.PhotoKeys.TITLE, photoAccessHelper.PhotoKeys.DURATION],  predicates: predicates  };  let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOption);  // 得到uri对应的PhotoAsset对象,读取文件的部分信息  const asset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();  Logg.i(TAG, 'asset displayName: ' + asset.displayName);  Logg.i(TAG, 'asset uri: '+asset.uri);  Logg.i(TAG, 'asset photoType: ' + asset.photoType);  Logg.i(TAG, 'asset width: ' +  asset.get(photoAccessHelper.PhotoKeys.WIDTH));  Logg.i(TAG, 'asset height: ' +  asset.get(photoAccessHelper.PhotoKeys.HEIGHT));  Logg.i(TAG, 'asset title: '  +  asset.get(photoAccessHelper.PhotoKeys.TITLE));  return asset;  } catch (error){  Logg.e(TAG, 'uriGetAssets failed with err: ' + JSON.stringify(error));  }  return undefined;  
}

FetchOptions用来配置要查询的媒体信息内容,比如长、宽等信息,其中photoAccessHelper.PhotoAsset的photoType表示媒体类型,是音频还是视频。

接下里我们再介绍另一个能力,如果是视频的话有时候想要获取视频封面,即Thumbnail,photoAccessHelper.PhotoAsset提供了查询封面的接口:getThumbnail(),返回的是一个pixelMap,如何将pixelMap转换成图像呢?在pixelMap文档里看到从pixelMap读取buffer的方法:

import { BusinessError } from '@kit.BasicServicesKit';
async function Demo() {const readBuffer: ArrayBuffer = new ArrayBuffer(96); // 96为需要创建的像素buffer大小,取值为:height * width *4if (pixelMap != undefined) {pixelMap.readPixelsToBuffer(readBuffer, (error: BusinessError, res: void) => {if(error) {console.error(`Failed to read image pixel data. code is ${error.code}, message is ${error.message}`);// 不符合条件则进入return;} else {console.info('Succeeded in reading image pixel data.');  //符合条件则进入}})}
}

上面ArrayBuffer需要指定大小,将前面获取到的宽高相乘再乘以4即可。将获取到的readBuffer写入文件发现图片不是正常的图片,这里又需要用到image.createImagePacker():

let imagePath:string|undefined = undefined;  
let pixelMap = await matedata.getThumbnail();  
Logg.i(this.TAG, 'getThumbnail successful ' + JSON.stringify(pixelMap));  
let cacheDir = getContext().cacheDir;  
imagePath = `${cacheDir}/thumbnail${Date.now()}.jpg`;  
let dstFile = fs.openSync(imagePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);  
let packOpts: image.PackingOption = { format: "image/jpeg", quality: 98 };  
await image.createImagePacker().packToFile(pixelMap, dstFile.fd, packOpts)  
fs.close(dstFile);  
Logg.i(this.TAG, "copy file success");

需用用createImagePacker将pixelMap写入到目标文件,并且指定图片格式和质量。

从相机拍摄

上面实现了从相册获取照片,接下来实现使用摄像机拍照和拍视频功能。
有两种方式可以实现打开系统相机进行拍摄。

Want
下面是示例代码:

invokeCamera(callback: (uri: string) => void) {  const context = getContext(this) as common.UIAbilityContext;  const want: Want = {  action: 'ohos.want.action.imageCapture',  parameters: {  "callBundleName": context.abilityInfo.bundleName,  }  };  const result: (error: BusinessError, data: common.AbilityResult) => void =  (error: BusinessError, data: common.AbilityResult) => {  if (error && error.code !== 0) {  console.log(`${TAG_CAMERA_ERROR} ${JSON.stringify(error.message)}`)  return;  }  // 获取相机拍照后返回的图片地址  const resultUri: string = data.want?.parameters?.resourceUri as string;  if (callback && resultUri) {  callback(resultUri);  }  }  context.startAbilityForResult(want, result);  
}

通过want意图对象打开相机界面,参考 如何调用系统拍照并获取图片,这种方式无法设置录制视频最大长度等。

cameraPicker
相机选择器使用示例:

import { cameraPicker as picker } from '@kit.CameraKit';
import { camera } from '@kit.CameraKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
let mContext = getContext(this) as common.Context;async function demo() {try {let pickerProfile: picker.PickerProfile = {cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK};let pickerResult: picker.PickerResult = await picker.pick(mContext,[picker.PickerMediaType.PHOTO, picker.PickerMediaType.VIDEO], pickerProfile);console.log("the pick pickerResult is:" + JSON.stringify(pickerResult));} catch (error) {let err = error as BusinessError;console.error(`the pick call failed. error code: ${err.code}`);}
}

示例中mediaTypes数组指定了媒体格式,可以包含视频和图片;PickerProfile指定了摄像头是前置还是后置,主要有一下属性:

名称类型必填说明
cameraPositioncamera.CameraPosition相机的位置。
saveUristring保存配置信息的uri。
videoDurationnumber录制的最大时长。


PickerResult是相机选择器的处理结果,有一下属性:

名称类型必填说明
resultCodenumber处理的结果,成功返回0,失败返回-1。
resultUristring返回的uri地址。若saveUri为空,resultUri为公共媒体路径。若saveUri不为空且具备写权限,resultUri与saveUri相同。若saveUri不为空且不具备写权限,则无法获取到resultUri。
mediaTypePickerMediaType返回的媒体类型。


根据返回结果中mediaType来表示是图片还是视频,按照不同媒体类型处理即可。

总结

本文介绍了HarmonyOS Next中图片视频选择、图片视频拍摄的能力,重点分析了无需权限即可实现的photoAccessHelper和cameraPicker组件。

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

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

相关文章

iOS 网络请求断连重试失败?抓包分析丢包原因的完整流程

在移动 App 的开发中&#xff0c;中断网络环境&#xff08;如切换到飞行模式再回网&#xff09;后&#xff0c;App 在重连过程中有时会出现请求未重新发送或丢包的情况。这类问题难重现、难定位&#xff0c;尤其在 iOS 平台上更容易被忽视。我们最近就遇到一个用户反馈“切换网…

使用 DHTMLX Gantt 添加迷你地图:提升大型项目可视化与导航体验

在应对数千个任务构成的大型项目时&#xff0c;DHTMLX Gantt 以其卓越的性能表现和流畅渲染能力广受欢迎。然而&#xff0c;在实际使用中&#xff0c;终端用户往往需要快速定位到时间线中的特定位置&#xff0c;这在面对庞杂任务结构时尤为困难。为此&#xff0c;DHTMLX 提供了…

ROM修改进阶教程------用于自启脚本来打开系统的一些常用开关等指令 备份收藏 【一】

在定制化rom中。有很多项目需要反编译系统的相关应用来实现。但有些功能项完全可以使用指令来更改。那么结合自启脚本就可以很方便的来实现很多功能。网络虽然有很多类似的指令,但一些相关定制化项目的指令很少见而且不全面。此博文将全面收录此类指令。方便rom修改用户借鉴参…

腾讯云TSE注册中心实战:Nacos高可用集群搭建与流量治理避坑指南

1. 为什么选择腾讯云TSE托管Nacos&#xff1f; 在微服务架构中&#xff0c;注册中心承担着服务发现与配置管理的核心职能。Nacos作为阿里开源的动态服务发现组件&#xff0c;已成为国内微服务生态的事实标准。腾讯云微服务引擎TSE&#xff08;Tencent Cloud Service Engine&am…

领域驱动设计(DDD)【26】之CQRS模式初探

文章目录 一 CQRS初探&#xff1a;理解基本概念1.1 什么是CQRS&#xff1f;1.2 CQRS与CRUD的对比1.3 为什么需要CQRS&#xff1f; 二 CQRS深入&#xff1a;架构细节2.1 基本架构组成2.2 数据流示意图 三 CQRS实战&#xff1a;电商订单案例3.1 传统CRUD方式的订单处理3.2 CQRS方…

项目测试-接口测试

软件测试的分类 软件测试主要分硬件和软件 硬件测试: cpu,内存条,显卡...测试可以看得见摸得着的东西 软件测试: web,app,小程序... 测试可以看得见摸不着的东西 web端 web端是在电脑上常常使用的, 也可以称之为网站.(web端是B/S架构) web端的客户端是任何一个访问这个网…

相机的光圈

光圈&#xff08;Aperture&#xff09;是镜头中一个控制光线进入相机的开口&#xff0c;它在摄影中起着至关重要的作用。光圈的大小决定了进入相机传感器的光线数量&#xff0c;并影响曝光、景深、以及拍摄效果。光圈参数通常用f/值&#xff08;光圈值&#xff09;来表示&#…

HarmonyOS NEXT仓颉开发语言实战案例:小而美的旅行App

大家周末好&#xff0c;本文分享一个小而美的旅行app首页&#xff0c;效果图如下&#xff1a; 很显然这个页面还是使用List容器&#xff0c;页面两侧有统一的边距&#xff0c;我们可以在List容器统一设置&#xff1a; List(space:20){ } .padding(left:14,right:14,top:62) .w…

Python银行管理系统01升级(适合初学者)

目录 框架如下: 1. Account类 - 账户数据模型 2. Bank类 - 银行业务逻辑 3. BankApp类 - 图形用户界面 关键概念解析(适合初学者) 1. 面向对象编程(OOP)概念 2. Tkinter GUI编程基础 3. 数据持久化 4. 输入验证 学习建议 系统功能概览 完整代码: 在Python银行…

华为防火墙双向NAT实验

如图所示&#xff0c; 企业内网有一台Server2&#xff0c;通过在FW1上配置nat server&#xff0c;将Server2的www端口映射到了公网&#xff1b; 实验环境中&#xff0c;内网和外网都使用外网的server1提供的DNS服务&#xff0c;在DNS服务器上添加A记录&#xff0c;www.baidu.c…

前端路由的基石:深度剖析 Hash 与 History 模式的本质差异与实战抉择

在单页面应用&#xff08;SPA&#xff09;统治现代Web开发的今天&#xff0c;前端路由已成为构建流畅用户体验的核心技术。而hash和history作为两种主流实现方案&#xff0c;其设计理念和技术细节的差异直接影响着应用架构的选择。本文将深入解析二者的技术本质&#xff0c;通过…

微机系统 - 绪论

绪论: 一:微处理器,微型计算机和微型计算机系统: 分类: 按照系统结构和基本工作原理.计算机分为5大部分:运算器,控制器,存储器,输入设备,输出设备 按照体积,性能和价格分5类:巨型机,大型机,中型机,小型机,微型计算机(单板机,单片机) 微型计算机的特点:集成度高,体积小,重量轻…

基于Java+Springboot的宠物健康咨询系统

源码编号&#xff1a;S564 源码名称&#xff1a;基于Springboot的宠物健康咨询系统 用户类型&#xff1a;多角色&#xff0c;用户、顾问、管理员 数据库表数量&#xff1a;12 张表 主要技术&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven 运行环境&#xff1a;Win…

SpringBoot+MySQL宠物猫店管理系统

概述 基于SpringBootMySQL开发的宠物猫店管理系统完整源码。该系统功能完善&#xff0c;包含前后台完整功能模块&#xff0c;代码规范易于二次开发&#xff0c;是学习SpringBoot项目实战的优秀范例。 主要内容 前台功能展示 系统前台设计简洁实用&#xff0c;主要包含以下核…

UE5 - 制作《塞尔达传说》中林克的技能 - 16 - 遥控炸弹(一)

让我们继续《塞尔达传说》中林克技能的制作&#xff01;&#xff01;&#xff01; 本章节的核心目标&#xff1a;素材导入与遥控炸弹的外观 先让我们看一下完成后的效果&#xff1a; 基本流程&#xff1a;素材准备->C类开发->蓝图配置->场景部署 1.素材准备&#xff1…

HTTP中常见的Content-Type

Content-Type&#xff0c;也称为互联网媒体类型或MIME类型&#xff0c;是HTTP协议中的一个头部字段&#xff0c;用于指定处理请求和响应中的媒体类型信息。它告诉服务器如何处理请求的数据&#xff0c;同时也指导客户端&#xff08;通常是浏览器&#xff09;如何解析响应的数据…

Android11 wifi开启源码分析

目录 一、APP层源码分析 1.1、寻找页面activity 1.2、寻找页面开关按钮布局 二&#xff0c;framework层代码分析 2.1 开启wifi入口 2.2 WiFiNative 三&#xff0c;HAL层代码分析 这段时间撸了WIFI开启流程源码&#xff0c;本着前人栽树后人乘凉的原则&#xff0c;有志于…

R语言使用nonrandom包进行倾向评分匹配

倾向评分匹配&#xff08;Propensity Score Matching&#xff0c;简称PSM&#xff09;是一种统计学方法&#xff0c;用于处理观察研究&#xff08;Observational Study&#xff09;的数据&#xff0c;在SCI文章中应用非常广泛。在观察研究中&#xff0c;由于种种原因&#xff0…

LeetCode Hot 100 找到字符串中所有字母异位词

给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "a…

关于庐山派多视频层(layer)和bind_layer的应用

嘉立创分了适配层和OSD&#xff08;我称它为图片层&#xff09;顾名思义&#xff0c;一个是能显示视频流到LCD屏幕&#xff0c;一个是只能显示照片&#xff0c;也就是你可以对不同层进行操作而不影响其他层&#xff0c;解决的场景就是用于你画了一个正方形在照片上&#xff0c;…