Spanish [SOLUCIONADO] ERROR DE LA CÁMARA AL GUARDAR FOTOS EN DISPOSITIVO XIAOMI MI9

Anton Solans Argemí

Active Member
Licensed User
Buenos días,

He desarrollado una APP donde realizo y guardo una foto con el método siguiente:

B4X:
Sub [B]camera[/B](Directory As String, PictureName As String)
Dim i As Intent
onoff = True
i.Initialize("android.media.action.IMAGE_CAPTURE", "" )
i.PutExtra("crop", "true") 'crop ON
i.PutExtra("aspectX", 0) 'crop aspects
i.PutExtra("aspectY", 0) 'crop aspects
i.PutExtra("outputX", 200) 'crop size
i.PutExtra("outputY", 150) 'crop size
i.PutExtra("output", ParseUri("file://" & File.Combine(Directory, PictureName)))
StartActivity(i)
End Sub

Sub [B]ParseUri[/B](FileName As String) As Object
Dim r As Reflector
Return r.RunStaticMethod("android.net.Uri", "parse", Array As Object(FileName), Array As String("java.lang.String"))
End Sub

[endcode]

y en todos los dispositivos que he instalado la APP de distintas marcas me está funcionando perfectamente. Pero al instalar la APP en un Xiami MI9 da un error de 'Cámara sigue sin funcionar' y no me guarda la foto.  En el MANIFEST he añadido <uses-permission android:name="android.permission.CAMERA" />   pero tampoco me funciona.
 

josejad

Expert
Licensed User
Longtime User
¿Qué versión de Android tiene ese Xiaomi?

Para solicitar permiso para usar la cámara, no es suficiente con ponerlo en el manifest, además, hay que solicitarlo explícitamente, y tener el targetSdkVersion como 26+.

 

Anton Solans Argemí

Active Member
Licensed User
Pero esto puede ser el motivo por el cual me de este error? Porque hasta ahora no tenía puesta la línea en el manifest y funcionaba ok en los otros móviles instalados.
 

josejad

Expert
Licensed User
Longtime User
Bueno, no estoy totalmente seguro, tampoco nos das muchos datos.
¿Qué tienes puesto en tu línea de manifest?
B4X:
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="26"/>

¿Estás usando este ejemplo? Si es así, no debe tratarse de permisos:


No tienes posiblidad de conectar ese Xiaomi a tu ordenador con USB en modo depuración o con B4A Bridge para ver qué error te está lanzando?[/code]
 

Anton Solans Argemí

Active Member
Licensed User
En mi Manifest tengo puesto

B4X:
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="19"/>
[endcode]

El Xiaomi no lo tengo en la oficina, probaré de pasarme por el cliente para poder depurarlo.
 

Anton Solans Argemí

Active Member
Licensed User
Buenas de nuevo,

No he podido todavía debugar el proceso pero lo he probado en otro dispositivo XIAOMI y me sucede lo mismo. De este último tengo la información que da el móbil cuando sale el mensaje 'Cámara sigue sin funcionar' y pulso 'Información de la aplicación'.
A ver si este mensaje sirve de ayuda:
 

Attachments

  • IMG-20200303-WA0022.jpg
    IMG-20200303-WA0022.jpg
    229.5 KB · Views: 286

josejad

Expert
Licensed User
Longtime User
Pues tiene pinta de que estás intentando guardar la imagen en un directorio protegido.
Revisa el tutorial de los permisos, prueba a solicitarlos y prueba a guardar en otro directorio, por ejemplo en RuntimePermissions.GetSafeDirDefaultExternal("").

Si ya tienes ese XIAOMI, conectalo con B4A Bridge o con USB al ordenador y ejecuta tu app en modo Debug, a ver qué aparece en el Log cuando salta el error.

saludos,
 

Anton Solans Argemí

Active Member
Licensed User
El problema es que no los tengo. Enseguida que pueda tenir alguno en la oficina hago la prueba del Debug.
Gracias, de todos modos me miro lo de los permisos que me comentas.
 

