Android ImageView und OutOfMemoryError – die Lösung kann so einfach sein

Die Kernfunktion einer meiner Android 2.1 Anwendungen ist das Anzeigen und Sortieren von Grafiken auf dem mobilen Endgerät. Voraussetzung ist, dass die Anwendung alle gängigen Grafikformate lesen und die Bilder aus einem definierten Verzeichnis von der SD-Karte oder über das Netzwerk verarbeiten kann.

Zur Anzeige der Grafiken verwende ich die ImageView (android.widget.ImageView) welche Bestandteil der Android-Librarys ist. In der Theorie könnte alles so einfach sein – ImageView in die Oberfläche integrieren und mit setImageBitmap die gewünschte Grafik anzeigen – das müsste es doch gewesen sein … müsste. Die Realität sieht allerdings etwas anders aus: (weiterlesen …)


Mehrsprachige Webseite – Smarty macht es möglich

Das Smarty Templatesystem ist wohl jedem bekannt welcher hin und wieder eine Webseite auf Basis von PHP umsetzt. Einfach und relativ performant ist es dank Smarty möglich das Design von der grafischen Oberfläche zu trennen. Bei meinen Projekten kommt Smarty inzwischen seit einigen Jahren regelmäßig zum Einsatz.

Bisher kam ich um die Anforderung eine mehrsprachige Webseite umzusetzen herum – doch dies sollte sich am Wochenende schlagartig ändern. So musste recht kurzfristig die Webseite der Bildagentur SportingPicture.com auch noch ins englische Übersetzt werden. Leichter gesagt als getan – ein wenig herumgegoogelt und relativ schnell fand sich die geeignete PHP-Klasse smartyML.

smartyML erbt von der ursprünglichen Smarty-Klasse und stellt somit alle Features der ursprünglichen Klasse zur Verfügung. Lediglich eine zusätzliche Notation in den Templates führt dazu, dass im Filesystem abgelegte Sprachdateien eingelesen und herangezogen werden können.

In meinem Fall speichere ich die gewählte Sprache direkt am Userprofil so dass dieser bei jedem Besuch automatisch die richtige Sprache angezeigt bekommt. Da meine Smartyinstanziierung nur in einer einzelnen Klasse erfolgt war die Umstellung selbst recht schnell durchgeführt. Der grösse Aufwand lang darin die alten in den Templates direkt eingebauten Texte in die Sprachdatei auszulagern.

Wer also auf der Suche nach einer Lösung ist seine Webseite mehrsprachig anzubieten der sollte sich unbedingt einmal die smartyML Klasse ansehen:

http://smarty.incutio.com/?page=SmartyMultilanguageSupport


Tip: App nicht im Market zu finden android:minSdkVersion -> android:targetSdkVersion

Laut der Android-Dokumentation sind alle Anwendungen, welche für ein älteres SDK Entwickelt wurden auch auf Geräten mit neueren SDKs verfügbar. Im Prinzip ist das ganze so auch richtig, dennoch gibt es hier eine kleine Besonderheit wenn man eine Anwendung für das SDK 1.5 (android:minSdkVersion=”3″) entwickelt. Folgendes Szenario:

Ich habe meine ToDo-Liste in erster Linie für meinen HTC Hero, welcher in der aktuellen Version auf dem Google Android Betriebssystem in der Version 1.5 aufsetzt, entwickelt. Meine AndroidManifest.xml-Datei enthält folgende SDK-Definition:
<uses-sdk android:minSdkVersion=”3″ />

Die Anwendung läuft auf dem HTC Hero und anderen Geräten mit 1.5 ohne Probleme und ist im Android Market für diese Geräte ersichtlich. Ein Bekannter von mir nutzt nun keinen HTC Hero sondern ein Acer Liquid mit dem SDK 1.6. Nach der Theorie sollte nun die Anwendung auch auf diesem Gerät lauffähig und verfügbar sein. Dem war aber nicht so, die Anwendung konnte weder über die Suche noch über den direkten Link im Google Market gefunden werden – Skepsis macht sich breit …

Also habe ich mir noch einmal die Manifest-Datei angesehen – eigentlich müsste die Stimmen. Ich setze das die SDK-Version 3 ein und möchte das die Anwendung ab hier funktionsfähig ist. In der Dokumentation (Quelle hier) ist folgendes zu finden:

android:minSdkVersion
An integer designating the minimum API Level required for the application to run. The Android system will prevent the user from installing the application if the system’s API Level is lower than the value specified in this attribute. You should always declare this attribute.

Sprich der Paramenter android:minSdkVersion gibt an, ab welcher SDK Version die Anwendung funktionsfähig ist und im Market zu finden sein soll. Ist hier die Version 3 angegeben sollte die Anwendung für alle Android Geräte ab Version 1.5 verfügbar sein – ist sie aber nicht … Also weiter suchen. Im Folgenden stosse ich auf einen von mir bisher nicht beachteten Parameter:

android:targetSdkVersion
An integer designating the API Level that the application is targetting.
With this attribute set, the application says that it is able to run on older versions (down to minSdkVersion), but was explicitly tested to work with the version specified here. Specifying this target version allows the platform to disable compatibility settings that are not required for the target version (which may otherwise be turned on in order to maintain forward-compatibility) or enable newer features that are not available to older applications. This does not mean that you can program different features for different versions of the platform—it simply informs the platform that you have tested against the target version and the platform should not perform any extra work to maintain forward-compatibility with the target version.
Introduced in: API Level 4

Dieser Parameter wurde mit dem SDK 1.6 (also Level 4) neu eingeführt und beschreibt für welche SDK-Version die Anwendung entwickelt wurde. So ganz verstehe ich zwar nicht warum es diesen Parameter gibt da sich die Funktion ausm einer Sicht mit dem android:minSdkVersion überschneidet – aber nun gut. Nach etwas herumspielen kam ich auf folgende Lösung:

  • Umstellung der API in Eclipse auf Version 4 (also 1.6)
  • android:minSdkVersion=”3″
  • android:targetSdkVersion=”4″
  • neu Exportieren (hierbei erfolgt das Compiling gegen 1.6 und nicht gegen 1.5)

Die AndroidManifest.xml beinhaltet nun also die folgende Zeile zur Definition der SDK-Version:
<uses-sdk android:minSdkVersion=”3″ android:targetSdkVersion=”4″ />

Die folgenden Tests zeigen, dass die Anwendung nun auf dem Android 1.6 funktionsfähig sind und im Market zu finden sind. Gleichzeitig ist die Anwendung allerdings auch noch im Android 1.5 lauffähig und wird im Market gefunden. Die Erklärung ist hier wohl dass das SDK 1.5 den Parameter android:targetSdkVersion noch nicht kennt und einfach ignoriert und sich nur an dem Parameter android:minSdkVersion orientiert. Alle Geräte ab 1.6 benötigen zusätzlich das android:targetSdkVersion um die Anwendung installieren zu können.

Die Verwendung beider Parameter muss also sein – der wirkliche Beweggrund warum diese Parameter, welche wie gesagt aus meinen Augen im Grunde das gleiche Beschreiben erstellt wurden, ist mir nicht bekannt und geht mir nicht in den Kopf.


SFTP-Client mit Java implementieren

Wer innerhalb eines Projektes vor die Aufgabe gestellt wird, eine FTP-Verbindung über den SSH-Port (SFTP) aufzubauen steht schnell vor dem Problem, dass Java von Haus aus hierfür keine geeignete Library zur Verfügung stellt. Da ich selbst beim Suchen nach der geeigneten Lösung einen gewissen Moment in Google, auf diversen Seiten und Foren und im Quellcode von diversen Libs verbrachte, möchte ich hier die von mir präferierte Lösung vorstellen.

Eine sehr gute und für frei zum Download verfügbare Library ist die ‘JSch – Java Secure Channel’-Library von JCraft‘. Neben einer einfachen Verbindung auf einen SSH-Server (weiterlesen …)


Vererbung mit Hibernate – Persistieren von Klassenhierarchien

Wer zur Persistierung der Daten auf Hibernate setzt, kommt unweigerlich zu der Frage, wie soll mit Objektgraphen über mehrere Ebenen hinweg umgegangen werden.

Selbst verständlich stellt Hibernate hier Wege bereit, auch Objekte über mehrere Vererbungshierarchien hinweg zu persistieren. Hierzu stehen 3 unterschiedliche Wege zur Verfügung: (weiterlesen …)


Grafik mit Java manipulieren (Grösse verändern, Copyright einfügen)

Innerhalb meines CRM-Systems ist es notwendig, diverse Grafiken per Upload auf den Server zu übertragen. Hier bietet es sich an, diese direkt nach dem Upload zu verkleinern und mit einem Copyright zu versehen. Damit beim Verkleinern keine Verzerrung entsteht, habe ich mich dazu entschieden die kompletten Proportionen neu zu berechnen.

Bei der Suche nach helfenden Code-Schnipsel im Internet war ich nicht wirklich erfolgreich, so dass ich mich entschieden habe, meinen Code zur Verkleinerung der JPEG-Grafiken mittels Java hier zu veröffentlichen:

public static void scaleImage(InputStream in, OutputStream out, int maxWidth, int maxHeight, String copyright)
  throws IOException {
  // read image from stream
  ImageIcon icon = new ImageIcon(ImageIO.read(in));weiter...
 (weiterlesen …)