J'essaie le code source d'une application de caméra très basique sur Android Studio 3.4.1 avec l'API Android Virtual Device (AVD) Nexus 7 (2012) 29. J'ai pris une photo avec la caméra dans l'émulateur et j'ai essayé de l'enregistrer sous / storage / emulated / 0 / Pictures / myPic.png, mais a obtenu une exception de /storage/emulated/0/Pictures/myPic.png open failed: EACCES (Permission Denied). J'ai essayé tous les conseils disponibles en ligne, par exemple:
outStream = new FileOutputStream(file);
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); verifyStoragePermissions(this); ...... private void saveImageToFile(File file) { if (mCameraBitmap != null) { FileOutputStream outStream = null; verifyStoragePermissions(this); try { outStream = new FileOutputStream(file); ... } catch (Exception e) { Toast toastException = Toast.makeText(MainActivity.this, "Exception: " + e.getMessage(), Toast.LENGTH_SHORT); LinearLayout toastLayoutException = (LinearLayout) toastException.getView(); TextView toastTVException = (TextView) toastLayoutException.getChildAt(0); toastTVException.setTextSize(30); toastException.show(); } ...
public class MainActivity extends Activity { private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; public static void verifyStoragePermissions(Activity activity) { int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); boolean checkPermission = (permission == PackageManager.PERMISSION_GRANTED); Toast toastPermission = Toast.makeText(activity, "Is permission granted? " + checkPermission, Toast.LENGTH_SHORT); LinearLayout toastLayoutPermission = (LinearLayout) toastPermission.getView(); TextView toastTVPermission = (TextView) toastLayoutPermission.getChildAt(0); toastTVPermission.setTextSize(30); toastPermission.show(); if (permission != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE ); } }
Cependant, AUCUN des conseils ne fonctionne!
Le code a jeté une exception de
/storage/emulated/0/Pictures/myPic.png open a échoué: EACCES (Autorisation refusée)
quand il a atteint la ligne de
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Une idée pour résoudre ce problème davantage? Merci beaucoup.
6 Réponses :
J'ai finalement compris que le problème résidait dans l'API Android 29, une fois que je suis passé à l'API 28, plus aucun problème d'autorisation.
Merci, cela a résolu le problème pour moi. Travaillait sur l'API 29 et peu importe ce que j'ai essayé, j'ai continué à avoir le même problème. La mise à niveau vers l'API 28 l'a corrigé
La rétrogradation retarde simplement le problème, ajoutez plutôt android: requestLegacyExternalStorage = "true" à votre manifeste Android, voir la réponse ci-dessus
L'ajout d' android: requestLegacyExternalStorage = "true" au manifeste Android a fonctionné pour moi avec Android 29
<application android:name=".MyApplication" android:allowBackup="true" android:requestLegacyExternalStorage="true" ...
J'ai également eu cette erreur dans mon projet.
Je l'ai corrigé en ajoutant
android:requestLegacyExternalStorage="true"
dans le fichier manifestes. (vois ici)
J'ai également essayé d'utiliser un appareil photo et d'enregistrer la photo sur ImageView et j'ai eu des problèmes avec les autorisations. J'ai changé l'API de 29 à 28 - je n'ai pas aidé, ajoutez
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
n'a pas aidé. J'ai changé la méthode que j'ai utilisée pour créer un fichier pour stocker l'image à partir de:
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
à:
android:requestLegacyExternalStorage="true"
Et le problème est parti. BTW je ne sais pas pourquoi. Peut-être parce que le premier était obsolète.
Votre problème est dû à l'introduction du stockage scoped dans l'API 29. Vous avez trois solutions au problème (certaines ont déjà été mentionnées, mais j'ai pensé que cela aiderait à clarifier et à consolider):
N'exécutez votre application que sur les appareils exécutant l'API 28 ou version antérieure.
Ajoutez android:requestLegacyExternalStorage="true"
à AndroidManifest.xml afin que votre application puisse s'exécuter sur l'API 29 et au-dessus:
<application android: requestLegacyExternalStorage = "true" ...
Modernisez votre application pour l'API 29+. Commencez par vous débarrasser des autorisations WRITE_EXTERNAL_STORAGE. Et remplacez l'appel à Environment.getExternalStoragePublicDirectory()
getExternalFilesDir()
par getExternalFilesDir()
, qui enregistrera votre image sur un stockage externe mais dans un répertoire auquel votre application pourra accéder.
Vous trouverez ci-dessous une méthode pour enregistrer un Bitmap au format JPG à l'aide du MediaStore, qui permet à d'autres applications d'accéder à l'image:
private void saveImage(Bitmap bitmap) throws IOException { ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "myImage.jpg"); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg"); contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES); ContentResolver resolver = getContentResolver(); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); OutputStream imageOutStream = null; try { if (uri == null) { throw new IOException("Failed to insert MediaStore row"); } imageOutStream = resolver.openOutputStream(uri); if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream)) { throw new IOException("Failed to compress bitmap"); } } finally { if (imageOutStream != null) { imageOutStream.close(); } } }
ajoutez android:requestLegacyExternalStorage="true"
à votre manifeste Android
<manifest ... > <application android:requestLegacyExternalStorage="true" ... /> </manifest>
la raison de cela, vous pouvez lire à https://medium.com/@sriramaripirala/android-10-open-failed-eacces-permission-denied-da8b630a89df