drgottjr

Expert
Licensed User
Longtime User
sí, el mensaje lo dice todo: FileUriExposedException
lee aquí:
https://developer.android.com/reference/android/os/FileUriExposedException

no hace falta el permiso de cámara para un "intent" de cámara, pues se trata de una app que ya tiene permiso de cámara (permiso propio, ¿no?).
pero, sí lo que posiblemente te hace falta es el permiso de PERMISSION_WRITE_EXTERNAL_STORAGE (según la carpeta donde pretendes
guardar la foto). como sugiere don j.j.a más arriba.

tu código funciona en mi aparato de pruebas (nexus 5 os 8.1)
 

Anton Solans Argemí

Active Member
Licensed User
En el Manifest tengo puesto:

B4X:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"  android:maxSdkVersion="19" />
[endcode]

¿Sería correcto?

No podría ser algo en particular de los XIAOMI? Porque de momento con el resto de móbiles me funciona.
 

drgottjr

Expert
Licensed User
Longtime User
yo no quería decirlo, pero algo no suena con respecto a tus xiomis... sobretodo ya que occure el mismo problema en 2 aparatos distintos de la misma marca, pero no en aparatos de otra marca. la cámara y su funcionamiento son a menudo cuestión de fabricante, y no de google. se ha hablado mucho de ello aquí en el forum.

yo de tí, si la app no está terminada (o sea, desallorada), más vale dejar de lado los xiomis. será imposible desarollar una app si el aparato en que la pruebas está sospechoso. si la app sí está finalizada, entonces te hará falta la ayuda de algún usuario (experto) de xiomi. o buscar en la red. lo siento.

en cuanto a la app, hay varios problemas no solo con el manifest sino tambien dentro de la app. (problemas que posiblemente afectan tus xiomis. eso sí.)
mucho depende de si pretendes lanzar la app en play. en cambio, si la app es para tí sólo, entonces la cuestión de permisos se pone un tanto irrelevante.
leyendo el hilo aquí, veo que te han dicho bastante, pero tendrás que estudiar.

añadiendo declaraciones al manifest es a menudo solo el primer paso. luego tienes que tomar ciertos pasos dentro de la app (cuales pasos se refieren a declaraciones hechas en la manifest). por ejemplo, si declaras en el manifest que tu app quiere acceder a archivos externos (de tu app). luego, tienes que
confirmar esto en la app mediante un diálogo con el usuario. de esto hay muchísimos ejemplos. en cambio, si la app es para tí, puedes evitar mucho de esta complejidad al limitar el "targetSDK" a un sdk muy bajo. si la app es para play, entonces el "targetSDK" tiene que ser 28, lo que incurre toda una serie de cambios al manifest así como código para cumplir con las exigencias de google. tienes que familiarizarte con todo esto. como he dicho, hay muchísimos ejemplos en el forum.
 

Anton Solans Argemí

Active Member
Licensed User
Después de probar la APP en dos dispositivos distintos XIAOMI y otro HUAWEY he detectado que el método que utilizaba para hacer fotos no acababa de funcionar. Tras leer varios foros tomé la decisión de cambiar de método y utilizar el CameraEx y funciona correctamente con las marcas testeadadas hasta el momento Samsung,Xiaomi,Huawey pero tengo una duda que a continuación expongo:

Cuando hago una foto quiero que allí mismo se me previsualice y yo preguntar si quiere Cancelar (salir de la cámara),,Reintentar (volver a hacer la foto),Aceptar (Guardar la foto) pero no se como hacer la previsualización de la foto, es decir, hacer la foto y que se pare.
 

drgottjr

Expert
Licensed User
Longtime User
cuanda sacas una foto con camex, camex lanza un "event" (_PictureTaken) con la imagen sacada en forma de datos. tu manejas este "event".
primero, conviertes los datos a un bitmap con BytesToImage() (vease mas abajo)
luego asignas este bitmap a una imageview que haces visible en pantalla
luego paras el "preview" y sueltas la camara y terminas

