HarmonyOS 调用系统的AVRecorder相关API报错

​导入了media模块,创建了一个录像AVRecorder实例,然后在调用recorder的prepare方法时报错,错误code是5400106

相关的相机,麦克风权限已经授权过了;

这是prepare方法中传的config参数:​

{"audioSourceType":1,"videoSourceType":0,"profile":{"audioBitrate":48000,"audioChannels":2,"audioCodec":"audio/mp4a-latm","audioSampleRate":48000,"fileFormat":"mp4","videoBitrate":200000,"videoCodec":"video/avc","videoFrameWidth":1920,"videoFrameHeight":1080,"videoFrameRate":30},"url":"fd://121","rotation":0}

部分代码截图及报错截图在附件中。

HarmonyOS 调用系统的AVRecorder相关API报错-鸿蒙开发者社区

HarmonyOS 调用系统的AVRecorder相关API报错-鸿蒙开发者社区

HarmonyOS
2024-11-12 09:39:22
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
put_get

​5400106 不支持的规格 您可以根据此错误码在API文档全局搜索

错误信息

Unsupport format.

错误描述

不支持的规格。

可能原因

不支持的文件或者格式。

处理步骤

当前使用的格式规格不支持,需要您将文件切换为支持的规格。

以下内容为:

index.ets文件​

import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; 
import Logger from '../utils/Logger'; 
import common from '@ohos.app.ability.common'; 
import router from '@ohos.router' 
class routerParams { 
  text:string 
  data:string 
 
  constructor(str:string, data:string) { 
    this.text = str 
    this.data = data 
  } 
} 
const TAG: string = 'CAMERA_TAG'; 
@Entry 
@Component 
struct Index { 
  scroller: Scroller = new Scroller() 
  private controller: VideoController | undefined; 
  @State videosrc: string = ''; 
  @State path:string=""; 
  @State text:string=""; 
  permissions: Array<Permissions> = [ 
    'ohos.permission.CAMERA', 
    'ohos.permission.MICROPHONE', 
    'ohos.permission.WRITE_MEDIA', 
    'ohos.permission.READ_MEDIA', 
    'ohos.permission.MEDIA_LOCATION', 
  ]; 
  atManager = abilityAccessCtrl.createAtManager(); 
 
  onPageShow(){ 
    try{ 
 
      this.path=(router.getParams() as routerParams).data 
      console.log(this.path); 
    }catch (e){ 
      return; 
    } 
 
  } 
 
  //第1步:请求权限 
  async requestPermissions() : Promise<boolean>{ 
 
    return await new Promise((resolve: Function) => { 
      try { 
        let context = getContext() as common.UIAbilityContext; 
        this.atManager.requestPermissionsFromUser(context, this.permissions) 
          .then(async () => { 
            Logger.info(TAG, "权限请求成功") 
            resolve(true) 
          }).catch(() => { 
          Logger.info(TAG, "权限请求异常"); 
          resolve(false) 
        }); 
 
      } catch (err) { 
        Logger.info(TAG, "权限请求err:" + err) 
        resolve(false) 
      } 
    }); 
  } 
 
  build() { 
    Stack({ alignContent: Alignment.TopStart }) { 
      Scroll(this.scroller) { 
 
        Column() { 
          if (this.path) { 
            Video({ 
              src: "file://" + this.path, 
              controller: this.controller 
            }).height(300) 
          } 
 
          Button("录制视频") 
            .width('90%') 
            .height(45) 
            .backgroundColor('#0080FF') 
            .fontSize(16) 
            .fontColor(Color.White) 
            .margin({ top: 30 }) 
            .onClick(async () => { 
              let result = await this.requestPermissions(); 
              if(result) { 
                router.pushUrl({ url: "pages/Lx"}) 
              } 
            }) 
 
        }.width('100%') 
      } 
      .scrollable(ScrollDirection.Vertical) 
      .scrollBar(BarState.On) 
      .scrollBarColor(Color.Gray) 
      .scrollBarWidth(20) 
 
    }.width('100%').height('100%').backgroundColor(Color.White) 
  } 
}

