复制直接用!鸿蒙模拟器Arkts获取相册权限,保存图片到沙箱

import fileIo from '@ohos.fileio';
import photoAccessHelper from '@ohos.file.photoAccessHelper';
import fileUri from '@ohos.file.fileuri';
import promptAction from '@ohos.promptAction';
import image from '@ohos.multimedia.image';
import componentSnapshot from '@ohos.componentSnapshot';
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common';

@Component
export struct SaveImageComponent {
  private controller: CustomDialogController;
  
  // 需要申请的权限
  private readonly requiredPermissions: Permissions[] = [
    'ohos.permission.READ_IMAGEVIDEO', 
    'ohos.permission.WRITE_IMAGEVIDEO'
  ];

  async saveImage() {
    try {
      // 1. 申请必要权限
      await this.requestPermissions();
      
      // 2. 截图并转换为二进制流
      const arrayBuffer = await this.captureComponent();
      
      // 3. 保存图片到应用沙箱
      const imagePath = await this.saveToSandbox(arrayBuffer);
      
      // 4. 保存到系统相册
      await this.saveToGallery(imagePath);
      
      // 5. 显示成功提示
      promptAction.showToast({ 
        message: '图片保存成功', 
        duration: 2000 
      });
      
    } catch (error) {
      console.error('图片保存失败:', JSON.stringify(error));
      promptAction.showToast({ 
        message: `保存失败: ${error.message || '未知错误'}`, 
        duration: 3000 
      });
    } finally {
      // 无论成功失败都关闭弹窗
      this.controller.close();
    }
  }

  // 申请必要权限
  private async requestPermissions(): Promise<void> {
    try {
      const context = getContext(this) as common.UIAbilityContext;
      const atManager = abilityAccessCtrl.createAtManager();
      
      const grantStatus = await atManager.requestPermissionsFromUser(
        context, 
        this.requiredPermissions
      );
      
      // 检查所有权限是否都授予
      const allGranted = this.requiredPermissions.every(permission => {
        return grantStatus.authResults[permission] === 0;
      });
      
      if (!allGranted) {
        throw new Error('所需权限未完全授予');
      }
    } catch (error) {
      console.error('权限申请失败:', JSON.stringify(error));
      throw new Error('权限不足,无法保存图片');
    }
  }

  // 截图组件并转换为二进制流
  private async captureComponent(): Promise<ArrayBuffer> {
    try {
      const imgMsg = await componentSnapshot.get('share');
      const imagePacker = image.createImagePacker();
      return await imagePacker.packToData(imgMsg, {
        format: 'image/jpeg', 
        quality: 98
      });
    } catch (error) {
      console.error('截图失败:', JSON.stringify(error));
      throw new Error('截图生成失败');
    }
  }

  // 保存图片到应用沙箱
  private async saveToSandbox(arrayBuffer: ArrayBuffer): Promise<string> {
    let fileFd: number | null = null;
    
    try {
      const context = getContext(this);
      const timestamp = new Date().getTime();
      const imagePath = `${context.cacheDir}/screenshot_${timestamp}.jpeg`;
      
      // 创建文件并获取文件描述符
      fileFd = fileIo.openSync(imagePath, 
        fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE
      );
      
      // 写入数据
      const bytesWritten = fileIo.writeSync(fileFd, arrayBuffer);
      
      if (bytesWritten <= 0) {
        throw new Error('图片写入失败');
      }
      
      return imagePath;
    } catch (error) {
      console.error('沙箱保存失败:', JSON.stringify(error));
      throw new Error('图片保存到临时位置失败');
    } finally {
      // 确保文件描述符关闭
      if (fileFd !== null) {
        fileIo.closeSync(fileFd);
      }
    }
  }

  // 保存到系统相册
  private async saveToGallery(imagePath: string): Promise<void> {
    try {
      const context = getContext(this);
      const uri = fileUri.getUriFromPath(imagePath);
      
      // 创建图片保存请求
      const photoRequest = 
        photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(context, uri);
      
      if (!photoRequest) {
        throw new Error('创建图片保存请求失败');
      }
      
      const photoHelper = photoAccessHelper.getPhotoAccessHelper(context);
      
      // 应用更改(保存图片)
      await photoHelper.applyChanges([photoRequest]);
      
    } catch (error) {
      console.error('保存到相册失败:', JSON.stringify(error));
      throw new Error('图片保存到相册失败');
    }
  }
}

添加权限申请​​:在 module.json5 中添加:

"requestPermissions": [
  {
    "name": "ohos.permission.READ_IMAGEVIDEO"
  },
  {
    "name": "ohos.permission.WRITE_IMAGEVIDEO"
  }
]

 在UI中使用​​:

@Entry
@Component
struct MyComponent {
  private saveDialogController: CustomDialogController | null = null;
  
  build() {
    Button('保存图片')
      .onClick(() => {
        this.saveDialogController = new CustomDialogController({
          builder: SaveImageComponent({ controller: this.saveDialogController }),
        });
        this.saveDialogController.open();
      })
  }
}

简写(权限需要自己配置)

