Toon posts:

[j2me] binnenhalen chunked png-image lukt niet op mobiel!

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo dames en heren,

Ik heb gezocht en gezocht en gezocht en gezocht... Google noch Google Groups bracht uitkomst. :(

Het betreft namelijk het volgende:

Ik ben een midlet (j2ME) aan het schrijven voor MIDP 1.0 compliant mobiele telefoons. Één van de zaken die deze applicatie dient te kunnen is om een PNG-plaatje op te halen van een website (http) en die op het schermpje van de mobiele telefoon te tonen.

Na wat zoeken vond ik example code van een memberfunction getImage die in deze functionaliteit zou moeten voorzien:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*--------------------------------------------------
* Open an http connection and download a png file
* into a byte array.
*-------------------------------------------------*/
private Image getImage(String url) throws IOException
{
  ContentConnection connection = (ContentConnection) Connector.open(url);
  DataInputStream iStrm = connection.openDataInputStream();    
        
  Image im = null;

  try
  {
    // ContentConnection includes a length method
    byte imageData[];
    int length = (int) connection.getLength();
    if (length != -1)
    {
      imageData = new byte[length];

      // Read the png into an array        
      iStrm.readFully(imageData);
    }
    else  // Length not available...
    {       
      ByteArrayOutputStream bStrm = new ByteArrayOutputStream();       
        
      int ch;
      while ((ch = iStrm.read()) != -1)
        bStrm.write(ch);
        
      imageData = bStrm.toByteArray();
      bStrm.close();                
    }

    // Create the image from the byte array
    im = Image.createImage(imageData, 0, imageData.length);        
  }
  finally
  {
    // Clean up
    if (iStrm != null)
      iStrm.close();
    if (connection != null)
      connection.close();
  }
  return (im == null ? null : im);
}


De bovenstaande code leest een png-plaatje van het web in, plaatst die in een array, en converteert dat array vervolgens naar een interne image die vervolgens afgebeeld kan worden.

Er zijn zoals jullie kunnen zien twee verschillende codepaths: één die gebruik maakt van de member function "readFully" als de webserver van te voren de header "Content-Length" meestuurt met daarin het aantal te versturen bytes. De ander is een fallback-algoritme die de data gewoonweg byte per byte inleest als de Content-Length niet van te voren is opgegeven. Dit is bijvoorbeeld het geval als de http-data in "chunked"-mode wordt geserveerd.

Nou heb ik een PHP-pagina gemaakt die als GET-parameters de height en/of width van een plaatje accepteert en het te tonen plaatje vervolgens server-side rescaled, alvorens die via Apache in PNG-formaat te serveren. Omdat het geresizede PNG-plaatje on-the-fly wordt gegenereerd, stuurt Apache geen Content-Length mee, maar wordt de data dus chunked verzonden.

Nu volgt (eindelijk ;) ) mijn probleem:

Als ik met een aantal J2ME-phone-simulators op mijn development-PC de code test, dan werkt deze probleemloos met zowel statisch geserveerde PNG's als met dynamisch door PHP gegenereerde PNG's.

Dit gaat echter fout als ik met werkelijke mobieltjes test. Ik heb zowel met een Nokia 6600 als met een SonyEricsson P900 getest. In beide gevallen werkt weliswaar het ophalen van een statisch plaatje (waarbij Content-Length bekend is en readFully wordt gebruikt) probleemloos, maar maken de phones er een behoorlijk zooitje van, zodra ze een PNG-image in chunked vorm van een webserver proberen in te laden. Ten eerste wordt de data inhoudelijk op veel punten "verminkt" en ten tweede wordt slechts een fractie (in mijn geval 196 bytes) van de file ingelezen.

Nou kan dit liggen aan het feit dat de client één of ander ACK-bericht naar de server moet sturen voor elke aparte chunk en dat de chunks wellicht ook reassembled zouden moeten worden (wat dan ook meteen de inhoudelijke verschillen in data zou verklaren). Het punt is echter dat ik hierover nergens wat heb kunnen vinden. :'(

Daarom doe ik een beroep op mijn fellow Tweakers: wie heeft er nog meer ervaring met het ophalen van dynamisch (bijvoorbeeld door PHP) gegenereerde data (specifiek PNG-images) door een midp-client? En kunnen diegenen me wellicht vertellen wat ik fout doe of vergeten heb?

Ik heb nog een aantal alternatieve benaderingen die ik kan proberen, bijvoorbeeld het switchen van de server naar HTTP 1.0 modus (die data niet opdeelt in chunks, maar gewoon blijft sturen en vervolgens de connection afsluit) of anders het van te voren statisch opslaan van de dynamisch gegenereerde PNG, alvorens die (inclusief een Content-Length header) statisch te serveren. Beide methodes lijken mij echter lelijke workarounds. Het moet toch ook gewoon met HTTP 1.1 in chunked encoding modus kunnen werken? Wat doe ik toch fout? :?

Alvast hartelijk bedankt voor elke hulp die jullie me met dit probleem kunnen bieden! :)

Verwijderd

Topicstarter
Tijd voor een schopje. 8)

Verwijderd

Je kunt niet kwakkeloos de data concateneren als het gechunked was. Ik had een tijd geleden het zelfde probleem met een server die in http 1.1 modus de data chucked verstuurde en in http 1.0 modus, de data gewoon verstuurde.

Je moet denk ik eventjes in de specs duiken die bij http 1.1 horen. Daar staat in hoe je moet omgaan met het ontvangen en versturen van chunked http data.

zie paragraaf 3.6 in de volgende link:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html

Verwijderd

Topicstarter
Kijk, eindelijk eens wat informatie waar ik wat aan heb.! :D

Mag ik je hartelijk bedanken, MRwimlex? Afbeeldingslocatie: http://images.fok.nl/s/thumbsup.gif

Overigens wel erg misleidend dat de emulators het reassembleren van de chunks voor je uit handen nemen, terwijl werkelijke phones dat niet doen. :( Het zal wel liggen aan het feit dat de emulators te makkenlijk teruggrijpen naar win32-libraries op de http-data te lezen.

Of het moet per J2ME-implementatie verschillen (beide phones waarop ik de midlet tot nu toe heb getest waren gebaseerd op Symbian 7 en gebruikten dus precies dezelfde J2ME-implementatie)...

Ik kan in die documentatie die je me aanwees overigens nog niet zo gauw vinden hoe de client de volgende chunk van de server opvraagt... :? Maar ik ga nog wel even doorsnuffelen. 8)

Verwijderd

Ik gok erop dat windows een hoop voor je doet. Vooral als chuncked enconding op een windows bak wel goed gaat. Chuncked encoding gaat per definitie fout als je alleen de ontvangen data aanelkaarplakt. Je moet als je chuncked data ontvangt, echt een veel grotere routine schrijven. Zodat losse chunks herkend kunnen worden en dat dan uit een chunk alleen de data kan worden gehaald.

In het zelfde document(van mijn vorige post) staat nog een verwijzing naar een voorbeeld. Misschien heb je daar meer aan:
19.4.6 Introduction of Transfer-Encoding

succes!