​由router.pushUrl({ url: "pages/Lx"})行跳转带Lx.ets文件。

以下内容为Lx.ets文件​。

import camera from '@ohos.multimedia.camera'; 
import media from '@ohos.multimedia.media'; 
import { BusinessError } from '@ohos.base'; 
import common from '@ohos.app.ability.common'; 
import Logger from '../utils/Logger'; 
import router from '@ohos.router'; 
import { FileUtil } from '../utils/FileUtil'; 
 
import fileUri from '@ohos.file.fileuri'; 
 
const TAG: string = 'CAMERA_TAG'; 
 
 
 
/** 
 * 视频录制 
 */ 
 
 
class routerParams { 
  text:string 
  data:string 
  constructor(str:string, data:string) { 
    this.text = str 
    this.data = data 
  } 
} 
@Entry 
@Component 
struct Lx { 
  private mXComponentController: XComponentController = new XComponentController; 
  private surfaceId: string = ''; 
  //预览控件宽高 
  @State xComponentWidth: number = 0; 
  @State xComponentHeight: number = 0; 
  @State videoUri: string = ""; 
  url: string = ""; 
  @State recording: boolean = false;//正在录制视频 
  @State isFinished: boolean = false; 
  @State path:string =""; 
 
  @State cameraManager: camera.CameraManager | undefined =undefined; 
  @State videoOutput: camera.VideoOutput | undefined =undefined; 
  @State captureSession: camera.CaptureSession | undefined =undefined; 
  @State cameraInput: camera.CameraInput | undefined =undefined; 
  @State previewOutput: camera.PreviewOutput | undefined =undefined; 
  @State avRecorder: media.AVRecorder | undefined =undefined; 
 
 
  controller: VideoController = new VideoController(); 
 
 
  aboutToAppear() { 
    let context = getContext() as common.UIAbilityContext; 
    this.path = context.filesDir + "/" + "VIDEO_" + Date.parse(new Date().toString()) + ".mp4"; 
    let file = FileUtil.createOrOpen(this.path); 
    this.url = "fd://" + file.fd; 
    this.videoUri = fileUri.getUriFromPath(this.path); 
  } 
  build() { 
    Stack({ alignContent: Alignment.Top }) { 
      if (!this.isFinished) { 
        XComponent({ 
          id: 'componentId', 
          type: 'surface', 
          controller: this.mXComponentController, 
        }).onLoad(async () => { 
          this.surfaceId = this.mXComponentController.getXComponentSurfaceId(); 
 
          let baseContext = getContext() as common.BaseContext; 
          await this.initCamera(baseContext, this.surfaceId) 
        }).width('100%') 
          .height('100%') 
      } else { 
        Video({ 
          src: this.videoUri, 
          controller: this.controller 
        }).autoPlay(true) 
      } 
      Column() { 
        Button("返回", { type: ButtonType.Circle, stateEffect: false }) 
          .width(80) 
          .height(80) 
          .fontSize(16) 
          .fontColor('#ffffff') 
          .margin({ left: 20, top: 20 }) 
          .onClick(() => { 
            this.controller.stop(); 
            // this.stopRecord(); 
            let options: router.RouterOptions = { 
              url: '', 
              params: new routerParams("沙箱路径", this.path) 
            } 
            router.back(options); 
          }) 
        Blank() 
        if (!this.isFinished) { 
          Row() { 
            Button(this.recording ? "停止录制" : "开始录制", { type: ButtonType.Circle, stateEffect: false }) 
              .width(120) 
              .height(120) 
              .fontSize(20) 
              .margin({ left: 20 }) 
              .fontColor('#ffffff') 
              .onClick(() => { 
                if(this.recording) { 
                  this.stopRecord(); 
                }else { 
                  this.startRecord(); 
                } 
                this.recording = !this.recording; 
              }) 
          } 
          .width('100%') 
          .height(120) 
          .margin({ bottom: 60 }) 
          .justifyContent(FlexAlign.Center) 
          .alignItems(VerticalAlign.Center) 
        } 
      }.width('100%') 
      .height('100%') 
      .justifyContent(FlexAlign.Start) 
      .alignItems(HorizontalAlign.Start) 
 
    }.width('100%') 
    .height('100%') 
  } 
 
