Java Archives - Technik - Blogbasis.net https://technik.blogbasis.net/tag/java Die Basis des freien Wissens – Technik Sat, 06 Sep 2014 13:14:14 +0000 de hourly 1 https://wordpress.org/?v=6.8.1 Arch Java – Zu viele Ebenen aus symbolischen Links https://technik.blogbasis.net/arch-java-zu-viele-ebenen-aus-symbolischen-links-06-09-2014 https://technik.blogbasis.net/arch-java-zu-viele-ebenen-aus-symbolischen-links-06-09-2014#respond Sat, 06 Sep 2014 13:14:14 +0000 http://technik.blogbasis.net/?p=1173 Ich wollte nach einer Reihe Updates ein Java-Programm starten und wurde von folgender Fehlermeldung begrüßt:

> java 
/usr/bin/java: Zeile 2: /usr/lib/jvm/default/bin/java: Zu viele Ebenen aus symbolischen Links
/usr/bin/java: Zeile 2: exec: /usr/lib/jvm/default/bin/java: Kann nicht ausführen: Zu viele Ebenen aus symbolischen Links

Der Fix ist schnell angewandt.

/usr/bin/java ist zunächst nur ein Link:

> file /usr/bin/java
/usr/bin/java: symbolic link to `/usr/lib/java-common-wrapper'

Die verlinkte Datei ist ein Shell-Script:

> file /usr/lib/java-common-wrapper 
/usr/lib/java-common-wrapper: Bourne-Again shell script, ASCII text executable
> cat /usr/lib/java-common-wrapper 
#!/bin/bash
exec "${JAVA_HOME:-/usr/lib/jvm/default}/bin/${0##*/}" "$@"

Ein Blick auf  /usr/lib/jvm/default bringt die Erkenntnis, dass der symbolische Link kaputt ist:

> file /usr/lib/jvm/default 
/usr/lib/jvm/default: broken symbolic link to `default'

Diesen Link müssen wir reparieren und auf das „java-7-openjdk“-Verzeichnis zeigen lassen:

sudo mv default default.bak
sudo ln -s java-7-openjdk default

Jetzt passen die symbolischen Links wieder und man kann „java“ ausführen.

~ Sebastian

]]>
https://technik.blogbasis.net/arch-java-zu-viele-ebenen-aus-symbolischen-links-06-09-2014/feed 0
Arch/Awesome – Unausgefüllte Java Fenster fixen https://technik.blogbasis.net/archawesome-unausgefuellte-java-fenster-fixen-19-11-2013 https://technik.blogbasis.net/archawesome-unausgefuellte-java-fenster-fixen-19-11-2013#respond Tue, 19 Nov 2013 20:30:27 +0000 http://technik.blogbasis.net/?p=968 Da ich in letzter Zeit studiumsbedingt vermehrt mit Java Tools arbeite, störte mich der folgende Bug erheblich: Wenn man eine Java-GUI maximiert hat, so wurde nicht der Inhalt erweitert, sondern der zusätzliche Raum mit grauem Hintergrund aufgefüllt.

Das verfehlt natürlich zu 100% den Zweck des Maximierens. Das kann man sich ungefähr so vorstellen:

Java unvollständig maximiertes Fenster

Java unvollständig maximiertes Fenster

Die Lösung des Problems

Nach ein wenig Googlen stieß ich auf eine Lösungsbeschreibung im Arch-Wiki, die in etwa so lautete: Java kommt auf den Namen des Window-Managers (Awesome) nicht klar, sodass man Java mit einem kleinem Tool einen anderen Namen in die Umgebungsvariable legen muss.

Dazu muss man sich das Programm „wmname“ installieren:

sudo pacman -S wmname

Danach führt man wmname mit dem gewünschten Fake-Wert als Parameter aus. Bei mir hat der folgende Aufruf geholfen:

wmname LG3D

Führt man nun die Java-Applikation aus derselben Konsole aus, so funktioniert alles einwandfrei :)

Optimal maximiertes Java Fenster

Optimal maximiertes Java Fenster

