java - No se puede guardar el archivo de imagen en la actualización de Android Oreo. ¿Cómo hacerlo?
android-8.0-oreo (2)
No puedo guardar un archivo de imagen en Android Oreo (8.0) API 26.
El código funciona perfectamente en el nivel 25 de la API (7.0) y no encontré ningún cambio en la documentación "
Cambios de comportamiento de Android 8.0
"
Aqui esta mi codigo
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myrootDir = new File(root);
if (!myrootDir.exists()) {
myrootDir.mkdir();
}
File myDir = new File(root + "/Myimages");
if (!myDir.exists()) {
myDir.mkdir();
}
final String fname = System.currentTimeMillis()+"myimage.png";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
b.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
}catch (Exception e){
Log.e("MYAPP", "exception", e);
}
La excepción es FileNotFoundException, no existe tal archivo o directorio. (¿Pero por qué no en Android n?)
java.io.FileNotFoundException: /storage/emulated/0/Pictures/Myimages/1513151272243myimage.png (No such file or directory)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err: at java.io.FileOutputStream.open0(Native Method)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err: at java.io.FileOutputStream.open(FileOutputStream.java:287)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:171)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err: at com.package.package.DetailPage$12.run(DetailPage.java:737)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err: at android.os.Handler.handleCallback(Handler.java:789)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err: at android.os.Handler.dispatchMessage(Handler.java:98)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err: at android.os.Looper.loop(Looper.java:164)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6541)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err: at java.lang.reflect.Method.invoke(Native Method)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
De hecho, hay un ligero y sutil cambio en los permisos para las aplicaciones que se ejecutan y se dirigen a la API 26.
Anteriormente, a las aplicaciones se les otorgaban automáticamente todos los permisos en un grupo dado si el usuario había otorgado al menos un permiso en ese grupo.
Esto significa que a una aplicación a la que se le había otorgado
READ_EXTERNAL_STORAGE
se le
WRITE_EXTERNAL_STORAGE
otorgado
WRITE_EXTERNAL_STORAGE
inmediato, independientemente de si
WRITE_EXTERNAL_STORAGE
hubiera solicitado explícitamente.
A partir de Oreo, para las aplicaciones dirigidas a API 26+, esto se ha corregido, y solo se otorgarán los permisos que se solicitan explícitamente. Si el usuario ya ha otorgado un permiso en el mismo grupo, no habrá ninguna solicitud para el nuevo permiso, pero aún debe solicitarse.
Ese era el problema, en este caso.
Cuando se
READ_EXTERNAL_STORAGE
permiso
READ_EXTERNAL_STORAGE
a su aplicación en Nougat o inferior, también estaba obteniendo
WRITE_EXTERNAL_STORAGE
automáticamente, sin tener que solicitarlo específicamente.
Cuando intentas el mismo procedimiento para guardar archivos en Oreo, no
WRITE_EXTERNAL_STORAGE
automáticamente, por lo que la escritura finalmente falla.
Simplemente agregue una solicitud específica para
WRITE_EXTERNAL_STORAGE
.
Si el usuario ya ha otorgado
READ_EXTERNAL_STORAGE
, no se molestará con otra solicitud.
Alternativamente, puede solicitar únicamente
WRITE_EXTERNAL_STORAGE
desde el principio, lo que implícitamente incluye
READ_EXTERNAL_STORAGE
, y le ahorrará la necesidad de dos solicitudes separadas.
También estoy experimentando el mismo problema y estoy atrapado con este problema desde hace 2 meses. Ya he dado permiso para WRITE_EXTERNAL_STORAGE en el manifiesto primero y también comprobando si tiene permiso de escritura. Creo que no es un problema de permiso. Porque cuando pruebo con oreo la carpeta se está creando y hay un archivo de imagen dañado en la carpeta que estoy creando. Por eso no viene a la galería y luego al guardarlo me devuelve Imagen no capturada. Tengo este problema solo en Android 7.1.1 y Oreo. Hasta Android 7.0 está funcionando bien. He comprobado con los dispositivos Samsung Galaxy Note 8 y Google Pixel XL 2. Estoy usando una cámara personalizada con GPS y función inferior.
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
para guardar el byte de imagen y la función de guardar contiene el siguiente código
OutputStream output = null;
try {
output = new FileOutputStream(finalFile);
output.write(bytes);
} finally {
if (null != output) {
output.close();
}
}