controller: CustomDialogController
async saveImage(){
   //1.截图组件变成二进制流
    //1.1 组件信息
    //除了id要改其他的代码都可以原封不动的复用
    const imgMsg = await componentSnapshot.get('share')
    //1.2 创建imagePacker对象实例
    const imagePacker = image.createImagePacker()
    //1.3 将组件截图变成二进制流
    const arrayBuffer = await imagePacker.packToData(imgMsg,{format:'image/jpeg', quality: 98 })
    //2.将图片存储到沙箱
    //2.1获取context对象
    const ctx = getContext(this)
    //2.2生成一个唯一一个的图片路径
    const imagePath = ctx.cacheDir + '/' + Date.now() +'.jpeg'
    //2.3创建文件
    // 打开一个未创建的图片,让他具备创建和读写能力
    // 参数1: imagePath 文件的路径
    // 参数2: 因为还没有文件  fileIo.OpenMode.CREATE 所以先创建 fileIo.OpenMode.READ_WRITE 并设置读写能力
    const file = fileIo.openSync(imagePath,fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
    //2.4二进制写入沙箱
    fileIo.writeSync(file.fd,arrayBuffer)
    fileIo.closeSync(file.fd)
    //3.从沙箱目录拿到图片保存到相册
    //3.1获取uri地址
    const uri = fileUri.getUriFromPath(imagePath)
    //3.2获取资源文件请求
    const photoRequest = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(ctx, uri)
    //3.3创建获取相册实例
    const photoHelper = photoAccessHelper.getPhotoAccessHelper(ctx)
    //3.4保存到相册
    photoHelper.applyChanges(photoRequest)
    //3.5弹窗提示
    promptAction.showToast({ message: '保存成功' })
    //4.关闭弹框
    this.controller.close()
  }

用以前的demo试下,ok没有问题~~

<think>好的,我需要回答用户关于在ArkTS中将图片保存沙箱路径的方法,并提供示例。首先,我得先理解用户的问题。用户提到了引用中的内容,涉及Native接口和沙箱路径的获取,所以可能需要结合ArkTS调用原生能力的方式。 首先,ArkTS鸿蒙系统的一种开发语言,应该类似于TypeScript,所以可能需要使用到鸿蒙的API。根据引用中的信息,保存图片沙箱有两种情况:从rawfile保存和从网络保存。用户需要的是示例代码和方法步骤。 我需要确保回答结构清晰,分步骤说明。可能包括以下几个方面: 1. 保存rawfile中的图片沙箱:需要调用Native侧提供的接口,如saveImageOfRawfileCallback,传入文件名和路径,返回沙箱路径。 2. 保存网络图片沙箱:使用saveImageOfInternetCallback接口,传入URL、目标路径和文件名。 3. 路径获取方法:使用context.getFilesDir()或getCacheDir()来获取沙箱目录。 4. 前端显示:将返回的沙箱路径转换为URL,绑定到Image组件。 需要确认这些接口在ArkTS中是如何调用的,可能需要用到@ohos.fileio或者相关的文件模块。同时,示例代码可能需要使用ArkTS的语法,比如异步操作和接口调用。需要确保语法正确,比如使用async/await处理异步保存操作。 另外,引用中提到前端通过调用Native侧暴露的接口,所以在ArkTS中可能需要使用桥接方法或者直接调用鸿蒙提供的API。例如,context的使用和文件路径的处理。 在写示例代码时,需要注意ArkTS的语法结构,比如函数定义、导入模块等。例如,使用import引入必要的模块,定义异步函数来保存图片,并处理返回的沙箱路径。 最后,生成相关问题,可能涉及性能优化、路径访问权限、错误处理等。需要确保问题相关且有参考价值。</think>在ArkTS中实现图片保存到应用沙箱路径的方法主要分为保存Rawfile资源图片和网络图片两种场景,以下是具体实现步骤和示例: ### 一、保存Rawfile资源图片沙箱 1. **获取沙箱目录路径** 使用`getContext().filesDir`获取应用文件目录,或`getContext().cacheDir`获取缓存目录: ```typescript const sandBoxPath: string = getContext().filesDir; // 例如:/data/app/.../files/ ``` 2. **调用Native接口保存图片** ```typescript async function saveRawfileImage() { try { const fileName = 'sandBoxTest.jpg'; const savedPath = await nativeModule.saveImageOfRawfileCallback(fileName, sandBoxPath); console.log(`沙箱路径:${savedPath}`); return savedPath; } catch (error) { console.error(`保存失败:${error}`); } } ``` ### 二、保存网络图片沙箱 1. **定义接口参数** 需要传入网络图片URL、目标目录和自定义文件名: ```typescript const internetImageUrl = 'https://example.com/image.jpg'; const targetDir = getContext().filesDir; // 或 cacheDir const customFileName = 'downloaded_image.jpg'; ``` 2. **调用Native接口下载并保存** ```typescript async function saveInternetImage() { try { const savedPath = await nativeModule.saveImageOfInternetCallback( internetImageUrl, targetDir, customFileName ); console.log(`网络图片保存路径:${savedPath}`); return savedPath; } catch (error) { console.error(`下载失败:${error}`); } } ``` ### 三、前端显示沙箱图片 将返回的沙箱路径转换为`file://`协议URL后绑定到`Image`组件: ```typescript // 假设 savedPath 为 /data/app/.../files/downloaded_image.jpg const imageUrl = `file://${savedPath}`; // UI组件中 Image(src: imageUrl) .width(200) .height(200) ``` ### 关键点说明 1. **Native接口实现** Native侧需提供`saveImageOfRawfileCallback`和`saveImageOfInternetCallback`方法,前者从`rawfile`目录读取资源文件并复制沙箱,后者通过HTTP下载网络图片[^1][^3]。 2. **路径权限** 沙箱路径通过`getFilesDir()`或`getCacheDir()`获取,仅应用自身可访问,保证数据隔离[^2]。 3. **异步处理** 文件操作需使用`async/await`避免阻塞主线程。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值