android - Android 10 将文件写入公共 DCIM 目录,非弃用方法
问题描述
我们有一个 Android 应用程序,现场工作人员可以在其中拍摄照片,这些照片存储在他们的手机上,并通过网络 API 上传。如果上传失败,他们确实有重试机制,但有时他们需要求助于从手机中提取图像。为了将应用程序升级到 Android 10 版本而不弃用,我被迫将图像写入应用程序内部目录。问题是当他们升级他们的应用程序时,他们会从应用程序中丢失他们的照片。(我也将图像复制到备份目录,但这看起来有点笨拙)
我想将图像写入:/storage/emulated/0/DCIM/GoTrialImages
相反,他们将去:/storage/emulated/0/Android/data/au.come.aceware.ktr.ktr/files/DCIM/GoTrialImages/photoIntent(其中 photoIntent 是发生这种情况的活动)
这是我从在线文章中复制和调整的代码:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fileName = "JPEG_" + timeStamp + ".jpg";
File mediaStorageDir = new File(getExternalFilesDir(Environment.DIRECTORY_DCIM + File.separator +"GoTrialPhotos"), TAG);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()){
Log.d(TAG, "failed to create directory");
}
// Return the file target for the photo based on filename
File file = new File(mediaStorageDir.getPath() + File.separator + fileName);
Uri bmpUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", file);
这是清单中的文件提供程序条目:
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>```
and here is @xml/provider_paths:
```<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>```
1) Is it possible to do what I am seeking to do ?
2) How do I do it without using deprecated code
Many thanks in advance
Tony
Following the suggestion to use media store I kept most of the code for creating the app internal file name
(mainly because I wanted the randomised display name):
private File createImageFileV2() throws IOException
{
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
imageFileNameToUseAtWebServerEnd = strTrial + "_" + timeStamp + "_" + strUserId + ".jpg";
File[] storageDir = getExternalMediaDirs();
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir[0] /* directory */
);
return image;
}
I then passed the file object in to the following code:
public Uri testgetPhotoFileUri2(File f)
{
Uri uri = null;
String strDisplayName = f.getName();
final ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, strDisplayName);
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM );
final ContentResolver resolver = thisContext.getContentResolver();
try
{
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
uri = resolver.insert(contentUri, values);
if (uri == null)
throw new IOException("Failed to create new MediaStore record.");
return uri;
}
catch (IOException e)
{
if (uri != null) {
// Don't leave an orphan entry in the MediaStore
resolver.delete(uri, null, null);
}
}
return uri;
}
I then used the resulting uri as my camera uri:
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraUri);
However, when the OnActivityResult calls HandleBigCameraPhoto and attempts to extract the bitmap using the CameraUri:
private void handleBigCameraPhoto() {
Bitmap bitmap = null;
if (cameraUri != null)
{
if (Build.VERSION.SDK_INT >= 29) {
ImageDecoder.Source source = ImageDecoder.createSource(getApplicationContext().getContentResolver(), cameraUri);
try {
bitmap = ImageDecoder.decodeBitmap(source);
} catch (IOException e) {
e.printStackTrace();
}
It error traps to "no such file or directory"
Does this mean that I need to most of my work (image resizing, rotation, etc) using my app private file only and then as a last step insert the bitmap in to media store (and then delete the app private file so the user does not see the file name twice under gallery, recents)?
解决方案
您不会使用已弃用的功能:
File file = new File(getExternalFilesDir(null)
.getParentFile()
.getParentFile()
.getParentFile()
.getParentFile(), "DCIM");
;-)。
推荐阅读
- ruby-on-rails - 如何将 URL 参数传递给 Rails 应用程序中的内部链接?
- python - 使用 uwsgi 对服务器中的 Flask 应用程序进行更改后没有任何反应
- hive - 将表从 Hive 迁移到 Cassandra - 使用 COPY
- javascript - Ionic - 我如何得到下周的日期?
- android - 不是更新用户的数据,而是从 firebase 中删除数据
- c++ - 函数接收与传递不同的值
- apache-kafka - 卡夫卡流 - TimeWindows
- macos - NSClickGestureRecognizer.location(in:) 和 hitTest()
- python - python(flask)如何从纯文本输入中呈现html链接
- javascript - 取消禁用直接输入