Android und toDataURL – Bilder herunterladen und speichern (oder doch nicht?)

Das Entwickeln mit PhoneGap und Sencha Touch macht mir wirklich Spaß. Sofern die Anwendung nicht zu komplex wird, erzielt man mit dieser Kombination wirklich schnell ordentliche Ergebnisse. Allerdings gibt es auch hier wie so oft zwei Seiten der Medaille. PhoneGap schließt zwar eine Lücke, man findet bei der Entwicklung einer App aber auch hin wieder eine im Funktionsumfang (sei es, weil die Funktion nicht implementiert ist oder es nicht machbar ist).

So ist es einfach nicht möglich über PhoneGap/JavaScript Binär-Files zu schreiben. Einmal den großen Google befragt, findet man sehr schnell heraus, dass man dafür ein Plugin schreiben muss. Das ist jedoch ärgerlich, weil man dann ja doch wieder für jede Plattform Code anpassen muss. Ok, für das Herunterladen von Daten mag das vielleicht noch gehen, weil schon einige Plugins im Netz kursieren. Aber das widerspricht doch der Plattform unabhängigen Entwicklung…
Zumindest für Bilddaten nutze ich deshalb einen kleinen Trick, um das Ganze zu umgehen.

Dabei mach ich mir zu Nutze, dass es seit HTML5 das Canvas Objekt gibt, auf das man Zeichnen kann. Den Inhalt eines solchen Canvas kann man über die Funktion toDataURL als Base64 codierten String auslesen und abspeichern. Und das tue ich im folgenden Codeschnipsel auch: Bild laden, auf Canvas zeichnen, Daten auslesen.

  1. var canvas = document.createElement('canvas');
  2. var ctx = canvas.getContext('2d');
  3.  
  4. var img = new Image();
  5.  
  6. // After image loaded, get Base64 data
  7. img.onload = function(){
  8.   canvas.width = img.width;
  9.   canvas.height = img.height;
  10.   console.log(
  11.     "Image (" + img.width + "x" + img.height + ")"
  12.   );
  13.   ctx.drawImage(img, 0, 0, img.width, img.height);
  14.   var data = ctx.canvas.toDataURL();
  15.   console.log("Data loaded: " + data);
  16.  
  17.   // Just return the image data
  18.   return data.replace(/data.*base64,/g, "");
  19. }
  20.  
  21. img.onerror = function(error) {
  22.   console.log(error);
  23. }
  24.  
  25. // start loading
  26. img.src = uri;

Mit diesem Trick spart man sich das Herunterladen von Bilddaten per Ajax und kommt ganz bequem an die Base64 codierten Daten eines Bildes heran, die man nun per FileWriter.write() mit PhoneGap auf das Gerät speichern kann. Man muss jedoch beachten, dass die Bild-Daten durch den Overhead um ca. 33% aufgebläht werden (siehe hier).

Das klingt doch ganz Nett oder? Ja, aber es gibt hier ein großes ABER.
Denn womit ich nicht gerechnet habe: Google hat die toDataURL bis Android 2.2 noch gar nicht implementiert! So funktioniert der Trick zwar auf meinem Tablet mit Android 3.0 aber nicht auf meinem HTC mit Android 2.2!
Eine Suche bei Google förderte folgenden Einblick in den Android-Code zu Tage:

  1. String ImageBuffer::toDataURL(const String&) const
  2. {
  3.    // leaving this unimplemented, until I understand what
  4.    // its for (and what it really is).
  5.   return "data:,";
  6.   // I think this means we couldn't make the data url
  7. }

Den Kommentaren kann man deutlich entnehmen, dass hier ein Entwickler am Werk war, der sich mit der Materie nicht wirklich auskannte…

Bleibt abzuwarten, ob die Funktion auch noch ihren Weg in Android 2.x finden wird!

2 Gedanken zu „Android und toDataURL – Bilder herunterladen und speichern (oder doch nicht?)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.