2012-10-12 50 views
7

Mientras escribo el archivo en la tarjeta SD externa recibo un error. Se rechaza el permiso EACCESS. He establecido el permiso <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Pero cuando leo el archivo puedo leerlo con éxito pero no puedo escribir el archivo. El código que estoy usando para escribir el archivo en la tarjeta SD es:EACCESS Permiso denegado en Android

String path="mnt/extsd/Test"; 

       try{ 
        File myFile = new File(path, "Hello.txt");    //device.txt 
        myFile.createNewFile(); 
        FileOutputStream fOut = new FileOutputStream(myFile); 

        OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut); 
        myOutWriter.append(txtData.getText()); 
        myOutWriter.close(); 
        fOut.close(); 
        Toast.makeText(getBaseContext(),"Done writing SD "+myFile.getPath(),Toast.LENGTH_SHORT).show(); 
       } catch (Exception e) { 
        Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_SHORT).show(); 
        System.out.println("Hello"+e.getMessage()); 
       } 
      } 

el camino para la tarjeta de almacenamiento externo es mnt/extsd/. Es por eso que no puedo usar Environment.getExternalStorageDirectory().getAbsolutePath() que me da una ruta mnt/sdcard y esta ruta es para la ruta de almacenamiento interno en mi tableta. Indique por qué esto es así. ¿Cómo puedo resolver esto?

Respuesta

13

Como recuerdo, Android recibió un soporte parcial de almacenamiento múltiple desde Honeycomb, y el almacenamiento primario (el que obtiene de Environment.getExternalStorageDirectory, generalmente parte del eMMC interno tarjeta) todavía está protegido por el permiso WRITE_EXTERNAL_STORAGE, pero los almacenes secundarios (como la tarjeta SD extraíble real) están protegidos por un nuevo permiso android.permission.WRITE_MEDIA_STORAGE, y el nivel de protección es signatureOrSystem, consulte también la discusión en this article.

Si este es el caso, entonces parece imposible que una aplicación normal a escribir nada a la sdcard real sin una firma plataforma ...

+0

bien ... ¿Hay alguna otra forma de escribir? – CodingDecoding

+0

¿Tiene acceso de root a su tableta? Si aún así puede hacer una prueba como esta: 1) permita que su aplicación use el permiso WRITE_MEDIA_STORAGE y luego reconstruirlo; 2) desinstala tu aplicación si ya está instalada, luego ejecuta "adb root", "adb remount", "adb push YouApp.apk /system/app/YouApp.apk", esto hará que tu aplicación sea una aplicación del sistema; 3) inicie su aplicación y verifique si el código de prueba está funcionando o no.En caso afirmativo, no parece haber otra alternativa, salvo firmar la aplicación por certificado de plataforma o convertirla en una aplicación de sistema. O puede esperar para ver si alguien más tiene una idea mejor. –

+0

Gracias por la información. Realmente ayudó :) – CodingDecoding

7

A partir del nivel de API 19, Google has added API.

  • Context.getExternalFilesDirs()
  • Context.getExternalCacheDirs()
  • Context.getObbDirs()

Aplicaciones no debe permitirse escribir en dispositivos de almacenamiento externos secundarios, excepto en sus directorios de paquete específico según lo permitido por permisos sintetizados. Restringir las escrituras de esta manera garantiza que el sistema pueda limpiar los archivos cuando las aplicaciones se desinstalan.

El siguiente es un enfoque para obtener el directorio específico de la aplicación en la tarjeta SD externa con rutas absolutas.

Context _context = this.getApplicationContext(); 

File fileList2[] = _context.getExternalFilesDirs(Environment.DIRECTORY_DOWNLOADS); 

if(fileList2.length == 1) { 
    Log.d(TAG, "external device is not mounted."); 
    return; 
} else { 
    Log.d(TAG, "external device is mounted."); 
    File extFile = fileList2[1]; 
    String absPath = extFile.getAbsolutePath(); 
    Log.d(TAG, "external device download : "+absPath); 
    appPath = absPath.split("Download")[0]; 
    Log.d(TAG, "external device app path: "+appPath); 

    File file = new File(appPath, "DemoFile.png"); 

    try { 
     // Very simple code to copy a picture from the application's 
     // resource into the external file. Note that this code does 
     // no error checking, and assumes the picture is small (does not 
     // try to copy it in chunks). Note that if external storage is 
     // not currently mounted this will silently fail. 
     InputStream is = getResources().openRawResource(R.drawable.ic_launcher); 
     Log.d(TAG, "file bytes : "+is.available()); 

     OutputStream os = new FileOutputStream(file); 
     byte[] data = new byte[is.available()]; 
     is.read(data); 
     os.write(data); 
     is.close(); 
     os.close(); 
    } catch (IOException e) { 
     // Unable to create file, likely because external storage is 
     // not currently mounted. 
     Log.d("ExternalStorage", "Error writing " + file, e); 
    } 
} 

salida del registro desde arriba se ve así:

context.getExternalFilesDirs() : /storage/extSdCard/Android/data/com.example.remote.services/files/Download 

external device is mounted. 

external device download : /storage/extSdCard/Android/data/com.example.remote.services/files/Download 

external device app path: /storage/extSdCard/Android/data/com.example.remote.services/files/ 
0

He resuelto este problema mediante la eliminación de la android:maxSdkVersion="18" en uses-permission en el archivo de manifiesto. Es decir utilizar esto:

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

en lugar de:

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

Comprobar si el usuario está teniendo el permiso de almacenamiento externo o no. De lo contrario, utilice el directorio de caché para guardar el archivo.

final boolean extStoragePermission = ContextCompat.checkSelfPermission(
       context, Manifest.permission.WRITE_EXTERNAL_STORAGE) 
       == PackageManager.PERMISSION_GRANTED; 

      if (extStoragePermission && 
     Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) { 
       parentFile = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); 
      } 
      else{ 
       parentFile = new File(context.getCacheDir(), Environment.DIRECTORY_PICTURES); 
      }