Trabajando en Android Java, SDK actualizado recientemente al nivel de API 29 ahora se muestra una advertencia que indica que
Environment.getExternalStorageDirectory()
está obsoleto en el nivel de API 29
Mi codigo es
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");
}
});
}
¿Cuál será la alternativa para esto?
fuente
getExternalMediaDir
en elContext
, ver usted mismo: developer.android.com/reference/android/content/Context YgetExternalMediaDirs
está en desuso, también miran: developer.android.com/reference/android/content/... TantogetExternalFilesDir()
ygetExternalCacheDir()
se eliminan al desinstalar la aplicación ( ver la misma URL). Entonces, ninguno de los anteriores puede sustituirEnvironment.getExternalStorageDirectory()
.Obtenga el
destPath
con la nueva llamada API:String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
fuente
Para Android Q, puede agregar
android:requestLegacyExternalStorage="true"
a su elemento en el manifiesto. Esto lo opta por el modelo de almacenamiento heredado y su código de almacenamiento externo existente funcionará.<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10 or higher. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Técnicamente, solo necesita esto una vez que actualice su
targetSdkVersion
a 29. Las aplicaciones contargetSdkVersion
valores más bajos por defecto optan por el almacenamiento heredado y deberíanandroid:requestLegacyExternalStorage="false"
optar por no participar.fuente
Este es un pequeño ejemplo de cómo obtener un URI para un archivo si desea tomar una foto usando la cámara predeterminada y almacenarla en una carpeta DCIM (DCIM / app_name / filename.jpg):
Cámara abierta (recuerde el permiso 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) } } }
Y obtén 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 ) }
No se olvide del permiso WRITE_EXTERNAL_STORAGE para pre Q y agregue un FileProvider a AndroidManifest.xml.
Y obtén un resultado:
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 } } } } }
fuente
Úselo
getExternalFilesDir()
, engetExternalCacheDir()
lugar deEnvironment.getExternalStorageDirectory()
cuando cree un archivo en Android 10.Vea la siguiente línea:
val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")
fuente
getExternalFilesDir()
una ruta personalizada para guardar la imagen? Quiero usar esto para evitar mostrar imágenes en la galería. De forma predeterminada, se guarda enAndorid/data/packagename/...
Esto funcionó para mi
Agregue esta línea en la etiqueta de la aplicación del
manifest
archivoandroid:requestLegacyExternalStorage="true"
Ejemplo
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" android:requestLegacyExternalStorage="true" android:supportsRtl="true" android:theme="@style/AppTheme"> </application>
defaultConfig { minSdkVersion 16 targetSdkVersion 29 multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" }
fuente