sirve que para nand memoria interna funciona dispositivos cual como celular caracteristicas almacenamiento android file-permissions

android - que - ¿mkdir() funciona dentro del almacenamiento flash interno, pero no en la tarjeta SD?



para que sirve la memoria flash (4)

Intenta con esto. Funciona bien para mí.

final String NEW_FOLDER_NAME = "TestFolder"; String extStore = System.getenv("EXTERNAL_STORAGE"); File f_exts = new File(extStore, NEW_FOLDER_NAME); String secStore = System.getenv("SECONDARY_STORAGE"); File f_secs = new File(secStore, NEW_FOLDER_NAME); testPath(f_exts); textPath(f_secs);

y cambie el valor booleano en la función testPath siguiente manera

boolean success; if(path.exists()) { // already created success = true; } else { success = path.mkdir(); }

Si la carpeta ya existe, el método path.mkdir() devuelve falso.

y hecho.!!!

referencia de this pregunta.

Actualmente estoy creando una aplicación de administración de archivos que permite al usuario navegar por el sistema de archivos de su dispositivo. El usuario comienza en el directorio raíz / de su dispositivo, pero puede buscar cualquier ubicación que desee, como el almacenamiento flash interno o la tarjeta SD.

Uno de los requisitos críticos de esta aplicación es permitir al usuario crear nuevas carpetas en cualquier lugar. Una característica como esta sería inmensamente útil para la aplicación. Sin embargo, el método File#mkdir() no funciona en absoluto en el directorio de la tarjeta SD.

Agregué los permisos apropiados al archivo de manifiesto. También escribí una prueba para ver qué directorios (todos los cuales existen en mi dispositivo Lollipop 5.0) permiten la creación de una nueva carpeta. Según mis observaciones, el File#mkdir() solo funciona cuando está dentro del directorio de almacenamiento flash interno.

Nota: no confunda Environment#getExternalStorageDirectory() con la ubicación de la tarjeta SD, como se explica en este artículo . También en Lollipop 5.0, creo que /storage/emulated/0/ y /storage/sdcard0/ refieren al almacenamiento flash interno, mientras que /storage/emulated/1/ y /storage/sdcard1/ refieren a la tarjeta SD (que es al menos cierto para el dispositivo con el que estoy probando).

¿Cómo puedo crear nuevos archivos y carpetas en áreas fuera de la ruta de almacenamiento externo en dispositivos Android no rooteados?

Manifiesto:

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

Prueba:

... public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final String NEW_FOLDER_NAME = "TestFolder"; testPath(new File(Environment.getExternalStorageDirectory(), NEW_FOLDER_NAME)); testPath(new File("/storage/emulated/0/", NEW_FOLDER_NAME)); testPath(new File("/storage/emulated/1/", NEW_FOLDER_NAME)); testPath(new File("/storage/sdcard0/Download/", NEW_FOLDER_NAME)); testPath(new File("/storage/sdcard1/Pictures/", NEW_FOLDER_NAME)); } private void testPath(File path) { String TAG = "Debug.MainActivity.java"; String FOLDER_CREATION_SUCCESS = " mkdir() success: "; boolean success = path.mkdir(); Log.d(TAG, path.getAbsolutePath() + FOLDER_CREATION_SUCCESS + success); path.delete(); } }

Salida:

/storage/emulated/0/TestFolder mkdir() success: true /storage/emulated/0/TestFolder mkdir() success: true /storage/emulated/1/TestFolder mkdir() success: false /storage/sdcard0/Download/TestFolder mkdir() success: true /storage/sdcard1/Pictures/TestFolder mkdir() success: false


Primero, debe tener en cuenta que file.mkdir() y file.mkdirs() devuelve false si el directorio ya existía. Si desea saber si el directorio existe en la devolución, use (file.mkdir() || file.isDirectory()) o simplemente ignore el valor de retorno y llame a file.isDirectory() (consulte la documentación).

Dicho esto, su verdadero problema es que necesita permiso para crear el directorio de almacenamiento extraíble en Android 5.0+. Trabajar con tarjetas SD extraíbles en Android es horrible.

En Android 4.4 (KitKat), Google restringió el acceso a las tarjetas SD (consulte here , here y here ). Vea esta respuesta de que lleva a esta publicación XDA si necesita crear un directorio en una tarjeta SD extraíble en Android 4.4 (KitKat).

En Android 5.0 (Lollipop), Google introdujo nuevas API de acceso a tarjetas SD. Para ver ejemplos de uso, consulte esta respuesta de .

Básicamente, debe usar DocumentFile#createDirectory(String displayName) para crear su directorio. Deberá solicitar al usuario que otorgue permisos a su aplicación antes de crear este directorio.

NOTA: Esto es para almacenamiento extraíble. El uso del File#mkdirs() funcionará en el almacenamiento interno (que a menudo se confunde con el almacenamiento externo en Android) si tiene el permiso android.permission.WRITE_EXTERNAL_STORAGE .

Publicaré un código de ejemplo a continuación:

Marque si necesita pedir permiso:

File sdcard = ... // the removable SD card List<UriPermission> permissions = context.getContentResolver().getPersistedUriPermissions(); DocumentFile documentFile = null; boolean needPermissions = true; for (UriPermission permission : permissions) { if (permission.isWritePermission()) { documentFile = DocumentFile.fromTreeUri(context, permission.getUri()); if (documentFile != null) { if (documentFile.lastModified() == sdcard.lastModified()) { needPermissions = false; break; } } } }