Fazit

Wie immer gibt es für alles eine kleine oder manchmal auch eine größere Lösung :)

~Sebastian

]]>
https://technik.blogbasis.net/archawesome-unausgefuellte-java-fenster-fixen-19-11-2013/feed 0
Ein Fraktal Programmieren https://technik.blogbasis.net/ein-fraktal-programmieren-06-08-2013 https://technik.blogbasis.net/ein-fraktal-programmieren-06-08-2013#respond Tue, 06 Aug 2013 13:33:04 +0000 http://technik.blogbasis.net/?p=744 Heute schreibe ich mal ein bisschen was dazu, wie man ein Fraktal implementieren kann. Ich werde hierbei einfach eine Java-Klasse für ein Projekt schreiben, dass ich zusammen mit einem Freund gemacht habe. Die Erklärungen lassen sich aber auch auf andere Programmiersprachen anwenden. Ich werde hier einfach Schritt für Schritt beschreiben wie ich eine Version des Newton-Fraktals implementiere. Wenn man die Schritte selber nachmachen will kopiert man am besten einfach das Git-Repository und fügt es in ein Eclipse Java-Projekt ein.

Die Java Klasse erzeugen

Als erstes wird mit Eclipse die Klasse erstellt. Diese Klasse erbt von der Oberklasse Fraktalprogramm. Ein Fraktalprogramm hat eine Hauptmethode nähmlich calcPixel. calcPixel bekommt als eingabe vom Renderer den Punkt der berechnet werden soll. Dann berechnet calcPixel die Farbe die der Pixel bekommen soll und gibt sie zurück damit der Renderer den entschprechenden Pixel einfärben kann. Das kann man natürlich auch anders realiesieren, aber so bleibt der Code vielleicht noch am übersichtlichsten. So sieht in diesem Fall also meine Klasse aus:

package de.a.newton; //Das eigene Package
import java.awt.Color; // Benötigt um Farben auszugeben

import de.otori.engine.FraktalProgram; // die Eltern-Klasse
import de.otori.engine.Point2F; // Format der Koordinate die übergeben wird

public class Newton extends FraktalProgram{

public Newton() {
// TODO Auto-generated constructor stub
}

@Override
public Color calcPixel(Point2F coordinate) {
// TODO Auto-generated method stub
return null;
}

}

Damit man die Klasse dem Renderer als Objekt übergeben werden kann erstellen wir noch ein generisches Objekt der Klasse welches dann schon voreingestellt ist.

public static final Newton GenerischeEinstellungen = new Newton();

Dann erstellen wir den Konstruktor:

/**
* Konstruktor
*/
public Newton() {
zoom = 1.; //Das Zoomlevel und der Mittelpunkt gehören zur Oberklasse
center = new Point2F(0, 0);
}

Jetzt kann amn schnell testen ob bis hier schon alles klappt. Wir schreiben einfach eine kleine Testfunktion die einen Sinus malen soll.

@Override
public Color calcPixel(Point2F coordinate) {
double sin = Math.sin(coordinate.x); //den Sinus von x berechnen
if(coordinate.y < sin + 1 && coordinate.y>sin-1) //wenn der wert des Sinus 
{return Color.black;}// in etwa der y Koordinate gleicht wird der Punkt schwarz

return Color.white; // ansonsten bleibt er weiss
}

Jetzt muss noch in engine/Programm.java das entsprechende Programm aufgerufen werden

private FraktalProgram[] fraktals = {  Newton.GenerischeEinstellungen};

Wenn man jetzt das Gesamte Programm neu kompiliert und ausführt sollte man etwas wie das hier erreichen:

Sinustest

 

Wenn man doppel Rechtsklickt erkennt man schon die Sinuskurve

Sinus-Test2

Die Regeln für die Erzeugung programmieren

