uni-app targetSdkVersion高于28时 华为webview内拍照无法保存图片 一直提示正在保存照片

发布于 1周前 作者 eggper 来自 Uni-App

uni-app targetSdkVersion高于28时 华为webview内拍照无法保存图片 一直提示正在保存照片

项目属性 详细信息
产品分类 uniapp/App
PC开发环境 Windows
PC开发环境版本 win11 23h2
HBuilderX类型 正式
HBuilderX版本 4.29
手机系统 全部
手机厂商 华为
页面类型 vue
vue版本 vue2
打包方式 云端
项目创建方式 HBuilderX

测试过的手机:

nova 5 pro 系统HarmonyOS 4.0.0

操作步骤:

自定义基座设置targetSdkVersion为30,webview中打开任意网站触发选择图片,选择拍照时拍完照一直正在保存,只有targetSdkVersion低于28才可以正常使用

预期结果:

拍照正常使用

实际结果:

拍照一直提示正在保存

bug描述:

打包app targetSdkVersion高于28,华为webview内拍照无法保存图片,一直提示正在保存照片,低于等于28可以正常使用,但是华为应用市场最低要求为30!

视频.zip


1 回复

针对您提到的uni-app在targetSdkVersion高于28时,华为设备上WebView内拍照无法保存图片的问题,这通常与Android系统的权限管理和文件存储机制变化有关。从Android 9(Pie, API级别28)开始,Google引入了Scoped Storage机制,对应用访问外部存储进行了更严格的限制。以下是一些可能的解决方案,通过代码示例来展示如何处理这个问题。

1. 动态请求存储权限

首先,确保你的应用有适当的权限来写入存储。尽管在Scoped Storage下,直接访问外部存储的路径受限,但存储权限仍然是必要的,特别是在处理拍照功能时。

// 在uni-app的manifest.json中配置必要权限
{
  "mp-weixin": {},
  "app-plus": {
    "distribute": {
      "android": {
        "permissions": [
          "android.permission.WRITE_EXTERNAL_STORAGE",
          "android.permission.READ_EXTERNAL_STORAGE"
        ]
      }
    }
  }
}

// 在页面加载或拍照功能触发前动态请求权限(需使用uni-app的API封装权限请求逻辑)
uni.authorize({
  scope: 'scope.writePhotosAlbum',
  success() {
    console.log('存储权限授权成功');
    // 触发拍照逻辑
  },
  fail() {
    console.log('存储权限授权失败');
  }
});

2. 使用MediaStore API保存照片

由于Scoped Storage的限制,建议使用MediaStore API来保存照片,这样可以避免直接访问外部存储路径的问题。以下是一个简化的示例,展示如何在Android原生代码中通过MediaStore保存照片(注意,这部分代码需要在原生插件或原生模块中实现,uni-app本身不直接支持Java/Kotlin代码,但可以通过扩展实现)。

ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "image.jpg");
values.put(MediaStore.Images.Media.DISPLAY_NAME, "image.jpg");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/MyApp");

Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
if (uri != null) {
    try (OutputStream outputStream = getContentResolver().openOutputStream(uri)) {
        // 将图片数据写入outputStream
    } catch (IOException e) {
        e.printStackTrace();
    }
}

结论

由于uni-app的限制,直接在JavaScript/TypeScript中处理这些原生级别的存储问题是不可能的。你需要创建一个原生插件或使用现有的原生模块来处理MediaStore API的调用和权限请求。这通常涉及到Android原生开发知识,并可能需要与uni-app社区或专业开发者合作来完成。

回到顶部