En travaillant sur Android Java, SDK récemment mis à jour au niveau de l'API 29, un avertissement s'affiche, indiquant que
Environment.getExternalStorageDirectory()
est obsolète au niveau de l'API 29
Mon code est
private void saveImage() {
if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
final String folderPath = Environment.getExternalStorageDirectory() + "/PhotoEditors";
File folder = new File(folderPath);
if (!folder.exists()) {
File wallpaperDirectory = new File(folderPath);
wallpaperDirectory.mkdirs();
}
showLoading("Saving...");
final String filepath=folderPath
+ File.separator + ""
+ System.currentTimeMillis() + ".png";
File file = new File(filepath);
try {
file.createNewFile();
SaveSettings saveSettings = new SaveSettings.Builder()
.setClearViewsEnabled(true)
.setTransparencyEnabled(true)
.build();
if(isStoragePermissionGranted() ) {
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
@Override
public void onSuccess(@NonNull String imagePath) {
hideLoading();
showSnackbar("Image Saved Successfully");
mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(new File(filepath))));
Intent intent = new Intent(EditImageActivity.this, StartActivity.class);
startActivity(intent);
finish();
}
@Override
public void onFailure(@NonNull Exception exception) {
hideLoading();
showSnackbar("Failed to save Image");
}
});
}
Quelle sera l'alternative pour cela?
Utilisez getExternalFilesDir()
, getExternalCacheDir()
ou getExternalMediaDir()
(méthodes sur Context
) au lieu de Environment.getExternalStorageDirectory()
.
Ou, modifiez mPhotoEditor
pour pouvoir travailler avec un Uri
, puis:
Utilisez ACTION_CREATE_DOCUMENT
Pour obtenir un Uri
à l'emplacement choisi par l'utilisateur, ou
Utilisez MediaStore
, ContentResolver
et insert()
pour obtenir un Uri
pour un type particulier de support (par exemple, une image) - voir cet exemple d'application qui montre comment procéder pour télécharger des vidéos MP4 à partir d'un site Web
Notez également que votre Uri.fromFile
Avec ACTION_MEDIA_SCANNER_SCAN_FILE
Devrait planter sur Android 7.0+ avec un FileUriExposedException
. Sur Android Q, seule l'option MediaStore
/insert()
obtiendra votre contenu indexé par MediaStore
rapidement.
Voir cet article de blog pour en savoir plus sur la manière dont Android Q a affecté le stockage externe.
Obtenez le destPath
avec le nouvel appel d'API:
String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
Voici un petit exemple comment obtenir l'URI d'un fichier si vous souhaitez prendre une photo en utilisant l'appareil photo par défaut et la stocker dans un dossier DCIM (DCIM/app_name/filename.jpg):
Ouvrez la caméra (rappelez-vous de l'autorisation CAMERA):
private var photoURI: Uri? = null
private fun openCamera() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
photoURI = getPhotoFileUri()
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
takePictureIntent.resolveActivity(requireActivity().packageManager)?.also {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
}
Et obtenez l'URI:
private fun getPhotoFileUri(): Uri {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val fileName = "IMG_${timeStamp}.jpg"
var uri: Uri? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver = requireContext().contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/app_name/")
}
uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
}
return uri ?: getUriForPreQ(fileName)
}
private fun getUriForPreQ(fileName: String): Uri {
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
val photoFile = File(dir, "/app_name/$fileName")
if (photoFile.parentFile?.exists() == false) photoFile.parentFile?.mkdir()
return FileProvider.getUriForFile(
requireContext(),
"ru.app_name.fileprovider",
photoFile
)
}
N'oubliez pas l'autorisation WRITE_EXTERNAL_STORAGE pour pré Q et ajoutez un FileProvider à AndroidManifest.xml.
Et obtenez un résultat:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_IMAGE_CAPTURE -> {
photoURI?.let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val thumbnail: Bitmap =
requireContext().contentResolver.loadThumbnail(
it, Size(640, 480), null
)
} else {
// pre Q actions
}
}
}
}
}