Die Berechnung eines Pixels soll solange andauern bis die Folge die das Fraktal beschreibt konvergiert (sich also irgendwann nicht mehr groß verändert sondern nur noch in einem bestimmten Bereich bleibt). Wenn sie aber einfach nicht konvergieren will müssen wir irgendwann einfach abbrechen. Dies machen wir nach einer willkürlich festgelegten Anzahl von Schritten (Iterationen). Die Anzahl der Iterationen sollte möglichst nah an Unendlich liegen. Also eine möglichst große Zahl sein. Dieses mal wählen wir 42.

/**
* The Maximum number of iterations determines the Quality of the computation:
* A high number results in longer computation time, a low in less quality
*/

private int MAX_ITER = 42;

Um dem Pixel später eine Farbe geben zu können lassen wir uns einfach ausgeben ab wann die Folge konvergiert dazu geben wir einfach den Itterationschritt mit.

Die Folge auf der das Newtonfraktal aufbaut ist laut Wikipedia  [latex]z_{n+1} := z_{n} – \dfrac{p(z_{n})}{p'(z_{n})}[/latex]. Wobei [latex]p[/latex] hier eine Funktion ist die auf [latex]z[/latex] angewendet wird. Man denkt vielleicht , das es einfacher ist die Formel einfach rekursiv zu implementieren. Das Lohnt sich aber aus Performance-Gründen nicht. Denn in einer imperativen Implementierung können wir immer so früh wie möglich abbrechen. Das wird hoffentlich klar sobald der Code geschrieben wird.

Unser ausgegebenes Bild wird die Komplexe Ebene darstellen weil unsere Folge auf Komplexen Zahlen definiert ist müssen wir auch mit Komplexen Zahlen rechnen die sind praktischer Weise schon einmal für die Mandelbrotmenge implementiert worden. Also werden wir sie hier einfach importieren. Die Funktion die wir als nächstes implementieren bekommt dannn als Eingabe eine Komplexe Zahl und wird uns eine Farbe zurückgeben. Hier bekommen wir erstmal eine Zahl zurück die wir dann später in eine Farbe umwandeln können. Die Komplexe Zahl erhalten wir einfach aus den Koordinaten underes Pixels. So kann zum Beispiel die X-Koordinate den Imaginäranteil und die Y-Koordinate den Realanteil darstelllen. Später werden wir die Funktion einfach mit einer aus den Pixeln erzeugten komplexen Zahl aufrufen. Die Zahl die wir dann bekommen wandeln wir dann in eine Farbe um.

Die Methode sieht also erstmal so aus:

public int calcConvergence(ComplexNumber startValue) {
return null;
}

Jetzt kann man sich etwas konkreter überlegen was berechnet werden soll. Auf dem Deutschen Wikipedia wird die Funktion [latex]p(z)=z^{3}-1[/latex] vorgeschlagen wenn man von dieser Funktion ausgeht und dies in die Ursprungsdefinition des Newtonfraktals([latex]z_{n+1} := z_{n} – \dfrac{p(z_{n})}{p'(z_{n})}[/latex]) einsetzt erhält man folgende Folge [latex]z_{n+1} := z_{n} – \dfrac{(z_{n})^{3}-1}{3*(z_{n})^{2}}[/latex].

Das kann man jetzt versuchen in Code umzusetzen.

public int calcConvergence(ComplexNumber startValue) {

int iteration = 1; // die Anzahl der Itterationen soll gezählt werden

ComplexNumber aktuellerWert = new ComplexNumber(startValue); //mit dem startValue fängt die Folge an

while(iteration < MAX_ITER)
{

//divident berechnen
ComplexNumber divident = new ComplexNumber(aktuellerWert); 
divident.pot(3); //z³
divident.sub(1);//-1

//divisor 
ComplexNumber divisor = new ComplexNumber(aktuellerWert); 
divisor.quad(); // z²
divisor.mul(3.);//*3

//Subtrahend
ComplexNumber subtrahend = new ComplexNumber(divident);
subtrahend.div(divisor); // quotient = dividend/ divisor

//Differenz Berechnen
aktuellerWert.sub(subtrahend);
iteration++;
if(aktuellerWert.absSqr() > 4.0){
//nach http://de.wikipedia.org/wiki/Julia-Menge#Graphische_Darstellung_der_Julia-Mengen
break;
}
}
return iteration;

}

Danach ruft man calcConvergence in  calcPixel auf. Dabei kann man sich eine fast belibige Farb-Funktion schreiben. Ich habe einfach große Teile von der Implementierung des Mandelbrot Fraktals übernommen.

public Color calcPixel(Point2F coordinate) {

int iter = calcConvergence( new ComplexNumber(coordinate.x,coordinate.y));//Die Nummer holen auf der die Farbe beruht 
if(iter == MAX_ITER)
{
return Color.black;
}
else
{ double near = Math.sqrt(iter) / Math.sqrt((double)MAX_ITER);
return ColorFun.farbVerlauf(Color.getHSBColor((float) (((coordinate.x / 3) + 0.5f) % 1.f), 1.f, 1.f), Color.getHSBColor((float) (coordinate.x / 3), 1.f, 1.f), near);}
}

}

Wenn man das Programm jetzt wieder ausführt sollte man etwas wie das hier erhalten:

By Georg-Johann Lay (self-made, see Visualising Julia sets) [Public domain], via Wikimedia Commons

Ich bekomme leider nur das hier :

Fail

 

naja, vermutlich habe ich bei der implementierung von den komplexen Zahlen zu viel gefuscht aber was auch immer ich da jetzt erhalten habe. Es scheint immerhin ein Fraktal zu sein….

Quellcode

Wenn man sich den Code genauer ansehen will oder es einfach ausprobieren will kann man hier das Projekt anschauen. Vielleicht sagt mir ja jemand was noch nicht stimmt.

]]>
https://technik.blogbasis.net/ein-fraktal-programmieren-06-08-2013/feed 0
Java und C / C++ – Bibliotheken https://technik.blogbasis.net/java-und-c-c-bibliotheken-30-03-2013 https://technik.blogbasis.net/java-und-c-c-bibliotheken-30-03-2013#respond Sat, 30 Mar 2013 22:30:59 +0000 http://technik.blogbasis.net/?p=300 Eigentlich hatte ich vor dieses Tutorial als eigenständigen Blog-Artikel zu schreiben, habe mich jedoch aus diversen Gründen dagegen entschieden.
Dieses Tutorial wurde schon auf diversen Foren veröffentlicht und ist fast einen Monat alt. Ich hoffe dennoch, dass ihr euren Spaß damit haben werdet. Falls noch weitere Fragen bestehen könnt ihr diese als Kommentar posten.
Es geht darum, wie ihr in Java Bibliotheken (Dynamic Link Library) in eine Java-Anwendung einbinden könnt.