A continuación (si needPermissions es true ), puede mostrar un cuadro de diálogo para explicarle al usuario que debe seleccionar la "Tarjeta SD" para otorgar permisos a su aplicación para crear archivos / directorios y luego iniciar la siguiente actividad:

if (needPermissions) { // show a dialog explaining that you need permission to create the directory // here, we will just launch to chooser (what you need to do after showing the dialog) startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), STORAGE_REQUEST_CODE); } else { // we already have permission to write to the removable SD card // use DocumentFile#createDirectory }

Ahora deberá verificar el resultCode y onActivityResult en onActivityResult :

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == STORAGE_REQUEST_CODE && resultCode == RESULT_OK) { File sdcard = ... // get the removable SD card boolean needPermissions = true; DocumentFile documentFile = DocumentFile.fromTreeUri(MainActivity.this, data.getData()); if (documentFile != null) { if (documentFile.lastModified() == sdcard.lastModified()) { needPermissions = false; } } if (needPermissions) { // The user didn''t select the "SD Card". // You should try the process over again or do something else. } else { // remember this permission grant so we don''t need to ask again. getContentResolver().takePersistableUriPermission(data.getData(), Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // Now we can work with DocumentFile and create our directory DocumentFile doc = DocumentFile.fromTreeUri(this, data.getData()); // do stuff... } return; } super.onActivityResult(requestCode, resultCode, data); }

Eso debería darle un buen comienzo para trabajar con DocumentFile y tarjetas SD extraíbles en Android 5.0+. Puede ser una PITA.

Además, no hay una API pública para obtener la ruta a una tarjeta SD extraíble (si es que existe). ¡No debe confiar en la codificación "/storage/sdcard1" ! Hay bastantes publicaciones al respecto en . Muchas de las soluciones usan la variable de entorno SECONDARY_STORAGE . A continuación hay dos métodos que puede usar para encontrar dispositivos de almacenamiento extraíbles:

public static List<File> getRemovabeStorages(Context context) throws Exception { List<File> storages = new ArrayList<>(); Method getService = Class.forName("android.os.ServiceManager") .getDeclaredMethod("getService", String.class); if (!getService.isAccessible()) getService.setAccessible(true); IBinder service = (IBinder) getService.invoke(null, "mount"); Method asInterface = Class.forName("android.os.storage.IMountService$Stub") .getDeclaredMethod("asInterface", IBinder.class); if (!asInterface.isAccessible()) asInterface.setAccessible(true); Object mountService = asInterface.invoke(null, service); Object[] storageVolumes; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { String packageName = context.getPackageName(); int uid = context.getPackageManager().getPackageInfo(packageName, 0).applicationInfo.uid; Method getVolumeList = mountService.getClass().getDeclaredMethod( "getVolumeList", int.class, String.class, int.class); if (!getVolumeList.isAccessible()) getVolumeList.setAccessible(true); storageVolumes = (Object[]) getVolumeList.invoke(mountService, uid, packageName, 0); } else { Method getVolumeList = mountService.getClass().getDeclaredMethod("getVolumeList"); if (!getVolumeList.isAccessible()) getVolumeList.setAccessible(true); storageVolumes = (Object[]) getVolumeList.invoke(mountService, (Object[]) null); } for (Object storageVolume : storageVolumes) { Class<?> cls = storageVolume.getClass(); Method isRemovable = cls.getDeclaredMethod("isRemovable"); if (!isRemovable.isAccessible()) isRemovable.setAccessible(true); if ((boolean) isRemovable.invoke(storageVolume, (Object[]) null)) { Method getState = cls.getDeclaredMethod("getState"); if (!getState.isAccessible()) getState.setAccessible(true); String state = (String) getState.invoke(storageVolume, (Object[]) null); if (state.equals("mounted")) { Method getPath = cls.getDeclaredMethod("getPath"); if (!getPath.isAccessible()) getPath.setAccessible(true); String path = (String) getPath.invoke(storageVolume, (Object[]) null); storages.add(new File(path)); } } } return storages; } public static File getRemovabeStorageDir(Context context) { try { List<File> storages = getRemovabeStorages(context); if (!storages.isEmpty()) { return storages.get(0); } } catch (Exception ignored) { } final String SECONDARY_STORAGE = System.getenv("SECONDARY_STORAGE"); if (SECONDARY_STORAGE != null) { return new File(SECONDARY_STORAGE.split(":")[0]); } return null; }


en Kitkat, Google restringió el acceso a la tarjeta SD externa, por lo que no podrá escribir en Almacenamiento externo en Kitkat.

En Lollipop, Google creó un nuevo FrameWork para escribir datos en un almacenamiento externo. Debe usar el nuevo DocumentFile

clase que es compatible con versiones anteriores.

Básicamente, puede solicitar el permiso al inicio de la aplicación para el directorio raíz de la aplicación y luego puede crear el directorio


path.mkdir() falla también cuando el directorio ya existe. Puede agregar un cheque primero:

if (!path.exists()) { boolean success = path.mkdir(); Log.d(TAG, path.getAbsolutePath() + FOLDER_CREATION_SUCCESS + success); path.delete(); } else { Log.d(TAG, path.getAbsolutePath() + "already exists"); }