JFreeChart "real-time" line graph with two lines - jfreechart

I am using JFreeChart to display data gathered from two sensors on an arduino using RXTX in "real-time". There is two values separated by a comma being sent from the arduino. I can successfully plot the data from one sensor on the graph but I am unable to add a second line for the data from the second sensor. Do anyone know how I can add the second line to the graph ?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import javax.swing.JOptionPane;
public class respiratorytest2 extends javax.swing.JFrame implements SerialPortEventListener {
public static float[][] C_A_Data = new float[120][2];
public static int count = 0;
public static respiratorytest2 demo;
public static float[ ]dataArray = new float[600];
public float data1;
public float data2;
public static Connection conn;
public static PreparedStatement stmt = null;
public static String sql;
public static int result=0;
public static int result2;
public static String gusername;
/**
* The number of subplots.
*/
public static final int SUBPLOT_COUNT = 3;
/**
* The datasets.
*/
private TimeSeriesCollection[] datasets;
/**
* The most recent value added to series 1.
*/
private double[] lastValue = new double[SUBPLOT_COUNT];
private double[] lastValue2 = new double[SUBPLOT_COUNT];
SerialPort serialPort;
/**
* The port we're normally going to use.
*/
private static final String PORT_NAMES[] = {
"/dev/tty.usbserial-A9007UX1", // Mac OS X
"/dev/ttyUSB0", // Linux
"COM3", // Windows
};
/**
* A BufferedReader which will be fed by a InputStreamReader converting the
* bytes into characters making the displayed results codepage independent
*/
private BufferedReader input;
/**
* The output stream to the port
*/
private OutputStream output;
/**
* Milliseconds to block while waiting for port open
*/
private static final int TIME_OUT = 2000;
/**
* Default bits per second for COM port.
*/
private static final int DATA_RATE = 9600;
public static void visibility(){
demo.setVisible(true);
}
public respiratorytest2(String title) {
super(title);
initialize();
final CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new DateAxis("Time (sec)"));
this.datasets = new TimeSeriesCollection[SUBPLOT_COUNT];
this.lastValue[0] = 100.0;
this.lastValue2[0] = 100.0;
final TimeSeries series = new TimeSeries("Volume ", Millisecond.class);
final TimeSeries series2 = new TimeSeries("Volume ", Millisecond.class);
this.datasets[0] = new TimeSeriesCollection(series);
this.datasets[1] = new TimeSeriesCollection(series2);
final NumberAxis rangeAxis = new NumberAxis("Volume");
rangeAxis.setAutoRangeIncludesZero(false);
final XYPlot subplot = new XYPlot(
this.datasets[0], null, rangeAxis, new StandardXYItemRenderer()
);
subplot.setBackgroundPaint(Color.lightGray);
subplot.setDomainGridlinePaint(Color.white);
subplot.setRangeGridlinePaint(Color.white);
plot.add(subplot);
final JFreeChart chart = new JFreeChart("Respiratory Test", plot);
chart.setBorderPaint(Color.black);
chart.setBorderVisible(true);
chart.setBackgroundPaint(Color.white);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final ValueAxis axis = plot.getDomainAxis();
axis.setAutoRange(true);
axis.setFixedAutoRange(60000.0); // 60 seconds
final JPanel content = new JPanel(new BorderLayout());
final ChartPanel chartPanel = new ChartPanel(chart);
content.add(chartPanel);
final JPanel buttonPanel = new JPanel(new FlowLayout());
content.add(buttonPanel, BorderLayout.SOUTH);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 470));
chartPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setContentPane(content);
}
public void initialize() {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
output = serialPort.getOutputStream();
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println("Exception=" + e.toString());
}
}
/**
* This should be called when you stop using the port. This will prevent
* port locking on platforms like Linux.
*/
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
/**
* Handle an event on the serial port. Read the data and print it.
*/
#Override
public synchronized void serialEvent(SerialPortEvent oEvent) {
int i=0,j=0,a,b;
StringBuffer sq = new StringBuffer();
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String inputLine = input.readLine();
System.out.println(inputLine);
String[] dArray = inputLine.split(",");
data1 = Float.valueOf(dArray[0]);
data2 = Float.valueOf(dArray[1]);
this.lastValue[0] = new Integer(dArray[0]).intValue();
this.lastValue2[0] = new Integer(dArray[1]).intValue();
//this.datasets[0].getSeries(0).add(new Millisecond(), this.lastValue[0]);
//this.datasets[1].getSeries(0).addOrUpdate(new Millisecond(),this.lastValue2[0]);
sq.append ("INSERT INTO U_DATA");
sq.append("(USERNAME, SESSION_NUM, SESSION_DATE, CHEST_DATA, ABDOMINAL_DATA) ");
sq.append("VALUES ( ");
sq.append("?, ?, ?, ?, ?");
sq.append(")");
System.out.println("Creating statement...");
try {
//stmt = conn.createStatement();
stmt = conn.prepareStatement(sq.toString());
stmt.setString(1, gusername);
stmt.setInt(2, result2);
stmt.setDate(3, sqlDate);
stmt.setFloat(4, data1);
stmt.setFloat(5, data2);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
result = stmt.executeUpdate();
count = count + 1;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//STEP 6: Clean-up environment
try {
stmt.close();
} catch (SQLException e) {
}
if (count == 400){
JOptionPane.showMessageDialog(null,"You Have Successfully Completed The Test");
conn.close();
report.main(gusername);
setVisible(false);
//dispose();
close();
//respiratorytest.successicon();
}
} catch (Exception e) {
System.err.println("Exception serialEvent=" + e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}
public static void main(String username) throws Exception {
gusername = username;
conn = DBman.main();
Statement stmt2 = null;
sql = "SELECT COUNT(DISTINCT SESSION_NUM) AS rnum FROM U_DATA WHERE USERNAME='"+gusername+"'";
ResultSet rs;
try {
stmt2 = conn.createStatement();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
rs = stmt2.executeQuery(sql);
rs.next();
result2 = rs.getInt("rnum");
result2 = result2 + 1;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
demo = new respiratorytest2("Respiratory Test");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(false);
}
}

You can add a second series to the chart, as shown here using TimeSeriesCollection:
or here using DynamicTimeSeriesCollection:
Use java.swing.Timer to poll the serial port periodically or a SwingWorker to query the serial port in the background, as shown here and here.

Related

Read Excel data and use it in selenium

This script is to read data from excel and use it in selenium script. This uses Apache POI to read the data, store it in variables and use it.
You can try following code. I have taken facebook as sample application.
package testPackage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.*;
import org.testng.annotations.DataProvider;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
public class ExcelReadingwithDP {
WebDriver driver;
#BeforeTest
public void OpenApp()
{
System.setProperty("webdriver.chrome.driver", "E:/Selenium/Webdriver/Softwares/chromedriver.exe");
driver = new ChromeDriver();
driver.navigate().to("http://facebook.com");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#Test(dataProvider="empLogin")
public void login(String username, String password)
{
WebElement login1 = driver.findElement(By.id("email"));
login1.clear();
login1.sendKeys(username);
WebElement passwd=driver.findElement(By.id("pass"));
passwd.clear();
passwd.sendKeys(password);
driver.findElement(By.xpath("//*[#id='u_0_q']")).click();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
WebElement back = driver.findElement(By.xpath("//*[#id='blueBarDOMInspector']/div/div[1]/div/div/h1/a/i"));
back.click();
}
#DataProvider(name="empLogin")
public Object[][] logindata()
{
Object[][] arrayobject = getexceldata("E://Deepak/IntranetLogin.xls","Sheet1");
return arrayobject;
}
public String[][] getexceldata(String filename, String sheetname)
{
String[][] arrayexceldata = null;
try
{
FileInputStream fis = new FileInputStream(filename);
Workbook wb = Workbook.getWorkbook(fis);
Sheet sh = wb.getSheet(sheetname);
int row = sh.getRows();
int col = sh.getColumns();
arrayexceldata = new String[row-1][col];
for (int i=1;i< row;i++)
{
for(int j=0;j<col;j++)
{
arrayexceldata[i-1][j]=sh.getCell(j,i).getContents();
}
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
e.printStackTrace();
} catch (BiffException e) {
e.printStackTrace();
}
return arrayexceldata;
}
}
/*
* Download Apache POI from https://www.apache.org/dyn/closer.lua/poi/release/bin/poi-bin-3.16-20170419.zip
*
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class FormFill {
public static void main(String[] args) throws Exception {
try {
FileInputStream fileInputStream = new FileInputStream("C:\\data.xls");
HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
HSSFSheet worksheet = workbook.getSheet("sheet1");
HSSFRow row1 = worksheet.getRow(0);
HSSFCell cellA1 = row1.getCell((short) 0);
String a1Val = cellA1.getStringCellValue();
HSSFCell cellB1 = row1.getCell((short) 1);
String b1Val = cellB1.getStringCellValue();
System.out.println("A1: " + a1Val);
System.out.println("B1: " + b1Val);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String url = "http://thedemosite.co.uk/addauser.php";
System.setProperty("webdriver.chrome.driver", "C:\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get(url);
//Thread.sleep(30000);
driver.findElement(By.name("username")).sendKeys(a1Val);
driver.findElement(By.name("password")).sendKeys(b1Val);
}
}
I feel csv is better than Excel because Excel more time to read the data but csv is fast.
private static final String CSV_SEPARATOR = ",(?=(?:[^\"]\"[^\"]\")[^\"]$)";
public List<String[]> parseFile(String fileName) {
try {
BufferedReader br = new BufferedReader(new FileReader(fileName));
br.readLine(); // skip header;
String line = br.readLine();
List<String[]> lines = new ArrayList();
while (line != null) {
//System.out.println(line.toString());
lines.add(line.split(CSV_SEPARATOR));
line = br.readLine();
}
return lines;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

how to export and import realm data in android

I know there are those questions which are similar to mine have already raised.
However, I can not go further more on some point.
** I can not copy file on below.-> realm.writeCopyTo(exportRealmFile);
** The code that I referred to is below.
https://stackoverflow.com/a/36324183/6650123
And let me share my application class which I defaulted Realm.
Wondering if the realm file can not be copied because of that..
Would you take a look and advise?
**
public class MyApplication extends Application {
private static MyApplication singleton;
private RealmConfiguration realmConfig;
String TAG=getClass().getName();
public static MyApplication getSingleton(){;
return singleton;
}
public void onCreate() {
super.onCreate();
singleton=this;
// Create the Realm configuration
realmConfig = new RealmConfiguration.Builder(this).build();
Realm.setDefaultConfiguration(realmConfig);
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
public void onLowMemory() {
super.onLowMemory();
}
public void onTerminate() {
super.onTerminate();
}
}
// my codes for backup realm
package com.first.project;
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import io.realm.Realm;
public class RealmBackupRestore {
private final static String TAG = RealmBackupRestore.class.getName();
private Context context;
private Realm realm;
public RealmBackupRestore(Context context) {
realm= Realm.getDefaultInstance();
//this.realm = Realm.getInstance(BaseApplication.realmConfiguration);
this.context = context;
}
public void backup() {
Log.d(TAG, "realm은"+realm);
Log.d(TAG, "Realm.getDefaultInstance();은"+Realm.getDefaultInstance());
File exportRealmFile = null;
File exportRealmPATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
Log.d(TAG, "exportRealmPATH"+exportRealmPATH);
String exportRealmFileName = "aa.realm";
Log.d(TAG, "Realm DB Path = " + realm.getPath());
try {
// create a backup file
exportRealmFile = new File(exportRealmPATH, exportRealmFileName);
// if backup file already exists, delete it
exportRealmFile.delete();
// copy current realm to backup file
realm.writeCopyTo(exportRealmFile);
} catch (IOException e) {
e.printStackTrace();
}
String msg = "File exported to Path: " +Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
Log.d(TAG, msg);
realm.close();
}
public void restore() {
//Restore
File exportRealmPATH = context.getExternalFilesDir(null);
String FileName = "default.realm";
String restoreFilePath = context.getExternalFilesDir(null) + "/" + FileName;
Log.d(TAG, "oldFilePath = " + restoreFilePath);
copyBundledRealmFile(restoreFilePath, FileName);
Log.d(TAG, "Data restore is done");
}
private String copyBundledRealmFile(String oldFilePath, String outFileName) {
try {
File file = new File(context.getFilesDir(), outFileName);
Log.d(TAG, "context.getFilesDir() = " + context.getFilesDir().toString());
FileOutputStream outputStream = new FileOutputStream(file);
FileInputStream inputStream = new FileInputStream(new File(oldFilePath));
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, bytesRead);
}
outputStream.close();
return file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private String dbPath() {
return realm.getPath();
}
}

write output in new file using buffer writter

Output of this program I want to write in new file.so how can I generate new file like xls. or other and write the results in it.
I had already read the file then applied kmean clustering algorithm and generate output now I want to write that.
package kmean;
//package greenblocks.statistics;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import weka.clusterers.SimpleKMeans;
import weka.core.Instances;
/**
*
* #author admin
*/
public class Kmean {
public static BufferedReader readDataFile(String filename) {
BufferedReader inputReader = null;
try {
inputReader = new BufferedReader(new FileReader(filename));
} catch (FileNotFoundException ex) {
System.err.println("File not found: " + filename);
}
return inputReader;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, Exception {
SimpleKMeans kmeans = new SimpleKMeans();
kmeans.setSeed(10);
//important parameter to set: preserver order, number of cluster.
kmeans.setPreserveInstancesOrder(true);
kmeans.setNumClusters(5);
BufferedReader datafile = readDataFile("elecNormNew.arff");
// BufferedReader datafile = readDataFile("perturbed.csv");
Instances data = new Instances(datafile);
kmeans.buildClusterer(data);
// This array returns the cluster number (starting with 0) for each instance
// The array has as many elements as the number of instances
int[] assignments = kmeans.getAssignments();
int i=0;
for(int clusterNum : assignments) {
System.out.printf("Instance %d -> Cluster %d \n", i, clusterNum);
i++;
}
// TODO code application logic here
}
}
use this code to write your output in new text file... may this will help you
package com.mkyong;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class WriteToFileExample {
public static void main(String[] args) {
try {
String content = "This is the content to write into file";
File file = new File("/filePath/filename.txt");
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
System.out.println("Done");
} catch (IOException e) {
e.printStackTrace();
}
}
}

XYDataset with a single data point : nothing gets plotted

This is a corner case I encountered. Below's a SSCCE:
import java.util.*;
import java.io.*;
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import org.jfree.data.time.*;
import org.jfree.data.xy.XYDataset;
public class FooMain {
public static void main(String args[]) throws Exception {
BufferedImage img = timeAxisSSEProcessionsChart();
ImageIO.write(img, "png", new File("img.png"));
System.exit(0);
}
private static XYDataset createTimeSeriesDataset() {
TimeSeries timeSeries = new TimeSeries("series-a");
timeSeries.add(RegularTimePeriod.createInstance(Millisecond.class, new java.util.Date(0) , TimeZone.getTimeZone("Zulu")), 100);
// if below line is commented out, nothing is plotted:
timeSeries.add(RegularTimePeriod.createInstance(Millisecond.class, new java.util.Date(1000), TimeZone.getTimeZone("Zulu")), 100);
TimeSeriesCollection rv = new TimeSeriesCollection();
rv.addSeries(timeSeries);
return rv;
}
public static BufferedImage timeAxisSSEProcessionsChart() throws Exception {
XYDataset dataset = createTimeSeriesDataset();
JFreeChart chart = ChartFactory.createTimeSeriesChart("title", "date", "series-a", dataset, true, true, false);
InputStream in = new ByteArrayInputStream(imageBytesFromChart(chart, 600, 400));
return ImageIO.read(in);
}
private static byte[] imageBytesFromChart(JFreeChart chart, int width, int height) {
BufferedImage objBufferedImage = chart.createBufferedImage(width, height);
ByteArrayOutputStream bas = new ByteArrayOutputStream();
try {
ImageIO.write(objBufferedImage, "png", bas);
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray=bas.toByteArray();
return byteArray;
}
}
The above code produces a plot as expected.
If however we comment out the line indicated in the createTimeSeriesDataset method, then nothing gets plotted:
So the question is: how can I ensure that at least a dot (or some other mark) gets printed in the corner case where the XYDataset contains only one data point?
The time series chart primarily consists of lines connecting the individual data points. When there is only one data element, there are no data points to connect. So far, so obvious.
One possible solution would be to enable the "tick shapes" for the chart when there is only one entry. I'm not sure whether this is an appropriate solution for your case. But this could be done with a method like
private static void showTickMarksForSingleElements(
XYDataset dataset, JFreeChart chart)
{
TimeSeriesCollection timeSeriesCollection =
(TimeSeriesCollection)dataset;
List<?> series = timeSeriesCollection.getSeries();
TimeSeries timeSeries = (TimeSeries) series.get(0);
if (timeSeries.getItemCount() == 1)
{
XYPlot plot = (XYPlot) chart.getPlot();
XYLineAndShapeRenderer renderer
= (XYLineAndShapeRenderer) plot.getRenderer();
renderer.setSeriesShapesVisible(0, true);
}
}
(Caution, there are obviously some assumptions about the types of the given objects involved - in doubt, check the types before doing the casts!)
The result would then be a single tick mark for time series that only contain a single element:
Here as another MVCE:
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.TimeZone;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
public class SingleElementChart {
public static void main(String args[]) throws Exception {
BufferedImage img = timeAxisSSEProcessionsChart();
show(img);
}
private static void show(final BufferedImage img)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JLabel(new ImageIcon(img)));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
private static TimeSeriesCollection createTimeSeriesDataset() {
TimeSeries timeSeries = new TimeSeries("series-a");
timeSeries.add(RegularTimePeriod.createInstance(
Millisecond.class, new java.util.Date(0),
TimeZone.getTimeZone("Zulu")), 100);
// if below line is commented out, nothing is plotted:
//timeSeries.add(RegularTimePeriod.createInstance(
// Millisecond.class, new java.util.Date(1000),
// TimeZone.getTimeZone("Zulu")), 100);
TimeSeriesCollection rv = new TimeSeriesCollection();
rv.addSeries(timeSeries);
return rv;
}
public static BufferedImage timeAxisSSEProcessionsChart() throws Exception {
XYDataset dataset = createTimeSeriesDataset();
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"title", "date", "series-a", dataset, true, true, false);
showTickMarksForSingleElements(dataset, chart);
InputStream in = new ByteArrayInputStream(
imageBytesFromChart(chart, 600, 400));
return ImageIO.read(in);
}
private static void showTickMarksForSingleElements(
XYDataset dataset, JFreeChart chart)
{
TimeSeriesCollection timeSeriesCollection =
(TimeSeriesCollection)dataset;
List<?> series = timeSeriesCollection.getSeries();
TimeSeries timeSeries = (TimeSeries) series.get(0);
if (timeSeries.getItemCount() == 1)
{
XYPlot plot = (XYPlot) chart.getPlot();
XYLineAndShapeRenderer renderer
= (XYLineAndShapeRenderer) plot.getRenderer();
renderer.setSeriesShapesVisible(0, true);
}
}
private static byte[] imageBytesFromChart(JFreeChart chart, int width, int height) {
BufferedImage objBufferedImage =
chart.createBufferedImage(width, height);
ByteArrayOutputStream bas = new ByteArrayOutputStream();
try {
ImageIO.write(objBufferedImage, "png", bas);
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray=bas.toByteArray();
return byteArray;
}

ArrayIndexOutOfBoundsException error when writing to a tag

I followed a tutorial on how to write a NDEF message to a tag. and now when I run it. it detects the tag and when I press the button to write the message and the app crashes. it gives me JAVA.LANG.ArrayIndexOutOfBoundsException can someone please help me on what I'm doing wrong.
this is the error I see in logcat.
any help is appreciated.
Here is the code:
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class WriteMessage extends Activity {
NfcAdapter adapter;
PendingIntent pendingIntent;
IntentFilter writeTagFilters[];
boolean writeMode;
Tag myTag;
Context ctx;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_message);
ctx=this;
Button WriteTag = (Button) findViewById (R.id.WriteTag);
final TextView Message = (TextView) findViewById (R.id.MessageBox);
WriteTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
if(myTag==null){
Toast.makeText(ctx, "Error_detected", Toast.LENGTH_LONG).show();
}else{
write(Message.getText().toString(), myTag);
Toast.makeText(ctx, "Ok_Writing", Toast.LENGTH_LONG).show();
}
}catch(IOException e){
Toast.makeText(ctx, "Error_Writing", Toast.LENGTH_LONG).show();
e.printStackTrace();
//} catch(FormatException e){
e.printStackTrace();
} catch (FormatException e) {
// TODO Auto-generated catch block
Toast.makeText(ctx, "Error_Writing", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
});
adapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(this, 0, new Intent (this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter (NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
writeTagFilters = new IntentFilter[] {tagDetected };
}
private void write(String text, Tag myTag)throws IOException, FormatException {
NdefRecord[] records = {createRecord(text)};
NdefMessage message = new NdefMessage(records);
Ndef ndef = Ndef.get(myTag);
ndef.connect();
ndef.writeNdefMessage(message);
ndef.close();
}
private NdefRecord createRecord (String text ) throws UnsupportedEncodingException {
String lang = "en";
byte[] textBytes = text.getBytes();
byte[] langBytes = lang.getBytes("US-ASCII");
int langLength = langBytes.length;
int textLength = textBytes.length;
byte[] payload = new byte [1+ langLength + textLength ];
payload[0] = (byte) langLength;
System.arraycopy(langBytes, 0, payload, 1, langLength);
System.arraycopy(langBytes, 0, payload, 1 + langLength, textLength);
NdefRecord recordNFC = new NdefRecord (NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
return recordNFC;
}
#Override
protected void onNewIntent(Intent intent){
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Toast.makeText(this, "ok_detection" + myTag.toString(), Toast.LENGTH_LONG ).show();
}
}
#Override
public void onPause(){
super.onPause();
WriteModeOff();
}
#Override
public void onResume(){
super.onResume();
WriteModeOn();
}
private void WriteModeOn(){
writeMode = true;
adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null);
}
private void WriteModeOff(){
writeMode = false;
adapter.disableForegroundDispatch(this);
}
}
Looks like createRecord() is copying langBytes into payload twice instead of copying textBytes, but with the length of textBytes. If textBytes is longer than langBytes, it won't find enough data to copy from the source.
See the documentation on arraycopy.

Resources