Bei der Arbeit mit Android Java, kürzlich aktualisiertes SDK auf API-Level 29, wird jetzt eine Warnung angezeigt, die dies besagt
Environment.getExternalStorageDirectory()
ist in API-Level 29 veraltet
Mein Code ist
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");
}
});
}
Was wird die Alternative dafür sein?
quelle
getExternalMediaDir
InContext
, sehen Sie es selbst: developer.android.com/reference/android/content/Context UndgetExternalMediaDirs
ist veraltet. Schauen Sie auch: developer.android.com/reference/android/content/… BeidegetExternalFilesDir()
undgetExternalCacheDir()
werden bei der Deinstallation der Anwendung gelöscht ( siehe die gleiche URL). Keines der oben genannten kann es ersetzenEnvironment.getExternalStorageDirectory()
.Holen Sie sich das
destPath
mit dem neuen API-Aufruf:String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
quelle
Für Android Q können Sie
android:requestLegacyExternalStorage="true"
Ihrem Element im Manifest hinzufügen . Dies setzt Sie in das alte Speichermodell und Ihre vorhandenen externen Speicher Code funktioniert.<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10 or higher. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Technisch gesehen benötigen Sie dies erst, wenn Sie Ihr Update
targetSdkVersion
auf 29 aktualisiert haben . Apps mit niedrigerentargetSdkVersion
Werten aktivieren standardmäßig den Legacy-Speicher und müssenandroid:requestLegacyExternalStorage="false"
sich abmelden.quelle
Dies ist ein kleines Beispiel zum Abrufen des URI für eine Datei, wenn Sie ein Foto mit der Standardkamera aufnehmen und in einem DCIM-Ordner (DCIM / app_name / filename.jpg) speichern möchten:
Öffnen Sie die Kamera (denken Sie an die Erlaubnis von 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) } } }
Und URI erhalten:
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 ) }
Vergessen Sie nicht die WRITE_EXTERNAL_STORAGE-Berechtigung für Pre-Q und fügen Sie AndroidManifest.xml einen FileProvider hinzu.
Und ein Ergebnis erhalten:
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 } } } } }
quelle
Bitte verwenden Sie
getExternalFilesDir()
,getExternalCacheDir()
anstattEnvironment.getExternalStorageDirectory()
beim Erstellen einer Datei in Android 10.Siehe folgende Zeile:
val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")
quelle
getExternalFilesDir()
mit benutzerdefiniertem Pfad zum Speichern von Bildern verwenden, ich möchte dies verwenden, um zu verhindern, dass Bilder in die Galerie gezeigt werden? Standardmäßig wird esAndorid/data/packagename/...
Das hat bei mir funktioniert
Fügen Sie diese Zeile in das Anwendungs-Tag der
manifest
Datei einandroid:requestLegacyExternalStorage="true"
Beispiel
<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" }
quelle