问题一: 使用vant-uploader该组件内使用input file,然而flutter webview_flutter貌似还不支持input选择相册打开相机
vant-uploader
参照了其它人的文章,特地在这里记录下.
https://blog.csdn.net/kameleon2013/article/details/109104531
https://blog.csdn.net/chjqxxxx/article/details/52724983
下载最新 webview_flutter插件版本,加入相册选择,相机拍照,本地编译之后,完美解决
问题二: 拍照后H5端没反应(用户已授权),未接收到文件
Android:WebView里调用相机/文件选取照片并上传
https://www.jianshu.com/p/232e0df0936f
Android 10 分区存储完全解析
https://blog.csdn.net/wanliguodu/article/details/120297395
重新梳理整个流程,
flutter --version
Flutter 3.11.0-12.0.pre • channel master
Framework • revision 216605b60f (9 months ago) • 2023-05-23 23:40:27 -0400
Engine • revision eebcf36cd3
Tools • Dart 3.1.0 (build 3.1.0-139.0.dev) • DevTools 2.23.1
webview使用是的老版本
webview_flutter: 2.0.7
追加针对Android 分区存储机制处理:
private Intent createCameraIntent() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // 判断是否为Android 10及以上
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "IMG_" + System.currentTimeMillis() + ".jpg");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES);
ContentResolver resolver = WebViewFlutterPlugin.activity.getContentResolver();;
mCameraFilePath = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraFilePath);
} else {
String filePath = Environment.getExternalStorageDirectory() + File.separator
+ Environment.DIRECTORY_PICTURES + File.separator;
String fileName = "IMG_" + System.currentTimeMillis() +".jpg";
mCameraFilePath = Uri.fromFile(new File(filePath + fileName));
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraFilePath);
}
return cameraIntent;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null){
return;
}
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (intent != null) {//文件中选图片
String dataString = intent.getDataString();
ClipData clipData = intent.getClipData();
if (clipData != null) {
results = new Uri[clipData.getItemCount()];
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
results[i] = item.getUri();
}
}
if (dataString != null) {
Log.v(TAG,"文件中获取: "+ dataString);
results = new Uri[]{Uri.parse(dataString)};
}
}else{// 从相机获取
updatePhotos();
Log.v(TAG,"从相机获取: "+ mCameraFilePath.toString());
results = new Uri[]{mCameraFilePath};
}
}
if (results == null) {
uploadMessageAboveL.onReceiveValue(null);
} else {
for (Uri uri : results) {
Log.v(TAG, String.format("Url: host: %s, path: %s, uri: %s",uri.getHost(),uri.getPath() ,uri));
}
uploadMessageAboveL.onReceiveValue(results);
}
uploadMessageAboveL = null;
}
/**
* 广播,唤醒系统刷新媒体文件
*/
private void updatePhotos() {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(mCameraFilePath);
WebViewFlutterPlugin.activity.sendBroadcast(intent);
}
Android 10 引入分区存储(Scoped Storage)机制的主要原因是为了增强用户数据隐私保护和管理,以及简化应用程序对文件系统的访问方式。以下是几个关键因素:
用户隐私保护:
分区存储限制了应用对用户个人文件的无节制访问,尤其是外部存储上的公共目录。在新的模式下,应用除非得到明确授权,否则无法读取其他应用创建或修改的文件。
统一权限模型:
在之前的Android版本中,由于权限体系的复杂性,应用可能通过各种手段绕过权限控制来访问用户的数据。分区存储将权限模型规范化,要求应用按照新的规范申请和使用权限。
清理冗余和混乱:
旧版Android系统中,不同的应用可能会随意地在公共目录下创建、读取、修改甚至删除文件,导致文件系统变得杂乱且难以管理。分区存储有助于减少这种混乱,并使得用户能够更方便地管理他们的文件。
兼容未来存储技术:
随着Android设备上存储技术的发展,如引入加密文件系统和云备份等功能,分区存储为这些高级功能提供了更好的支持,确保未来无论底层存储如何变化,应用都能够以标准化的方式进行交互。
遵从GDPR等法规:
随着全球范围内对于个人数据保护法律法规的强化,Google需要确保Android平台符合GDPR(欧洲通用数据保护条例)等数据保护规定,分区存储是实现这一目标的关键措施之一。
总之,Android 10 的分区存储设计改进了存储权限管理和数据隔离,提升了用户体验的同时也增强了安全性