2011-01-28 21 views
17

Estoy tratando de seleccionar un archivo de imagen de la galería de fotos y escribir en la tarjeta SD. A continuación se muestra el código que da como resultado una excepción. Parece arrojar esta excepción al intentar crear FileOutputStream. Tengo la siguiente línea agregada al archivo de manifiesto anidado dentro del elemento de la aplicación. No puedo encontrar una solución al problema:java.io.FileNotFoundException (Permiso denegado) Al intentar escribir en la tarjeta SD de Android

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

public boolean saveSelectedImage(Uri selectedImage, int imageGroup, 
     int imageNumber) 
{ 
    boolean exception = false; 
    InputStream input = null; 
    OutputStream output = null; 
    if(externalStorageIsWritable()) 
    { 
     try 
     { 
      ContentResolver content = ctx.getContentResolver(); 
      input = content.openInputStream(selectedImage); 
      if(input != null) Log.v(CLASS_NAME, "Input Stream Opened successfully"); 
      File outFile = null; 

      File root = Environment.getExternalStorageDirectory(); 
      if(root == null) Log.v(CLASS_NAME, "FAILED TO RETRIEVE DIRECTORY"); 
      else Log.v(CLASS_NAME, "ROOT DIRECTORY is:"+root.toString()); 

      output = new FileOutputStream(root+"/Image"+ imageGroup + "_" + imageNumber + ".png"); 

      if(output != null) Log.e(CLASS_NAME, "Output Stream Opened successfully"); 
      // output = new FileOutputStream 
      // ("/sdcard/Image"+imageGroup+"_"+imageNumber+".png"); 

      byte[] buffer = new byte[1000]; 
      int bytesRead = 0; 
      while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) 
      { 
       output.write(buffer, 0, buffer.length); 
      } 
     } catch (Exception e) 
     { 

      Log.e(CLASS_NAME, "Exception occurred while moving image: "); 
      e.printStackTrace(); 

      exception = true; 
     } finally 
     { 
      // if(input != null)input.close(); 
      // if(output != null)output.close(); 
      // if (exception) return false; 
     } 

     return true; 
    } else 
     return false; 

} 
+0

¿Ha solicitado permiso para escribir en su manifiesto? –

+1

Encontré la respuesta a mi problema El elemento uses-permission tiene que estar fuera del elemento de la aplicación en el archivo de manifiesto. – joefischer1

Respuesta

0

Usted puede tratar con:

String myPath=Environment.getExternalStorageDirectory()+"/Image"+ imageGroup + "_" + imageNumber + ".png"; 

File myFile = new File();  
input = new FileInputStream(myFile); 
7

También debe asegurarse de que el subsistema de almacenamiento externo está en el estado correcto ; use Environment.getExternalStorageState() y busque Environment.MEDIA_MOUNTED que es el único estado seguro.

También es una buena idea limitar el manejo de excepciones al IOException alrededor de esas secciones, para que no se recupere en exceso de problemas específicos de IO, p. medios desmontados

Si necesita eventos, existen intenciones de transmisión (Intent.ACTION_MEDIA_xxx) con la misma información que puede registrar con IntentListener.

También tenga en cuenta que el almacenamiento externo puede ser deshabilitado cuando está utilizando USB para la depuración!

También hay un período prolongado durante el inicio del dispositivo, donde el Almacenamiento externo no está disponible. Si haces cosas en los servicios al inicio, esto es un problema.

En general, su aplicación debe conocer el estado de Almacenamiento externo cuando accede a ella, y manejar casos donde no está disponible, o deja de estar disponible al acceder a ella.

+0

Para ser específico, debe probar que Environment.getExternalStorageState() devuelve Environment.MEDIA_MOUNTED. Ese es el único estado de almacenamiento que permite escribir. – RenniePet

+0

gracias, edité mi respuesta para reflejar eso. –

24

Así es como su archivo de manifiesto debe ser similar

<application android:icon="@drawable/icon" android:label="@string/app_name"> 
    <activity android:name=".WriteCBTextToFileActivity" 
       android:label="@string/app_name"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
</application> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

+0

Muchas gracias. Funciona bien :) –

+8

Hola, mi Manifiesto se ve así y sigo teniendo este error ... – MichalK

+0

¿Puedes compartir el archivo de manifiesto? – Saurabh

3

Si tiene los permisos correctos establecidos en el manifiesto, asegúrese de que el dispositivo no está en "Disco Drive "modo cuando se conecta a una PC. Cambie al modo "Solo carga" y debería funcionar.

9

Tuve este problema y las respuestas aquí no lo arreglaron, porque había cometido un error bastante tonto.

Asegúrate de darle a tu emulador de Android una tarjeta SD ... Dejé en blanco el tamaño de la tarjeta SD y, por supuesto, no pudo encontrar nada. Además de eso, estaba especificando un directorio dentro de dicha tarjeta SD que aún no se había creado, así que asegúrese de considerar ese caso también.

(Puede cambiar la configuración de la tarjeta SD de una AVD por ir al Administrador de dispositivos virtual de Android, la edición de su emulador de elección, y entrar en algún valor para el tamaño de la tarjeta SD)

+1

¿Por qué lo dejarían en blanco de forma predeterminada ... Muchas aplicaciones de hoy dependen de la tarjeta SD . –

0

intenta utilizar openFileOutput("filename") para devolver un FileOutputStream en lugar de especificar la ubicación por ti mismo.

Compruebe el doc here

+0

Esto funciona solo con archivos privados (a los que solo puede acceder la aplicación que realiza la llamada). –

2

en cuenta que, además de la respuesta Saurabh, ya que la API 23 que necesita para solicitar los permisos en tiempo de ejecución.

Ver aquí: https://developer.android.com/training/permissions/requesting.html

Y la respuesta de Justin Fiedler aquí: https://stackoverflow.com/a/33288986/328059

Además, he tenido varios casos en los que después de cambiar el permiso y volver a ejecutar la aplicación usando Instant Run los permisos no se han actualizado . Entonces, como mejor práctica, después de cambiar el manifiesto, desinstalo la aplicación del dispositivo de destino y la reconstruyo.

Cuestiones relacionadas