Das Tutorial gibt es als PDF Datei zum Download:

C++ Libs in Java

mfg
euer TgZero

]]>
https://technik.blogbasis.net/java-und-c-c-bibliotheken-30-03-2013/feed 0
Java mit Jad decompilen https://technik.blogbasis.net/java-mit-jad-decompilen-23-03-2013 https://technik.blogbasis.net/java-mit-jad-decompilen-23-03-2013#respond Sat, 23 Mar 2013 22:55:53 +0000 http://technik.blogbasis.net/?p=275 In diesem Blogpost möchte ich das Tool „jad“ zum Decompilen von Java-Programmen vorstellen. Ich habe dazu ein kleines CrackMe geschrieben, welches wir „cracken“ werden.

Voraussetzungen

Bevor wir jedoch mit dem Cracking anfangen können, müsst Ihr einige Voraussetzungen erfüllen:

  • Java Runtime Environment (JRE) muss installiert sein (java)
  • Java Development Kit (JDK) muss installiert sein (javac)
  • Jad musst installiert sein (http://www.varaneckas.com/jad/ oder Paketquellen)

Nachdem diese Tools installiert sind, kann es mit dem Lesen weitergehen :)

Das CrackMe

Ich habe ein einfaches CrackMe geschrieben, welches von der Console ein Passwort entgegen nimmt, und überprüft, ob dieses mit einem hinterlegten übereinstimmt. Ist dies der Fall, so wird banal „right password“ ausgegeben.

