We have an Android app where field workers take photographs which are stored on their phone and also uploaded via a web api. If the uploads fail they do have retry mechanisms but sometimes they need to resort to pulling the images off their phone. In order to bring the app up to Android 10 version without deprecation I was forced to write the images to an app internal directory. The problem is that when they upgrade their app they lose their photos from the app. (I do also copy the images to a backup directory but this is all looking a bit klutzy)
I would like to write the images to : /storage/emulated/0/DCIM/GoTrialImages
Instead they are going to : /storage/emulated/0/Android/data/au.come.aceware.ktr.ktr/files/DCIM/GoTrialImages/photoIntent (where photoIntent is the activity that this is occurring in)
Here is the code I have copied and tweaked from an online article:
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);
Here is my file provider entry in the manifest:
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)?