samsung - Android M escribe en la tarjeta SD-Permiso denegado
permisos tarjeta sd xiaomi (8)
Estoy intentando copiar un archivo desde mi aplicación a la tarjeta SD, pero recibo los errores de error (permiso denegado) . El sistema operativo es Android M y he permitido permisos de almacenamiento en tiempo de ejecución (verificada en la información de la aplicación). También he establecido los permisos de uso en AndroidManifest.xml
<application>...</application>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
No funciona si copio a la tarjeta SD
Source: data/user/0/com.example.myapp/cache/SomeFile.txt
Destination: /storage/1032-2568/SomeFolder/
Error: java.io.FileNotFoundException: /storage/1032-2568/SomeFolder/SomeFile.txt: open failed: EACCES (Permission denied)
Funciona si copio al almacenamiento interno.
Source: data/user/0/com.example.myapp/cache/SomeFile.txt
Destination: /storage/emulated/0/SomeFolder/
Código para copiar el archivo de origen a destino.
/*
* Below are the parameters I have tried
*
* inputPath - data/user/0/com.example.myapp/cache or data/user/0/com.example.myapp/cache/
* inputFile - /SomeFile.txt or SomeFile.txt
* outputPath - /storage/1032-2568/SomeFolder/ or /storage/1032-2568/SomeFolder
*/
public static void copyFile(String inputPath, String inputFile, String outputPath) {
InputStream in = null;
OutputStream out = null;
try {
//create output directory if it doesn''t exist
File dir = new File (outputPath);
if (!dir.exists()) {
dir.mkdirs();
}
in = new FileInputStream(inputPath + inputFile);
out = new FileOutputStream(outputPath + inputFile);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
// write the output file (You have now copied the file)
out.flush();
out.close();
}
catch (FileNotFoundException fnfe1) {
/* I get the error here */
Log.e("tag", fnfe1.getMessage());
}
catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
ES File Explorer
Vi que ES File Explorer tampoco puede escribir nada en la tarjeta SD en dispositivos Redmi. Aquí hay un video con solución . Siguiendo los pasos trabajados para ES Explorer en mi dispositivo. ¿Se puede hacer esto programáticamente?
A partir de la Api 23 y superiores, debe solicitar permisos explícitamente. Como ha mencionado, está solicitando permiso de tiempo de ejecución. Te sugeriré que hagas esto:
En tu Fragmento o Actividad
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_CODE);
else
copyFile(params...);
Luego anula este método en la Actividad / Fragmento
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
switch (requestCode) {
case PERMISSION_CODE:
copyFile(params...);
break;
}
}
// if user checks "don''t show again" and presses deny on the permission dialog
// then it will not show up again, in that case you need to show some message to the user
// to go in the settings and enable permissions manually
else if (!ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ToastManager.showLongToast(getActivity(), "Go to app settings and turn on permissions to enjoy complete features");
}
Debe agregar el tiempo de ejecución de la solicitud de permiso en Android 6.0 (nivel de API 23) y más, aquí están los documentos official
Este es el código para WRITE_EXTERNAL_STORAGE
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG,"Permission is granted");
return true;
}
Pide permiso de otra manera como esta
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
Después de Android 4.3 en algunos dispositivos, no puede obtener acceso directo de escritura a FileSystem en la tarjeta SD.
Debe utilizar el marco de acceso de almacenamiento para eso.
No puede copiar o eliminar archivos y carpetas en un almacenamiento externo usando una aplicación de terceros. como [explorador de archivos].
Es la política de datos actualizada después de la versión KITKAT .
Si solo se permiten en las aplicaciones del sistema. Así que puedes usar un explorador de archivos original (Come from ROM).
Si necesita utilizar una aplicación de terceros, ROOT su dispositivo. (Se requiere permiso de root)
Parece que los permisos de tiempo de ejecución se implementan correctamente, pero los problemas parecen estar en el dispositivo. Si está utilizando Redmi, debe permitir manualmente el permiso de una aplicación específica en la configuración de seguridad de Redmi. Este link muestra cómo habilitar los permisos en la seguridad de Redmi.
Puedo ver que está copiando todo el contenido de un archivo y tratando de escribir lo mismo en otro archivo. Podría sugerir una mejor manera de hacer esto:
Suponiendo que ya verificaste la existencia del archivo
StringWriter temp=new StringWriter();
try{
FileInputStream fis=new FileInputStream(inputFile+inputPath);
int i;
while((i=fis.read())!=-1)
{
temp.write((char)i);
}
fis.close();
FileOutputStream fos = new FileOutputStream(outputPath, false); // true or false based on opening mode as appending or writing
fos.write(temp.toString(rs1).getBytes());
fos.close();
}
catch (Exception e){}
Este código funcionó para mi aplicación ... Avíseme si esto funciona para usted o no ...
Según lo sugerido por @CommonsWare aquí, tenemos que usar el nuevo Storage Access Framework provisto por Android y tendremos que tomar el permiso del usuario para escribir el archivo de la tarjeta SD, ya que dijo que esto ya está escrito en el Administrador de archivos de la aplicación File Manager.
Aquí está el código para que el usuario elija la "tarjeta SD":
startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), requestCode);
que se verá algo así:
Y obtenga la ruta del documento en pickedDir
y pase más allá en su bloque copyFile y use esta ruta para escribir el archivo:
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (resultCode != RESULT_OK)
return;
else {
Uri treeUri = resultData.getData();
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
copyFile(sdCard.toString(), "/File.txt", path + "/new", pickedDir);
}
}
public void copyFile(String inputPath, String inputFile, String outputPath, DocumentFile pickedDir) {
InputStream in = null;
OutputStream out = null;
try {
//create output directory if it doesn''t exist
File dir = new File(outputPath);
if (!dir.exists()) {
dir.mkdirs();
}
in = new FileInputStream(inputPath + inputFile);
//out = new FileOutputStream(outputPath + inputFile);
DocumentFile file = pickedDir.createFile("//MIME type", outputPath);
out = getContentResolver().openOutputStream(file.getUri());
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
// write the output file (You have now copied the file)
out.flush();
out.close();
} catch (FileNotFoundException fnfe1) {
/* I get the error here */
Log.e("tag", fnfe1.getMessage());
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
También tengo ese problema, pero resolví mediante el uso del permiso de solicitud en tiempo de ejecución y después de dar el permiso a la fuerza. Después del permiso en la información de la aplicación del dispositivo Android. después de declarar el permiso en manifiesto => vaya a la configuración de su dispositivo => vaya a información de la aplicación => vaya a permiso => y finalmente permita el permiso. solo recuerda que acabo de hablar después de api nivel 22 significa de malvavisco.