Um dieses CrackMe umzusetzen, benötigen wir zwei Dateien:

  • main.java
  • cracks/CrackMe.java

main.java

Ich gehe davon aus, dass man sich für dieses Projekt ein eigenes Verzeichnis angelegt hat. Darin legen wir die main.java mit folgendem Inhalt an:

import cracks.CrackMe;

public class main {

    public static void main(String[] args) {

        CrackMe crackme = new CrackMe();

        crackme.crackMe();

    }

}

Die Main-Klasse macht nichts anderes, als das sie ein neues CrackMe-Objekt erzeugt und dessen Validierungsroutine aufruft.

CrackMe.java

Die interessantere Datei ist das CrackMe selbst. In unserem Projektverzeichnis legen wir einen Unterordner namens „cracks“ an. Darin speichern wir dann die CrackMe.java mit folgendem Inhalt:

package cracks;
import java.io.Console;

public class CrackMe {

    private String passwd = "1337Me";

    public void crackMe() {

        Console console = System.console();

        System.out.println("Enter password: ");

        String input = console.readLine();

        if(this.passwd.equals(input)) {
            System.out.println("Right password");
        } else {
            System.out.println("Wrong password");
        }
    }
}

Die „crackMe“-Funktion liest von der Konsole eine Zeile ein, und überprüft daraufhin, ob die Eingabe mit der privaten Variable „passwd“ übereinstimmt.

Kompilieren & Ausprobieren

Mit reinem Sourcecode können wir natürlich nicht viel anfangen. Deswegen bemühen wir zwei Aufrufe von javac um aus dem Quelltext die Class-Dateien zu erstellen:

javac main.java
javac cracks/CrackMe.java

Ein Aufruf von ls sollte uns dann die Existenz der Dateien bestätigen:

-> % ls *
-rw-r--r-- 1 gehaxelt users  311 23. Mär 22:28 main.class
-rw-r--r-- 1 gehaxelt users  172 23. Mär 22:28 main.java

cracks:
insgesamt 16K
drwxr-xr-x 2 gehaxelt users 4,0K 23. Mär 22:27 .
drwxr-xr-x 3 gehaxelt users 4,0K 23. Mär 22:28 ..
-rw-r--r-- 1 gehaxelt users  790 23. Mär 22:27 CrackMe.class
-rw-r--r-- 1 gehaxelt users  452 23. Mär 22:27 CrackMe.java

Wenn wir unser kleines Programm nun ausprobieren wollen müssen wir einfach die main aufrufen:

-> % java main
Enter password: 
TestPasswort
Wrong password

 CrackMe cracken

Wer sich den Quelltext angeschaut hat, der wird das Passwort bereits kennen. Da dies alles nur ein Beispiel sein soll, ist dieser Fakt mal zu vernachlässigen ;) Es gibt verschiedene Wege an das Passwort zu gelangen:

  • BruteForce
  • Strings
  • Jad

BruteForce

Man könnte bruteforce-artig das Programm aufrufen und verschiedene Eingaben ausprobieren, bis man entsprechend das richtige Passwort erraten hat. Dies ist aber kaum effizient, weswegen wir diesen Weg nicht weiter betrachten werden.

Strings

Ich hatte auf meinem alten Blog strings & Co bereits erläutert. Wenn man davon ausgeht, dass das zu überprüfende Passwort im Programm nicht weiter verschlüsselt ist, könnte dies ein erster Ansatz sein. Wir rufen einfach strings mit der CrackMe.class als Parameter auf:

-> % strings cracks/CrackMe.class
passwd
Ljava/lang/String;

Code
LineNumberTable
crackMe
StackMapTable
SourceFile
CrackMe.java
1337Me
Enter password: 
Right password
Wrong password
cracks/CrackMe
java/lang/Object
java/io/Console
java/lang/String
java/lang/System
console
()Ljava/io/Console;
Ljava/io/PrintStream;
java/io/PrintStream
println
(Ljava/lang/String;)V
readLine
()Ljava/lang/String;
equals
(Ljava/lang/Object;)Z