B4X:
Public Sub BytesToImage(bytes() As Byte) As Bitmap
    Dim In As InputStream
    In.InitializeFromBytesArray(bytes, 0, bytes.Length)
    Dim bmp As Bitmap
    bmp.Initialize2(In)
    In.Close
    Return bmp
End Sub

dicho todo esto, no comprendo cómo es posible que no logras lanzar la cámara con un intent en ninguno de los dispositivos. manejar la cámara tu mismo, y sobretodo para tus propósitos, no es de lo más fácil. algo no suena. pero lo de arriba te daría una foto para visualizar antes de proceder. si al usuario no le gusta y quiere sacar otra, haces desaparecer la imageview, arrancas la preview nuevamente y vuelves al principio.
 

electronicajaf

Member
Licensed User
Longtime User
Buenos días,

He desarrollado una APP donde realizo y guardo una foto con el método siguiente:

B4X:
Sub [B]camera[/B](Directory As String, PictureName As String)
Dim i As Intent
onoff = True
i.Initialize("android.media.action.IMAGE_CAPTURE", "" )
i.PutExtra("crop", "true") 'crop ON
i.PutExtra("aspectX", 0) 'crop aspects
i.PutExtra("aspectY", 0) 'crop aspects
i.PutExtra("outputX", 200) 'crop size
i.PutExtra("outputY", 150) 'crop size
i.PutExtra("output", ParseUri("file://" & File.Combine(Directory, PictureName)))
StartActivity(i)
End Sub

Sub [B]ParseUri[/B](FileName As String) As Object
Dim r As Reflector
Return r.RunStaticMethod("android.net.Uri", "parse", Array As Object(FileName), Array As String("java.lang.String"))
End Sub

[endcode]

y en todos los dispositivos que he instalado la APP de distintas marcas me está funcionando perfectamente. Pero al instalar la APP en un Xiami MI9 da un error de 'Cámara sigue sin funcionar' y no me guarda la foto.  En el MANIFEST he añadido <uses-permission android:name="android.permission.CAMERA" />   pero tampoco me funciona.
Buenos días, perdon por cualquier desprolijidad pero es la primera vez que respondo algo. Esto me pasa con las versiones nuevas de Android. Supongo que habras agregado los permisos de escritura en el Manifiesto así:
AddManifestText(<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>)
El problema que están teniendo todos los que quieren usar este código hoy es el siguiente y espero ser claro:
1- Tu aplicación tiene permisos para escribir el archivo realmente. Esto lo comprobas escribiendo un archivo de texto con algo dentro. Ej. File.WriteString(shared, "xxxx.txt", "Escribo algo dentro del archivoxxx") en la variable "shared" tengo la ruta que me da esta linea : "shared = rp.GetSafeDirDefaultExternal("fotos") "
2- Seguramente en el directorio de la aplicación aparece el nombre de la Imagen con su extensión pero de tamaño 0 bit.
3- El tema radica en que LA APLICACIÓN del telefono que llamás, NO TIENE PERMISOS para escribir en la carpeta de tu aplicación.
Solución Probada: Declaro como directorio destino la carpeta DCIM, ahí se va a escribir correctamente el archivo .jpg. Luegon con File.copyAsync(carpetaOrigen, foto.jpg, carpetaDestino, foto.jpg) la copias a la carpeta de tu aplicación, o donde quieras, pero que tengas permisos.
Luego que veas que esto funciona pode eliminarla de la carpeta DCIM con File.Delete(DCIM, Foto.jpg)
Ojo
con los tiempos de copia y delete, dale 1 segundo o menos para que se establescan los datos.
Saludos y espero que te sirva a vos y a todos los que buscamos auxilio en este lugar.
PD: Si hace falta paso la aplicación.
 
Last edited:
Top