Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Über mich
  • Deutsch
  • English
Menu

Android, Diagramme mit AFreeChart erstellen

Posted on 13. November 20152. Mai 2023 by Stefan Draeger

Wer sich mit Java schon etwas beschäftigt hat, sollte das Framework JFreeChart kennen. Für Android wurde dieses durchaus sehr gute Framework portiert und kann aus dem Repository von Google „https://code.google.com/p/afreechart/“ heruntergeladen werden.

Für mein Projekt habe ich die Version 0.0.4 gewählte welche unter der Adresse AFreeChart Downloads bezogen werden kann (dort befindet sich unter anderem die JavaDoc und eine *.apk Datei als lauffähige Android App).

  • Einbinden der Sourcen
  • Erstellen einer Activity mit einem Liniendiagramm
    • Diagramm einer View hinzufügen
  • Das Diagramm auf einer Activity darstellen
    • Das Layout zur Activity
    • Einbetten des Diagramms in den Container
  • Speichern des Diagramms als Bitmap
    • Teilen des Diagramms
  • Das fertige Diagramm

Einbinden der Sourcen

Zuerst muss die Datei afreechart-0.0.4.jar in das Projekt eingebunden werden. Dieses ist in jeder IDE unterschiedlich. Da ich InteliJ von JetBrains verwende und mein Projekt mit Gradle erstellen muss ich einen Ordner „libs“ neben dem „src“ Ordner erstellen.

"libs" Ordner für externe Bibliotheken
„libs“ Ordner für externe Bibliotheken

Nun noch die Datei in diesem Ordner ablegen und im Android Projekt bekannt machen.

Als Nächstes muss dieser Ordner in der Konfigurationsdatei „build.gradle(Module: app)“  eingetragen werden.

Konfigurationsdatei für die Abhängigkeiten im Android Projekt.
Konfigurationsdatei für die Abhängigkeiten im Android Projekt.

Es wird lediglich folgender Eintrag hinzugefügt bzw ergänzt.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Erstellen einer Activity mit einem Liniendiagramm

Um eine Activity mit zbsp. einem Liniendiagramm zu erstellen muss man ähnlich wie bei JFreeChart das Diagramm Objekt  „AFreeChart“ erstellen.

AFreeChart chart = ChartFactory.createTimeSeriesChart(
   "Titel",//Der Titel des Diagramms
   "Datum", //Die Achsenbeschriftung in X Richtung
   "Werte", //Die Achsenbeschriftung in Y Richtung
   dataset, //Das DataSet Objekt mit den Werten
   true, //Legende Anzeigen
   false, //Tooltips Anzeigen
   false //URL's Anzeigen
);

Diagramm einer View hinzufügen

Dieses Diagramm kann nun zu einer View hinzugefügt werden. Ich wende aus dem Beispiel die DemoView und leite davon meine neue View ab, somit muss ich mich nicht mit dem Überschreiben von Methoden kümmern.

public class EvaluationChartView extends DemoView {}

Als Erstes müssen wir unseren Konstruktor erstellen welcher als Parameter den Context und eine java.util.List (oder eine andere Collection) mit den Werten enthält. In meinem Fall sind dies Messergebnisse.

public EvaluationChartView(Context context, List<Measurement> measurements) {
        super(context);
}

Diese Messergebnisse müssen nun einem Dataset zugeordnet werden.

String text = ctx.getResources().getString(R.string.seriesTxt);
TimeSeries myTimeSerie = new TimeSeries(text);
for (Measurement measurement : measurements) {
  Minute minute = formatTimestamp(measurement.getTimestamp());
  myTimeSerie.add(minute, measurement.getValue());
}
TimeSeriesCollection dataset = new TimeSeriesCollection();
dataset.addSeries(myTimeSerie);

In diesem Beispiel habe ich die Zeitachse in Minuten Abstände eingestellt. Andere Werte können zbsp. sein:

RegularTimePeriod
RegularTimePeriod

Der Konstruktor der Klasse „Minute“ erwartet ein java.util.Date Objekt daher muss ich erst mein Timestamp (long) in ein Date Objekt umwandeln. Am einfachsten geht dieses mit der Klasse java.util.Calendar.