Wer genau hinschaut, findet das richtige Passwort in der Ausgabe. Falls man das Passwort nicht kennt, könnte man alle ausgegebenen Strings als Eingabe prüfen. Dies wäre aber keine gute Lösung, falls die Validierung von äußeren Faktoren abhängen würde (Serverabfragen, etc).

Jad

Der Blogpost soll eigentlich um das Tool „jad“ gehen. Mit diesem Tool kann man aus den .class-Dateien den Quelltext soweit wie möglich wieder herstellen.

Tipp: .jar-Dateien kann man einfach mit unzip entpacken, da sie auch nur Archive sind.

Für unseren CrackMe erstellen wir erstmal einen neuen Ordner „jad“ und kopieren die .class Dateien dorthin:

mkdir jad
mkdir jad/cracks
cp main.class jad/main.class
cp cracks/CrackMe.class jad/cracks/CrackMe.class
cd jad

Wir wechseln in das neu erstellte Verzeichnis, da wir darin operieren werden.

Das Decompilen

Wir müssen nun die zwei .class-Dateien dekompilieren. Wir brauchen dazu zwei Aufrufe von jad:

-> % jad -v -stat main.class
Parsing main.class...The class file version is 51.0 (only 45.3, 46.0 and 47.0 are supported)
 Generating main.jad
Method 
Method main
#classes: 1, #methods: 2, #fields: 0, elapsed time: 0.001s
-> % jad -v -stat -d cracks cracks/CrackMe.class
Parsing cracks/CrackMe.class...The class file version is 51.0 (only 45.3, 46.0 and 47.0 are supported)
 Generating CrackMe.jad
Method 
Method crackMe
#classes: 1, #methods: 2, #fields: 1, elapsed time: 0.002s

Der Parameter „-v“ lässt den Decompiler gesprächiger sein, und „-stat“ zeigt ein paar Statistiken an. Mit dem Parameter „-d“ setzen wir den Output-Ordner, welchen wir im zweiten Aufruf anpassen müssen.

Wir sollten erfolgreich die Dateien dekompiliert, und jad sollte diese als .jad Datei angelegt haben. Der Inhalt sollte so ähnlich aussehen:

main.jad

// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   main.java

import cracks.CrackMe;

public class main
{

    public main()
    {
    }

    public static void main(String args[])
    {
        CrackMe crackme = new CrackMe();
        crackme.crackMe();
    }
}

Diese Main-Datei interessiert uns nicht wirklich, da darin keine Validierung der Eingabe stattfindet.

 CrackMe.jad

Diese Datei ist viel interessanter, und deren Inhalt ist folgender:

// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   CrackMe.java

package cracks;

import java.io.Console;
import java.io.PrintStream;

public class CrackMe
{

    public CrackMe()
    {
        passwd = "1337Me";
    }

    public void crackMe()
    {
        Console console = System.console();
        System.out.println("Enter password: ");
        String s = console.readLine();
        if(passwd.equals(s))
            System.out.println("Right password");
        else
            System.out.println("Wrong password");
    }

    private String passwd;
}

Man erkennt eindeutig, dass der Decompiler ein etwas anderen Source erzeugt, als wir ihm geschrieben haben. Das wichtigste ist jedoch, dass wir nun Einsicht in den Quelltext haben.

Wenn wir nun das Programm „cracken“ wollen, können wir den einfachen Weg nehmen und die If-Abfrage abändern. Aus

if(passwd.equals(s))

wird

if(true)

Damit ist die Bedingung immer wahr, und man wird immer durchgelassen. Ziel soweit erfolgreich.

Als letztes müssen wir die Dateien nur noch neu kompilieren. Dazu benennen wir diese zunächst von .jad nach .java um:

cp main.jad main.java
cp cracks/CrackMe.jad cracks/CrackMe.java

