Android API29升31后图库选图报错:unknown protocol: content
修复思路:Android API31下NativeScript图库选图显示异常
核心问题分析
API29+ Android启用Scoped Storage后,@nativescript/imagepicker返回的是content://协议的URI,而NativeScript的Image组件直接绑定该URI时,底层无法识别非http/https/file协议的URI,导致抛出MalformedURLException。
具体修复方案
1. 优先升级依赖版本
你当前使用的@nativescript/core@7.1.3和@nativescript/imagepicker@1.0.9版本对API31的适配不完善,建议升级到兼容Scoped Storage的新版本:
- 将
@nativescript/core升级到8.x及以上稳定版 - 将
@nativescript/imagepicker升级到最新稳定版(如^1.1.12及以上)
升级后很多适配问题会被底层插件修复,是最省心的解决方案。
2. 正确使用ImageAsset对象绑定
不要直接提取content://URI绑定到Image组件,NativeScript的Image组件支持直接绑定ImageAsset对象,修改代码如下:
修正选择照片的回调逻辑
首先修正代码中变量名错误(你当前代码里this.addPhoto(imageAsset)的imageAsset未定义,应该用循环中的selected):
this.imagePicker .authorize() .then(() => this.imagePicker.present()) .then((selection) => { console.log("selection done") selection.forEach((selected) => { console.log("selected: " + JSON.stringify(selected)) this.addPhoto(selected); // 替换为当前选中的ImageAsset对象 }) }) .catch((e) => { console.log("throwing exception") console.log(e); });
模板中直接绑定ImageAsset
在HTML模板中,直接将Image组件的src绑定到ImageAsset对象即可:
<Image [src]="photo" stretch="aspectFit"></Image>
3. 转换ImageAsset为ImageSource绑定
如果需要更灵活的图片处理(比如压缩、缓存),可以将ImageAsset转换为ImageSource对象后再绑定:
import { ImageSource } from "@nativescript/core"; async addPhoto(selected: ImageAsset) { // 将ImageAsset转换为ImageSource const imageSource = await ImageSource.fromAsset(selected); // 将ImageSource存入数组供模板绑定 this.photos.push(imageSource); }
4. 检查并配置API31权限
API31及以上版本,Android将READ_EXTERNAL_STORAGE替换为READ_MEDIA_IMAGES权限,确保在AndroidManifest.xml中添加:
<!-- API31+ 图库读取权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- 兼容API30及以下版本 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="30" />
内容的提问来源于stack exchange,提问作者Tsujmi
相关产品推荐
相关产品推荐

