Работая над Android Java, недавно обновил SDK до уровня API 29, теперь отображается предупреждение, в котором говорится, что
Environment.getExternalStorageDirectory()
устарело на уровне API 29
Мой код
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");
}
});
}
Что будет для этого альтернатива?
источник
getExternalMediaDir
вContext
, убедитесь в этом сами: developer.android.com/reference/android/content/Context ИgetExternalMediaDirs
осуждается, также смотрят: developer.android.com/reference/android/content/... ОбаgetExternalFilesDir()
иgetExternalCacheDir()
удаляются после приложения удаления ( см. тот же URL). Итак, ничто из вышеперечисленного не может заменитьEnvironment.getExternalStorageDirectory()
.Получите
destPath
с помощью нового вызова API:String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
источник
Для Android Q вы можете добавить
android:requestLegacyExternalStorage="true"
к своему элементу в манифесте. Это позволяет выбрать устаревшую модель хранилища, и ваш существующий код внешнего хранилища будет работать.<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10 or higher. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Технически вам это понадобится только после того, как вы обновите свой
targetSdkVersion
до 29. Приложения с более низкимиtargetSdkVersion
значениями по умолчанию выбирают устаревшее хранилище, и им нужноandroid:requestLegacyExternalStorage="false"
будет отказаться.источник
Это небольшой пример того, как получить URI для файла, если вы хотите сделать снимок с помощью камеры по умолчанию и сохранить его в папке DCIM (DCIM / app_name / filename.jpg):
Открыть камеру (помните про разрешение КАМЕРЫ):
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) } } }
И получите 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 ) }
Не забывайте о разрешении WRITE_EXTERNAL_STORAGE для pre Q и добавьте FileProvider в AndroidManifest.xml.
И получим результат:
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 } } } } }
источник
Используйте
getExternalFilesDir()
,getExternalCacheDir()
а неEnvironment.getExternalStorageDirectory()
при создании файла в Android 10.См. Строку ниже:
val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")
источник
getExternalFilesDir()
настраиваемый путь для сохранения изображения, я хочу использовать его для предотвращения отображения изображений в галерее? По умолчанию он сохраняется вAndorid/data/packagename/...
Это сработало для меня
Добавьте эту строку в тег приложения
manifest
файлаandroid:requestLegacyExternalStorage="true"
пример
<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" }
источник