2011-07-07 14 views
7

Necesito obtener imágenes junto con otros datos (muy similares al correo electrónico con archivos adjuntos) en el servidor. También necesito hacerlo de manera confiable para poder volver a intentarlo, etc. en caso de falla.Android cargando imágenes al servidor de la manera más eficiente

El servidor es WCF REST y hago muchas otras comunicaciones con él (JSON) pero acabo de recibir este nuevo requisito para cargar imágenes.

Como utilizo JSON para publicar datos en mi servidor, utilizo GSON en el lado de Android para serializar datos.

Así es como lo tengo implementado hasta el momento (todo lo demás funciona de esta manera, pero me acaba de comenzar con imágenes)

  1. usuario campos de actividad de llenado (datos de texto)
  2. usuario toma un cierto cuadro (s) a través de los intentos de cámara. Actualmente solo uso 1 archivo para las imágenes
  3. Tomo la foto desde la tarjeta SD, la carga/redimensiona - muestra en ImageView y almacena en el byte []
  4. El usuario envía - Tomo todos los datos junto con las imágenes de byte [] y pongo en objeto Java
  5. convertidor GSON llamadas y serializar objetos
  6. Guardar objeto en SQLite
  7. AsyncTask ve en SQLite para los registros, se abre el cursor y obtener de texto
  8. AsyncTask crea HTTPConnection y mensajes de datos de texto a mi servidor.
  9. FINAL

Ahora a mis problemas .. obviamente en # 3 - I "explotar" carnero con mis matrices de bytes. En algún momento incluso siento que mi Nexus S se vuelve lento. Pero al hacer eso, evito llenar la tarjeta SD o la carpeta de la aplicación con muchos archivos. Tomo una foto y luego la agarro. La siguiente imagen sobrescribirá la anterior.

El paso # 5 ES lento. No probé el serializador personalizado en GSON y en vez de serializar una matriz de bytes en algo como [1, -100,123, -12] puedo obtener un tamaño mucho más pequeño con Base64 pero aún así. Será lento. Y puedo tener hasta 20 imágenes ...

El paso # 6 no es problema. Pero con cierto tamaño (probé imagen de 300) empecé a error en el paso 7 en OpenCursor

07-06 20:28:47.113: ERROR/CursorWindow(16292): need to grow: mSize = 1048576, size = 925630, freeSpace() = 402958, numRows = 2 
07-06 20:28:47.113: ERROR/CursorWindow(16292): not growing since there are already 2 row(s), max size 1048576 
07-06 20:28:47.113: ERROR/Cursor(16292): Failed allocating 925630 bytes for text/blob at 1,1 

Por lo tanto, todo esto no es algo que me gusta. Lo ideal es que todos los datos se carguen en una sola pieza en el servidor.

Estaba pensando en almacenar imágenes marcadas con la fecha en la tarjeta SD y almacenar solo su nombre en la base de datos. Que los procesaría justo antes de enviarlos al servidor. Y en cuanto al éxito, eliminaría esas imágenes. Este tipo de lógica hará que el esquema de SQLite sea mucho más complejo, pero tal vez no haya una mejor manera.

Supongo que estoy buscando las mejores prácticas para tratar con imágenes.Cómo hacer followin con un mínimo uso de memoria/CPU:

  1. Tomar foto
  2. visualización de miniaturas
  3. Redimensionar
  4. enviaría al servidor

EDIT 1:

Actualmente Estoy investigando la posibilidad de cargar shizang completo como un mensaje MIME de varias partes. Eso requeriría agregar algunos JAR a mi paquete de Android. Además no estoy seguro de qué tan efectivo será de código de Apache para cargar imágenes y enviarlas (supongo que mejor que mi código) http://okandroidletsgo.wordpress.com/2011/05/30/android-to-wcf-streaming-multi-part-binary-images/

y que iba a tener que lidiar con el análisis de todo esto en el lado WCF ya que no hay forma de hacerlo con .NET framework incorporado.

http://antscode.blogspot.com/2009/11/parsing-multipart-form-data-in-wcf.html

POR FAVOR DIME SI probado esto!

EDIT 2:

MIME no es bueno. No tiene ningún sentido, ya que serializa binario utilizando base 64 que es lo mismo ..

+1

¿Estás guardando la imagen en la base de datos? Eso haría explotar el tamaño de la base de datos y los usuarios se quejarán de que la aplicación ocupa demasiado espacio en el almacenamiento interno del teléfono y, de todos modos, solicitarán soporte para la aplicación2: ¿por qué no mantener las imágenes en la tarjeta sd? –

+0

@denis Encontré ese límite de tamaño de Cursor en Android de 1MB así que no es solo un problema con el almacenamiento interno, sino que también voy a llegar a ese límite fácilmente al guardar este tipo de datos en SQLite. Parece que usar almacenamiento externo es la forma correcta de manejar tales cosas – katit

Respuesta

16

Nadie respondió, pero aquí es lo que pensé manera difícil:

Regla # 1: Cuando se trata de imágenes - evitar el uso de objetos/memoria. Suena obvio, pero no lo es. Pensé que cambiar el tamaño de la imagen a 800x600 está bien. Algo más grande: puede considerar dejarlo como está porque es posible hacer una secuencia http en un archivo más grande, pero es difícil trabajar con excepciones OOM cuando carga imágenes en la memoria para procesar

Regla # 2: Cuando use GSON - use JsonWriter para completar la transmisión. De lo contrario, la memoria explotará. Que pasar esa corriente a HttpClient. JsonWriter escribirá en fragmentos y los datos se enviarán a medida que se procese.

Regla # 3: Ver la regla # 2. Funcionará bien para múltiples imágenes pequeñas. De esta forma, GSON los serializará uno por uno y los enviará a la transmisión. Cada imagen SERÁ cargada en la memoria de todos modos.

Regla # 4: Esta es probablemente la mejor solución, pero requiere una mayor coordinación con el servidor. Las imágenes se envían 1 por 1 antes de que el mensaje se envíe al servidor. Enviaron como transmisión sin ninguna codificación. De esta forma no tienen que estar codificados en base64 y no tienen que cargarse en la memoria del dispositivo. El tamaño de la transmisión será más pequeño también. Cuando se envían todas las imágenes: publique el objeto informativo principal y recopile todo el paquete en el servidor.

Regla # 5: Olvídate de almacenamiento BLOB de SQLite

En pocas palabras:

  • Es mucho más barato en términos de recursos para enviar imágenes sin ningún tipo de cambio de tamaño. Cambio de tamaño sólo tiene sentido cuando Obtén de hasta alrededor de 800x600-ish
  • Envío de imágenes múltiples en un solo paquete tiene sentido cuando la imagen de conseguir pequeños como 600x400-ish
  • Tan pronto como sea necesario para subir archivos - empezar a pensar corrientes en todas partes. NO cargue cosas en la memoria.
+0

Hola, Katit, gracias, suena lógico. ¿Hay algún fragmento en algún lugar para el dispositivo y el servidor? Me gustaría subir imágenes a un servidor. Estoy usando php ahora. – Diego

Cuestiones relacionadas