  //第1步:初始化照相机 
  async initCamera(baseContext: ESObject, surfaceId: string) { 
    this.cameraManager = camera.getCameraManager(baseContext); 
    if (!this.cameraManager) { 
      Logger.error(TAG, "camera.getCameraManager error"); 
      return; 
    } 
 
    //监听照相机状态变化 
    this.cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => { 
      Logger.info(TAG, `camera : "222222222222222"+${cameraStatusInfo.camera.cameraId}`); 
      Logger.info(TAG, `status: "11111111111"+${cameraStatusInfo.status}`); 
 
    }); 
    // 获取相机列表 
    let cameraArray: Array<camera.CameraDevice> = []; 
    try { 
      cameraArray = this.cameraManager.getSupportedCameras(); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`getSupportedCameras call failed. error code: ${err.code}`); 
    } 
 
    if (cameraArray.length <= 0) { 
      console.error("cameraManager.getSupportedCameras error"); 
      return; 
    } 
    for (let index = 0; index < cameraArray.length; index++) { 
      Logger.info(TAG, 'cameraId : ' + cameraArray[index].cameraId); // 获取相机ID 
      Logger.info(TAG, 'cameraPosition : ' + cameraArray[index].cameraPosition); // 获取相机位置 
      Logger.info(TAG, 'cameraType : ' + cameraArray[index].cameraType); // 获取相机类型 
      Logger.info(TAG, 'connectionType : ' + cameraArray[index].connectionType); // 获取相机连接类型 
    } 
 
    // 获取相机设备支持的输出流能力 
    let cameraOutputCap: camera.CameraOutputCapability = this.cameraManager.getSupportedOutputCapability(cameraArray[0]); 
    if (!cameraOutputCap) { 
      Logger.error(TAG, "cameraManager.getSupportedOutputCapability error"); 
      return; 
    } 
    Logger.info(TAG, "outputCapability: " + JSON.stringify(cameraOutputCap)); 
 
    //预览流与录像输出流的分辨率的宽高比要保持一致 
    let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles; 
 
    let position: number = 0; 
    if (previewProfilesArray != null) { 
      previewProfilesArray.forEach((value: camera.Profile, index: number) => { 
        Logger.info(TAG, `支持的预览尺寸: [${value.size.width},${value.size.height}]`); 
        if (value.size.width === 1920 && value.size.height === 1080) { 
          position = index; 
        } 
      }) 
    } else { 
      Logger.error(TAG, "createOutput photoProfilesArray == null || undefined"); 
    } 
 
    let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles; 
    if (!photoProfilesArray) { 
      Logger.error(TAG, "createOutput photoProfilesArray == null || undefined"); 
    } 
 
    this.xComponentWidth = previewProfilesArray[position].size.width; 
    this.xComponentHeight = previewProfilesArray[position].size.height; 
 
    this.mXComponentController.setXComponentSurfaceSize({ 
      surfaceWidth: previewProfilesArray[position].size.width, 
      surfaceHeight: previewProfilesArray[position].size.height 
    }); 
 
    let videoProfilesArray: Array<camera.VideoProfile> = cameraOutputCap.videoProfiles; 
    if (!videoProfilesArray) { 
      console.error("createOutput videoProfilesArray == null || undefined"); 
    } 
 
    let metadataObjectTypesArray: Array<camera.MetadataObjectType> = cameraOutputCap.supportedMetadataObjectTypes; 
    if (!metadataObjectTypesArray) { 
      console.error("createOutput metadataObjectTypesArray == null || undefined"); 
    } 
 
    // videoProfile的宽高需要与AVRecorderProfile的宽高保持一致,并且需要使用AVRecorderProfile锁支持的宽高 
    let videoSize: camera.Size = { 
      width: 640, 
      height: 480 
    } 
    let videoProfile: undefined | camera.VideoProfile = videoProfilesArray.find((profile: camera.VideoProfile) => { 
      return profile.size.width === videoSize.width && profile.size.height === videoSize.height; 
    }); 
 
    if (!videoProfile) { 
      console.error('videoProfile is not found'); 
      return; 
    } 
 
    // 配置参数以实际硬件设备支持的范围为准 
    let aVRecorderProfile: media.AVRecorderProfile = { 
      audioBitrate: 48000, 
      audioChannels: 2, 
      audioCodec: media.CodecMimeType.AUDIO_AAC, 
      audioSampleRate: 48000, 
      fileFormat: media.ContainerFormatType.CFT_MPEG_4, 
      videoBitrate: 2000000, 
      videoCodec: media.CodecMimeType.VIDEO_MPEG4, 
      videoFrameWidth: videoSize.width, 
      videoFrameHeight: videoSize.height, 
      videoFrameRate: 30 
    }; 
    let aVRecorderConfig: media.AVRecorderConfig = { 
      audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, 
      videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV, 
      profile: aVRecorderProfile, 
      url: this.url, // 文件需先由调用者创建,赋予读写权限,将文件fd传给此参数,eg.fd://45--file:///data/media/01.mp4 
      rotation: 0, // 合理值0、90、180、270,非合理值prepare接口将报错 
      location: { latitude: 30, longitude: 130 } 
    }; 
 
 
    try { 
      this.avRecorder = await media.createAVRecorder(); 
 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`createAVRecorder call failed. error code: ${err.code}`); 
    } 
 
    if (this.avRecorder === undefined) { 
      return; 
    } 
 
    try { 
      await this.avRecorder.prepare(aVRecorderConfig); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`prepare call failed. error code: ${err.code}`); 
    } 
 
    let videoSurfaceId: string | undefined = undefined; // 该surfaceID用于传递给相机接口创造videoOutput 
    try { 
      videoSurfaceId = await this.avRecorder.getInputSurface(); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`getInputSurface call failed. error code: ${err.code}`); 
    } 
    if (videoSurfaceId === undefined) { 
      return; 
    } 
    // 创建VideoOutput对象 
    try { 
      this.videoOutput = this.cameraManager.createVideoOutput(videoProfile, videoSurfaceId); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`Failed to create the videoOutput instance. error: ${JSON.stringify(err)}`); 
    } 
    if (this.videoOutput === undefined) { 
      return; 
    } 
    this.videoOutput.on('frameStart', () => { 
      console.info('Video frame started'); 
    }); 
    // 监听视频输出错误信息 
    this.videoOutput.on('error', (error: BusinessError) => { 
      console.log(`Preview output error code: ${error.code}`); 
    }); 
 
 
    //创建会话 
    try { 
      this.captureSession = this.cameraManager.createCaptureSession(); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error('Failed to create the CaptureSession instance. errorCode = ' + err.code); 
    } 
    if (this.captureSession === undefined) { 
      return; 
    } 
    // 监听session错误信息 
    this.captureSession.on('error', (error: BusinessError) => { 
      Logger.error(TAG, `Capture session error code: ${error.code}`); 
    }); 
 
    // 开始配置会话 
    try { 
      this.captureSession.beginConfig(); 
    } catch (error) { 
      let err = error as BusinessError; 
      Logger.error(TAG, 'Failed to beginConfig. errorCode = ' + err.code); 
    } 
 
    // 创建相机输入流 
    let cameraInput: camera.CameraInput | undefined = undefined; 
    try { 
      cameraInput = this.cameraManager.createCameraInput(cameraArray[0]); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`Failed to createCameraInput. error: ${JSON.stringify(err)}`); 
    } 
    if (cameraInput === undefined) { 
      return; 
    } 
    // 监听cameraInput错误信息 
    let cameraDevice: camera.CameraDevice = cameraArray[0]; 
    cameraInput.on('error', cameraDevice, (error: BusinessError) => { 
      console.log(`Camera input error code: ${error.code}`); 
    }); 
 
    // 打开相机 
    try { 
      await cameraInput.open(); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`Failed to open cameraInput. error: ${JSON.stringify(err)}`); 
    } 
    // 向会话中添加相机输入流 
    try { 
      this.captureSession.addInput(cameraInput); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`Failed to add cameraInput. error: ${JSON.stringify(err)}`); 
    } 
 
    // 创建预览输出流,其中参数 surfaceId 参考下面 XComponent 组件,预览流为XComponent组件提供的surface 
    let previewOutput: camera.PreviewOutput | undefined = undefined; 
    try { 
      previewOutput = this.cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`Failed to create the PreviewOutput instance. error: ${JSON.stringify(err)}`); 
    } 
 
    if (previewOutput === undefined) { 
      return; 
    } 
    // 向会话中添加预览输入流 
    try { 
      this.captureSession.addOutput(previewOutput); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`Failed to add previewOutput. error: ${JSON.stringify(err)}`); 
    } 
 
    // 向会话中添加录像输出流 
    try { 
      this.captureSession.addOutput(this.videoOutput); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`Failed to add videoOutput. error: ${JSON.stringify(err)}`); 
    } 
 
    // 提交会话配置 
    try { 
      await this.captureSession.commitConfig(); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`captureSession commitConfig error: ${JSON.stringify(err)}`); 
    } 
 
    // 启动会话 
    try { 
      await this.captureSession.start(); 
    } catch (error) { 
      let err = error as BusinessError; 
      console.error(`captureSession start error: ${JSON.stringify(err)}`); 
    } 
 
    // 启动录像输出流 
    this.videoOutput.start((err: BusinessError) => { 
      if (err) { 
        console.error(`Failed to start the video output. error: ${JSON.stringify(err)}`); 
        return; 
      } 
      console.log('Callback invoked to indicate the video output start success.'); 
    }); 
  } 
  //第2步:录制 
  async startRecord() { 
    if (this.avRecorder) { 
      console.log("6666666666") 
      console.log(this.avRecorder.state) 
      console.log("6666666666") 
      // 开始录像 
      try { 
        await this.avRecorder.start(); 
      } catch (error) { 
        let err = error as BusinessError; 
        console.log("8888888888888888888888888") 
        console.error(`avRecorder start error: ${JSON.stringify(err)}`); 
      } 
      console.log("7777777777777") 
      console.log(this.avRecorder.state) 
      console.log("7777777777777") 
    } 
 
  } 
 
  //第3步:停止录像 
  async stopRecord() { 
    if (this.avRecorder) { 
      console.log("99999999999999999999999999") 
      console.log(this.avRecorder.state) 
      console.log("999999999999999999999") 
      // 停止录像 
      try { 
        // 停止录像输出流 
 
        if (this.videoOutput){ 
          this.videoOutput.stop((err: BusinessError) => { 
            if (err) { 
              console.error(`Failed to stop the video output. error: ${JSON.stringify(err)}`); 
              return; 
            } 
            console.log('Callback invoked to indicate the video output stop success.'); 
          }); 
        } 
        // 停止录像 
        try { 
          await this.avRecorder.stop(); 
          await this.avRecorder.release(); 
        } catch (error) { 
          let err = error as BusinessError; 
          console.error(`avRecorder stop error: ${JSON.stringify(err)}`); 
          console.log("失败") 
        } 
      } catch (error) { 
        let err = error as BusinessError; 
        Logger.error(TAG, `avRecorder stop error: ${JSON.stringify(err)}`); 
      } 
      // 停止当前会话 
      try { 
        if (this.captureSession ) {this.captureSession.stop();} 
        // fs.closeSync(file); 
        // 释放相机输入流 
        if (this.cameraInput ) {this.cameraInput.close();} 
        // 释放预览输出流 
        if (this.previewOutput) {this.previewOutput.release();} 
        // 释放录像输出流 
        if (this.videoOutput) { 
          this.videoOutput.release(); 
        } 
        // 释放会话 
        if (this.captureSession) { 
          this.captureSession.release(); 
        } 
        // 会话置空 
        if (this.captureSession) { 
          this.captureSession = undefined; 
        } 
        this.isFinished = true; 
      }catch (error) { 
        let err = error as BusinessError; 
        Logger.error(TAG, `avRecorder stop error: ${JSON.stringify(err)}`); 
      } 
    } 
  } 
}

