Pracując na Android Java, ostatnio zaktualizowanym SDK do poziomu API 29, teraz jest wyświetlane ostrzeżenie, które to stwierdza
Environment.getExternalStorageDirectory()
jest przestarzały na poziomie interfejsu API 29
Mój kod to
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");
}
});
}
Jaka będzie alternatywa dla tego?
źródło
getExternalMediaDir
wContext
zobacz to sam: developer.android.com/reference/android/content/Context IgetExternalMediaDirs
jest przestarzała, również spojrzeć: developer.android.com/reference/android/content/... ZarównogetExternalFilesDir()
igetExternalCacheDir()
są usuwane po odinstalowaniu aplikacji ( zobacz ten sam adres URL). Tak więc żadne z powyższych nie może zastąpićEnvironment.getExternalStorageDirectory()
.Pobierz za
destPath
pomocą nowego wywołania interfejsu API:String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
źródło
W przypadku Androida Q możesz dodać
android:requestLegacyExternalStorage="true"
do swojego elementu w manifeście. Ten opowiada cię do starszego modelu pamięci, a istniejący zewnętrzny kod przechowywania zadziała.<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10 or higher. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Z technicznego punktu widzenia jest to potrzebne tylko po zaktualizowaniu
targetSdkVersion
do 29. Aplikacje o niższychtargetSdkVersion
wartościach domyślnie przechodzą na starszą pamięć i musiałybyandroid:requestLegacyExternalStorage="false"
z niej zrezygnować.źródło
Proszę używać
getExternalFilesDir()
,getExternalCacheDir()
zamiastEnvironment.getExternalStorageDirectory()
podczas tworzenia pliku w Androidzie 10.Zobacz poniżej wiersz:
val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")
źródło
getExternalFilesDir()
niestandardowej ścieżki do zapisywania obrazu, chcę tego użyć, aby zapobiec wyświetlaniu obrazów w Galerii? Domyślnie zapisz doAndorid/data/packagename/...
To jest mały przykład, jak uzyskać identyfikator URI dla pliku, jeśli chcesz zrobić zdjęcie przy użyciu domyślnego aparatu i zapisać je w folderze DCIM (DCIM / nazwa_aplikacji / nazwa_pliku.jpg):
Otwórz kamerę (pamiętaj o uprawnieniu KAMERA):
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) } } }
I pobierz 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 ) }
Nie zapomnij o uprawnieniu WRITE_EXTERNAL_STORAGE dla pre Q i dodaj FileProvider do AndroidManifest.xml.
I uzyskaj wynik:
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 } } } } }
źródło
To zadziałało dla mnie
Dodaj tę linię w tagu aplikacji
manifest
plikuandroid:requestLegacyExternalStorage="true"
Przykład
<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" }
źródło