Ich habe hier bewusst auf „cp“ gesetzt, damit wir ein Backup vom Decompiler-Output haben. Unsere umbenannten Dateien müssen wir nur noch mit dem javac bearbeiten.

javac main.java
javac cracks/CrackMe.java

Das CrackMe sollte nun gecracked sein, und jede beliebige Eingabe als korrekt durchlassen. Wer dies ausprobieren möchte, muss einfach wieder die main ausführen:

-> % java main
Enter password: 
bestimmt nicht das richtige Passwort :(
Right password

Fazit

Falls Ihr Projekte in Java schreibt, dann solltet ihr wissen, dass man sehr leicht an den Quelltext gelangen kann. Falls man darin wichtige Informationen verstecken möchte, dann hilft ggf. ein Obfuscator oder die Verschlüsselung der Informationen. Alles in allem wird es aber einen Weg geben, an diese Informationen zu gelangen.

Dieser Blogpost soll nur für Lernzwecke dienen und keinesfalls zu illegalen Aktivitäten anstiften.

~ Sebastian

]]>
https://technik.blogbasis.net/java-mit-jad-decompilen-23-03-2013/feed 0
Eigene EventListener in Android entwickeln https://technik.blogbasis.net/eigene-eventlistener-in-android-entwickeln-18-03-2013 https://technik.blogbasis.net/eigene-eventlistener-in-android-entwickeln-18-03-2013#respond Mon, 18 Mar 2013 17:20:44 +0000 http://technik.blogbasis.net/?p=242 Ich schreibe mit einem Kumpel an einer kleinen App. Für ein bestimmtes Feature benötigten wir einen eigenen EventListener. Die Implementierung dessen möchte ich folgend beschreiben.

Um das System dahinter zu verdeutlichen, müssen wir uns dazu keine extra App vorstellen, denn die App-Entwicklung für Android basiert auf Java. In dem folgenden Beispiel nutzen wir eine Calculator-Klasse, welche ein paar einfache Rechenoperationen durchführen soll. Das Ergebnis wollen wir dann per onFinished-Event ausgeben lassen.

Die main-Klasse

Die von mir genutzte Main-Klasse würde in einer Android-App die entsprechende Activity darstellen, welche von dem onFinished-Event Gebrauch machen möchte.

import tools.Calculator;
import tools.EventListener;

public class main {

    public static void main(String[] args) {

        Calculator calc = new Calculator();

        calc.setOnFinishedEventListener(new EventListener() {

            @Override
            public void onFinished(Object result) {

                System.out.println("Result: "+String.valueOf((int)result));

            }

        });

        calc.calculate(5,5,Calculator.PLUS);

    }

}

In dieser Activity bzw. Klasse erzeugen wir ein Objekt der Calculator Klasse. Diesem Objekt weisen wir über calc.setOnFinishedEventListener(…) unser EventListener-Objekt, in welchem wir die onFinished Methode überschreiben. In dieser Methode geben wir das Ergebnis einfach als String aus.

Wichtig ist, dass wir den EventListener vor der Berechnung selbst setzen. Andernfalls würde es zu keinem Event kommen, da wir in der Calculator-Klasse dieses nach der Berechnung abfeuern.

EventListener.java

Um einen EventListener umzusetzen, müssen wir ein entsprechendes Interface erstellen. Dieses Inferface enthält die Methode onFinished, welche wir weiter oben überschrieben haben.

package tools;

public interface EventListener {

    void onFinished(Object result);

}

 

Calculator.java

In der Calculator.java, in welcher später das Event abgefeuert werden soll, muss eine Funktion implementiert werden, welche den EventListener setzt. Zunächst weist man der Klasse eine neue private Variable, welche den EventListener enhält, zu. Wir brauchen nun nur noch eine Setter-Methode, um den EventListener zu setzen:

package tools;

public class Calculator {

    public static final int PLUS = 0;
    public static final int MINUS = 1;
    public static final int DIV = 2;
    public static final int MULT = 3;

    private int _result;
    private EventListener _eListener = null;