Lx文件中需要utils目录下的FileUtil.ets文件和Logger.ts文件。

以下为FileUtil.ets文件内容。

import fs from '@ohos.file.fs'; 
import buffer from '@ohos.buffer'; 
 
// 大小和单位 
const GB_MAGNITUDE: number = 1024 * 1024 * 1024 
const MB_MAGNITUDE: number = 1024 * 1024 
const KB_MAGNITUDE: number = 1024 
const GB_SYMBOL: string = 'GB' 
const MB_SYMBOL: string = 'MB' 
const KB_SYMBOL: string = 'KB' 
const BYTE_SYMBOL: string = 'B' 
 
export class FileUtil { 
  /** 
   * 新建并打开文件 
   */ 
  static createOrOpen(path: string) : fs.File{ 
    let isExist = fs.accessSync(path); 
    let file: fs.File; 
    if(isExist) { 
      file = fs.openSync(path, fs.OpenMode.READ_WRITE); 
    }else { 
      file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) 
    } 
    return file; 
  } 
  /** 
   * 保存arrayBuffer到文件 
   * @param path 
   * @param arrayBuffer 
   * @returns 
   */ 
  static writeBufferToFile(path: string, arrayBuffer: ArrayBuffer): number { 
 
    try { 
      let file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 
      let value = fs.writeSync(file.fd, arrayBuffer); 
      fs.closeSync(file); 
      return value; 
    }catch (err){ 
      console.log("FileUtil", "writeFile err:" + err); 
      return -1; 
    } 
  } 
  /** 
   * 保存文本到文件 
   * @param path 
   * @param text 
   * @returns 
   */ 
  static writeStrToFile(path: string, text: string): number { 
    try { 
      let file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 
      let value = fs.writeSync(file.fd, text); 
      fs.closeSync(file); 
      return value; 
    }catch (err) { 
      console.log("FileUtil", "writeFile err:" + err); 
      return -1; 
    } 
  } 
}