private Minute formatTimestamp(long timestamp) {
   Calendar cal = Calendar.getInstance();
   cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
   cal.setTimeInMillis(timestamp);
   return new Minute(cal.getTime());
}

Als Zeitzone setzte ich hier die deutsche Zeitzone, eleganter ist es jedoch die Zeitzone vom Gerät zu verwenden.
Wenn Sie die Zeitzone vom Gerät verwenden möchten, kann die Zeile

cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));

entfallen, da die Klasse java.util.Calendar schon die Zeitzone vom Gerät hat.

Das Diagramm auf einer Activity darstellen

Nachdem wir das Diagramm erstellt und mit Daten befüllt haben, werden wir nun dieses auf einer Activity darstellen.

Das Layout zur Activity

Das Layout für diese Activity wird einfach ausfallen, da wir unser View Objekt selbst erstellen benötigen wir zuerst nur einen Container für dieses.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/evaluationCreateLayout"></LinearLayout>
</RelativeLayout>

Das „LinearLayout“ wird unser Container.

Einbetten des Diagramms in den Container

Zuerst erstellen wir unser DiagrammView Objekt und holen eine Referenz zum Linearlayout (unser Container). In dieses Layout wird nun unser DiagrammView Objekt mit der Methode „addView(View view)“ hinzugefügt.

Context ctx = getApplicationContext();
EvaluationChartView chartView = new EvaluationChartView(ctx, measurements, evaluation.getEvaluationChartValues());
Point p = LayoutHelper.getScreenSize(ctx);
chartView.setMinimumWidth(p.x);
LinearLayout evaluationCreateLayout = (LinearLayout) findViewById(R.id.evaluationCreateLayout);
evaluationCreateLayout.addView(chartView);

Damit das Diagramm die volle Breite des Bildschirms einnimmt, nutze ich eine Hilfsklasse welche mir die Bildschirmgröße als android.graphics.Point liefert (ähnlich wie java.awt.Point).

public static Point getScreenSize(Context context) {
   WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
   Display display = wm.getDefaultDisplay();
   Point size = new Point();
   display.getSize(size);
   return size;
}

Speichern des Diagramms als Bitmap

Wer sich schonmal mit JFreeChart beschäftig hat, wird nun eine UtilKlasse vermissen

ChartUtilities.writeChartAsPNG(outputStream,getDataset(), width,height);

Hier kann mit einem einfachen Trick Abhilfe geschaffen werden. Es ist in Android möglich von jedem View Objekt einen „Screenshot“ zu erstellen und somit erstellen wir von unserem Container welches unser Diagramm enthält, einen Screenshot und speichern dieses als Bitmap auf dem Gerät.

private File storeChart(){
   File file = new File(CardioLoggerStatics.getExternalDirectory(getApplicationContext())+"/chart.png");
   FileOutputStream out = null;
   try {
       out = new FileOutputStream(file);
       LinearLayout view = (LinearLayout) findViewById(R.id.evaluationCreateLayout);
       view.setDrawingCacheEnabled(true);
       view.buildDrawingCache();
       Bitmap bmp = view.getDrawingCache();
       bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
   } catch (Exception e) {
       e.printStackTrace();
   } finally {
      try {
           if (out != null) {
              out.close();
           }
      } catch (IOException e) {
        e.printStackTrace();
    }
  }
 return file;
}

Da wir das Bitmap auf dem Gerät ablegen wollen benötigen wir zusätzliche Rechte (Permissions) welche in der Android.Manifest.xml festgehalten werden.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Teilen des Diagramms

Dieses erstellte Bild kann nun mit anderen Geräte oder Systemen geteilt / verschickt werden. Das Objekt „chartFile“ ist vom Typ java.io.File und enthält unseren Screenshot vom Container.

private void shareEvaluation() {
   Intent intent = new Intent();
   intent.setAction(Intent.ACTION_SEND);
   intent.setType("text/plain");
   intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   File chartFile = storeChart();
   intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(chartFile));
   getApplicationContext().startActivity(intent);
}

Das fertige Diagramm

Folgendes Diagramm habe ich mit dem oben dargestellten Code generiert.
Die Werte sind nur Beispielhaft.

Schreibe einen Kommentar Antworten abbrechen

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

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen

Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}