    public void calculate(int x, int y, int op) {

        switch(op) {
            case PLUS: {
                _result = x + y;               
            }
            case MINUS: {
                _result = x - y;
            }
            case DIV: {
                _result = x / y;
            }
            case MULT: {
                _result = x * y;
            }
            default: {
                _result =  x + y;
            }

        }

        if(_eListener != null)
            _eListener.onFinished(_result);

    }

    public void setOnFinishedEventListener(EventListener listener) {
        _eListener = listener;
    }

}

Wie man erkennen kann, ruft man zum abfeuern des Events einfach an der gewünschten Stelle die onFinished-Funktion auf. Dies macht allerdings nur Sinn, falls diese nicht null ist.

Fazit

Man kann sehr einfach eigene EventListener umsetzen, um bestimmte Funktionalitäten – meistens in parallelem bzw. asynchronen Code – zu programmieren.

~ Sebastian

]]>
https://technik.blogbasis.net/eigene-eventlistener-in-android-entwickeln-18-03-2013/feed 0
Java – verschiedene Rückgabetypen https://technik.blogbasis.net/java-verschiedene-rueckgabetypen-10-03-2013 https://technik.blogbasis.net/java-verschiedene-rueckgabetypen-10-03-2013#respond Sun, 10 Mar 2013 16:53:16 +0000 http://technik.blogbasis.net/?p=90 In verschiedenen typenlosen Programmiersprachen kann man in ein Array verschiedene Datentypen platzieren. In der typenbehafteten Sprache Java ist das etwas umständlicher. Mit einem kleinen Trick kann eine Funktion trotzdem verschiedene Datentypen zurückgeben.

Das Problem

Ich konstruiere hier ein kleines Problem. Nehmen wir mal an, wir möchten eine Funktion schreiben, welche uns den Flächeninhalt, sowie das Volumen eines Quadrats bzw. Würfels ausgibt. Als Eingabe erhält diese Funktion nur Seitenlänge als Integer.

public int[] SurfaceVolume(int x) {
    int[] retarr = new int[2];
    int[0] = x*x; //surface
    int[1] = x*x*x; //volume
}

Das würde nun ohne Weiteres funktionieren. Gehen wir aber mal davon aus, dass wir den Volumen-Anteil als Double zurückgeben möchten. Dann stehen wir von dem Problem, dass wir nicht ein Array aus zwei verschiedenen Datentypen erstellen können.

Hilfsklasse SurfaceVolumeRet

Wir können uns aber eine kleine Klasse schreiben, welche unser Array „ersetzt“, in dem diese die zwei verschiedene Datentypen speichert. Die Klasse könnte so aussehen:

public class SurfaceVolumeRet {
    private int __surface;
    private double __volume;

    public SurfaceVolumeRet(int surface, double volume) {
        this.__surface = surface;
        this.__volume = volume;
    }

    public int getSurface() {
        return this.__surface;
    }

    public int getVolume() {
        return this.__volume;
    }
}

Nun haben wir uns einfach einen neuen Datentyp erstellt, welcher die zwei verschiedenen Datentypen in sich trägt. Ich habe hier nur Getter-Methoden implementiert, da ich nur lesend auf die Werte zugreifen möchte. Ggf. sollten hier noch die Setter-Methoden implementiert werden. Wir müssen die Funktion nur noch ein wenig anpassen:

public SurfaceVolumeRet SurfaceVolume(int x) {
    return new SurfaceVolumeRet(x*x,Double.parseDouble(x*x*x));
}

Wir können dann in der aufrufenden Funktion mit unserem SurfaceVolumeRet-Objekt arbeiten und die entsprechenden Getter-Methoden nutzen, um an die Ergebnisse zu gelangen.

public void aufruf() {
    SurfaceVolumeRet ret = SurfaceVolume(x);
    System.out.println("Surface: " + String.valueOf(ret.getSurface()));
    System.out.println("Volume: " + String.valueOf(ret.getVolume()));
}

~Sebastian

]]>
https://technik.blogbasis.net/java-verschiedene-rueckgabetypen-10-03-2013/feed 0