以下为Logger.ts文件内容。

import hilog from '@ohos.hilog'; 
 
class Logger { 
  private domain: number; 
  private prefix: string; 
  private format: string = "%{public}s, %{public}s"; 
 
  constructor(prefix: string) { 
    this.prefix = prefix; 
    this.domain = 0xFF00; 
  } 
 
  debug(...args: any[]) { 
    hilog.debug(this.domain, this.prefix, this.format, args); 
  } 
 
  info(...args: any[]) { 
    hilog.info(this.domain, this.prefix, this.format, args); 
  } 
 
  warn(...args: any[]) { 
    hilog.warn(this.domain, this.prefix, this.format, args); 
  } 
 
  error(...args: any[]) { 
    hilog.error(this.domain, this.prefix, this.format, args); 
  } 
} 
 
export default new Logger('[Sample_Camera]');

另需在module.json5中配置以下内容:

ohos.permission.CAMERA、 
ohos.permission.MICROPHONE、 
ohos.permission.MEDIA_LOCATION、
分享
微博
QQ
微信
回复
2024-11-12 15:55:37
相关问题
HarmonyOS 应用内录屏相关API
193浏览 • 1回复 待解决
AVRecorder 支持文件类型
1515浏览 • 1回复 待解决
HarmonyOS 视频压缩没有相关api
402浏览 • 1回复 待解决
获取HarmonyOS系统版本api
356浏览 • 1回复 待解决
HarmonyOS操作系统相关问题
393浏览 • 1回复 待解决
HarmonyOS API调用崩溃问题
454浏览 • 1回复 待解决
HarmonyOS 元服务各种API报错
296浏览 • 1回复 待解决
webview如何调用webRTC相关功能
1335浏览 • 1回复 待解决
HarmonyOS 获取系统相册报错
224浏览 • 1回复 待解决
HarmonyOS app调用打电话功能报错
263浏览 • 1回复 待解决
HarmonyOS拍照后调用openSync方法报错
575浏览 • 1回复 待解决
HarmonyOS API调用与Dialog弹框
247浏览 • 0回复 待解决
HarmonyOS 使用华为登录API 报错1001500001
472浏览 • 1回复 待解决