I have a program that connects client threads to a cinema through a socket.
the client transfers his details (client no., required tickets) the cinema processes the request in another thread that makes sure there is enough seats available.
as you will see in the code, i have a slight problem with figuring out how to send a feedback to the client from the cinema(server), the code presented is not completed, i just wanted to give you an idea of how it looks.
my idea is to transfer the dataOutputStream to the cinemaThread and when its done, the cinema thread will return the feedback through the stream to the client is it possible?
Client side
import java.util.Random;
/**
* this class in designed to define client properties
* #author David and Adam
*
*/
public class Client extends Thread{
private int serialNumber;
private int NumberOfTickets;
private String creditNumber;
private String serverPort;
private int rowNumber;
/**
* full constructor
* #param serialNumber
* #param NumberOfTickets
* #param creditNumber
*/
public Client(int serialNumber){
this.serialNumber = serialNumber;
this.NumberOfTickets = generateTicketNumber();
this.creditNumber = generateCreditNumber();
this.rowNumber = -1;
}
/**
* returns a value in the required number of ticket range.
* #return
*/
private int generateTicketNumber(){
return (new Random()).nextInt(Constants.MaxNumberOfTickets-1)+Constants.MinNumberOfTickets;
}
/**
* returns a random credit number constructed of 16 digits.
* #return
*/
private String generateCreditNumber(){
String s = String.valueOf((new Random()).nextInt(9)+1);
for(int i=0 ; i<16 ; i++){
s = (new Random()).nextInt()+s;
}
return s;
}
Server side
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* an implementation of server side defined as cinema hall
* #author David
*
*/
public class Cinema {
private int[][] cinemaHall;
private int ticketPrice;
private int securedPort;
private int numberOfRequests;
/**
* full constructor
*
*/
public Cinema(){
this.numberOfRequests = 0;
initializeCinemaHall();
setTicketPrice();
setSecuredPort();
}
/**
* initializes cinema hall to 0's
*/
private void initializeCinemaHall(){
this.cinemaHall = new int[10][10];
for(int i=0 ; i<cinemaHall.length ; i++)
for(int j=0 ; j<cinemaHall.length ; j++)
this.cinemaHall[i][j] = 0;
}
/**
* generates the ticket price on sale
*/
private void setTicketPrice(){
this.ticketPrice = Constants.TicketSalePrice;
}
/**
* sets the secured port
*
*/
private void setSecuredPort(){
this.securedPort = Constants.SecuredPort;
}
public int[][] getCinemaHall() {
return cinemaHall;
}
public void setCinemaHall(int[][] cinemaHall) {
this.cinemaHall = cinemaHall;
}
public int getTicketPrice() {
return ticketPrice;
}
public void setTicketPrice(int ticketPrice) {
this.ticketPrice = ticketPrice;
}
public int getNumberOfRequests() {
return numberOfRequests;
}
public void setNumberOfRequests(int numberOfRequests) {
this.numberOfRequests = numberOfRequests;
}
/**
* main function for establishing communication between cinema and customers
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException{
Cinema cinema = new Cinema();
ServerSocket server = new ServerSocket(Constants.ServerPort);
System.out.println("**********Yes Planet server in listening**********");
// create a connection to clients
while(cinema.numberOfRequests<Constants.MaxClientNumber){
try {
//wait for client
Socket s = server.accept();
System.out.println("Client connected to socket");
// get client info
DataInputStream dis = new DataInputStream(s.getInputStream());
String clientInfo = dis.readLine();
String[] details = clientInfo.split("/");
try {
// parse data to correct type and send data to cinema thread
Thread cinemaThread = new CinemaThread(cinema, Integer.parseInt(details[0])
, Integer.parseInt(details[1]), details[2]);
cinemaThread.start();
}
catch (Exception e){
System.out.println("An error has occured, client request have been canceled");
}
} catch (IOException e) {
System.out.println("Connection error ");
e.printStackTrace();
}
}
}
}
Cinema Thread
public class CinemaThread extends Thread{
private int clientNumber;
private Cinema cinema;
private int requiredTickets;
private String clientCreditNumber;
private boolean occupied;
private int lineNumber;
private boolean alive;
/**
* full constructor
* #param clientNumber
* #param cinema
* #param requiredTickets
* #param clientCreditNumber
*/
public CinemaThread(Cinema cinema, int clientNumber, int requiredTickets, String clientCreditNumber){
this.clientNumber = clientNumber;
this.cinema = cinema;
this.requiredTickets = requiredTickets;
this.clientCreditNumber = clientCreditNumber;
this.occupied = false;
this.lineNumber = -1;
this.alive = true;
}
/**
* the method checks for available seats to each individual required client.
* in case an available sequence is found, cinema hall is updated with client details and a connection
* with the credit company is established forwarding the data needed to proceed.
*/
public void run(){
int ticketCount=0;
int startSeat = -1;
int endSeat = -1;
for(int i=0 ; i<cinema.getCinemaHall().length && !occupied; i++){
for(int j=0 ; j<cinema.getCinemaHall().length && !occupied; j++){
if(cinema.getCinemaHall()[i][j]>0)
ticketCount++;
else
ticketCount=0;
if(ticketCount == requiredTickets){
lineNumber = i;
startSeat = j-requiredTickets+1;
endSeat = j;
occupied=true;
}
}
for(int k=startSeat ;k<=endSeat ; k++)
cinema.getCinemaHall()[lineNumber][k] = clientNumber;
}
if(occupied){
// connection with credit company
}
this.alive = false;
}
public boolean status(){
return this.alive;
}
}
You don't need to transfer a DataOutputStream. Use Socket.getOutputStream().
server side
public static void main(String[] args) throws IOException{
// ... ...
// Socket s = server.accept();
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
// ... ...
Thread cinemaThread = new CinemaThread( /* ... */, dos);
// ... ...
}
public CinemaThread(/* ... */, DataOutputStream dos){
// ... ...
this.dos = dos;
}
public void run(){
// ... ...
if(occupied)
dos.writeBoolean(true);
else
dos.writeBoolean(false);
// ... ...
}
Streams are typically one way 'out' or 'in', so by my reading of the question, no it is not possible to use one stream for both.
Related
I am using Microsoft Cognitive Services - Speech Recognition on an Android application. Everything works fine when the code is in my main activity, but when I want to move the part corresponding to speech recognition to a new class, it throws an error.
Here are the code samples:
In the main activity
int m_waitSeconds = 0;
MicrophoneRecognitionClient micClient = null;
FinalResponseStatus isReceivedResponse = FinalResponseStatus.NotReceived;
Boolean speechIntent = false;
SpeechRecognitionMode speechMode = SpeechRecognitionMode.ShortPhrase;
public enum FinalResponseStatus { NotReceived, OK }
/**
* Gets the primary subscription key
*/
public String getPrimaryKey() {
return this.getString(R.string.primaryKey);
}
/**
* Gets the secondary subscription key
*/
public String getSecondaryKey() {
return this.getString(R.string.secondaryKey);
}
/**
* Gets the LUIS application identifier.
* #return The LUIS application identifier.
*/
private String getLuisAppId() {
return this.getString(R.string.luisAppID);
}
/**
* Gets the LUIS subscription identifier.
* #return The LUIS subscription identifier.
*/
private String getLuisSubscriptionID() {
return this.getString(R.string.luisSubscriptionID);
}
/**
* Gets the default locale.
* #return The default locale.
*/
private String getDefaultLocale() {
return "en-us";
}
/**
* Handles the Click event of the _startButton control.
*/
private void StartButton_Click(View v) {
this.m_waitSeconds = this.speechMode == SpeechRecognitionMode.ShortPhrase ? 20 : 200;
if (this.micClient == null) {
if (this.speechIntent) {
this.WriteLine("--- Start microphone dictation with Intent detection ----");
this.micClient = SpeechRecognitionServiceFactory.createMicrophoneClientWithIntent(
this,
this.getDefaultLocale(),
this,
this.getPrimaryKey(),
this.getSecondaryKey(),
this.getLuisAppId(),
this.getLuisSubscriptionID());
}
else
{
this.micClient = SpeechRecognitionServiceFactory.createMicrophoneClient(
this,
this.speechMode,
this.getDefaultLocale(),
this,
this.getPrimaryKey(),
this.getSecondaryKey());
}
}
this.micClient.startMicAndRecognition();
}
public void onFinalResponseReceived(final RecognitionResult response) {
boolean isFinalDicationMessage = this.speechMode == SpeechRecognitionMode.LongDictation &&
(response.RecognitionStatus == RecognitionStatus.EndOfDictation ||
response.RecognitionStatus == RecognitionStatus.DictationEndSilenceTimeout);
if (null != this.micClient && ((this.speechMode == SpeechRecognitionMode.ShortPhrase) || isFinalDicationMessage)) {
// we got the final result, so it we can end the mic reco. No need to do this
// for dataReco, since we already called endAudio() on it as soon as we were done
// sending all the data.
this.micClient.endMicAndRecognition();
}
if (isFinalDicationMessage) {
this.isReceivedResponse = FinalResponseStatus.OK;
}
Confidence cMax = Confidence.Low;
int iMax = 0;
if (!isFinalDicationMessage && response.Results.length != 0) {
for (int i = 0; i < response.Results.length; i++) {
//get the text with highest confidence:
if(response.Results[i].Confidence.getValue() > cMax.getValue()){
cMax = response.Results[i].Confidence;
iMax = i;
}
}
this.WriteLine(response.Results[iMax].DisplayText);
}
}
/**
* Called when a final response is received and its intent is parsed
*/
public void onIntentReceived(final String payload) {
this.WriteLine("--- Intent received by onIntentReceived() ---");
this.WriteLine(payload);
this.WriteLine();
}
public void onPartialResponseReceived(final String response) {
this.WriteLine("--- Partial result received by onPartialResponseReceived() ---");
this.WriteLine(response);
this.WriteLine();
}
public void onError(final int errorCode, final String response) {
this.WriteLine("--- Error received by onError() ---");
this.WriteLine("Error code: " + SpeechClientStatus.fromInt(errorCode) + " " + errorCode);
this.WriteLine("Error text: " + response);
this.WriteLine();
}
/**
* Called when the microphone status has changed.
* #param recording The current recording state
*/
public void onAudioEvent(boolean recording) {
if (!recording) {
this.micClient.endMicAndRecognition();
}
}
/**
* Writes the line.
*/
private void WriteLine() {
this.WriteLine("");
}
/**
* Writes the line.
* #param text The line to write.
*/
private void WriteLine(String text) {
System.out.println(text);
}
In a separate class
public class SpeechRecognition implements ISpeechRecognitionServerEvents
{
int m_waitSeconds = 0;
private MicrophoneRecognitionClient micClient = null;
private FinalResponseStatus isReceivedResponse =FinalResponseStatus.NotReceived;
private Boolean speechIntent = false;
private SpeechRecognitionMode speechMode=SpeechRecognitionMode.ShortPhrase;
public enum FinalResponseStatus { NotReceived, OK }
/**
* Gets the primary subscription key
*/
public String getPrimaryKey() {
return Integer.toString(R.string.primaryKey);
}
/**
* Gets the secondary subscription key
*/
public String getSecondaryKey() {
return Integer.toString(R.string.secondaryKey);
}
/**
* Gets the LUIS application identifier.
* #return The LUIS application identifier.
*/
private String getLuisAppId() {
return Integer.toString(R.string.luisAppID);
}
/**
* Gets the LUIS subscription identifier.
* #return The LUIS subscription identifier.
*/
private String getLuisSubscriptionID() {
return Integer.toString(R.string.luisSubscriptionID);
}
/**
* Gets the default locale.
* #return The default locale.
*/
private String getDefaultLocale() {
return "en-us";
}
public void startSpeechRecognition() {
this.m_waitSeconds = this.speechMode == SpeechRecognitionMode.ShortPhrase ? 20 : 200;
if (this.micClient == null) {
if (this.speechIntent) {
this.micClient = SpeechRecognitionServiceFactory.createMicrophoneClientWithIntent(
this.getDefaultLocale(),
this,
this.getPrimaryKey(),
this.getSecondaryKey(),
this.getLuisAppId(),
this.getLuisSubscriptionID());
}
else
{
this.micClient = SpeechRecognitionServiceFactory.createMicrophoneClient(
this.speechMode,
this.getDefaultLocale(),
this,
this.getPrimaryKey(),
this.getSecondaryKey());
}
}
this.micClient.startMicAndRecognition();
}
public void endSpeechRecognition(){
this.micClient.endMicAndRecognition();
}
public void onFinalResponseReceived(final RecognitionResult response) {
boolean isFinalDicationMessage = this.speechMode == SpeechRecognitionMode.LongDictation &&
(response.RecognitionStatus == RecognitionStatus.EndOfDictation ||
response.RecognitionStatus == RecognitionStatus.DictationEndSilenceTimeout);
if (null != this.micClient && ((this.speechMode == SpeechRecognitionMode.ShortPhrase) || isFinalDicationMessage)) {
// we got the final result, so it we can end the mic reco. No need to do this
// for dataReco, since we already called endAudio() on it as soon as we were done
// sending all the data.
this.micClient.endMicAndRecognition();
}
if (isFinalDicationMessage) {
this.isReceivedResponse = FinalResponseStatus.OK;
}
Confidence cMax = Confidence.Low;
int iMax = 0;
if (!isFinalDicationMessage && response.Results.length != 0) {
for (int i = 0; i < response.Results.length; i++) {
//get the text with highest confidence:
if(response.Results[i].Confidence.getValue() > cMax.getValue()){
cMax = response.Results[i].Confidence;
iMax = i;
}
}
System.out.println("Action to take: " + response.Results[iMax].DisplayText);
}
}
/**
* Called when a final response is received and its intent is parsed
*/
public void onIntentReceived(final String payload) {
System.out.println("--- Intent received by onIntentReceived() ---");
System.out.println(payload);
}
public void onPartialResponseReceived(final String response) {
System.out.println("--- Partial result received by onPartialResponseReceived() ---");
System.out.println(response);
}
public void onError(final int errorCode, final String response) {
System.err.println("--- Error received by onError() ---");
System.err.println("Error code: " + SpeechClientStatus.fromInt(errorCode) + " " + errorCode);
System.err.println("Error text: " + response);
}
/**
* Called when the microphone status has changed.
* #param recording The current recording state
*/
public void onAudioEvent(boolean recording) {
System.out.println("--- Microphone status change received by onAudioEvent() ---");
System.out.println("********* Microphone status: " + recording + " *********");
if (recording) {
System.out.println("Please start speaking.");
}
if (!recording) {
this.micClient.endMicAndRecognition();
}
}
}
You can clearly see that it is basically the same code but it gives me this error in the onError function after i call this.micClient.startMicAndRecognition();
:
Error code: LoginFailed -1910505470
I solved the problem.
I was getting a wrong Primary key in this line of code:
public String getPrimaryKey() {
return Integer.toString(R.string.primaryKey);
}
It is because the primary key is too long to be read by the processor as an integer then transformed to a String. I had to get the primary key from the main activity via getString(R.string.primaryKey) then pass it as a parameter to the constructor of the SpeechRecognition class.
I am implementing an java program that scans some of the smart devices that I have, using SSDP discovery. The code that I am using detects only 2 devices among 10 that are connected to my local network. I could not understand the reason is.
My question is, why I am not able to get all the devices that are in my local network.
This is the code that I am using
static final String HOST = "Host:" + SSDP.ADDRESS + ":" + SSDP.PORT;
static final String MAN = "Man: \"ssdp:discover\"";
static final String NEWLINE = "\r\n";
int mMX = 10; /* seconds to delay response */
String mST; /* Search target */
public SSDPSearchMsg(String ST) {
mST = ST;
}
public int getmMX() {
return mMX;
}
public void setmMX(int mMX) {
this.mMX = mMX;
}
public String getmST() {
return mST;
}
public void setmST(String mST) {
this.mST = mST;
}
#Override
public String toString() {
StringBuilder content = new StringBuilder();
content.append(SSDP.SL_MSEARCH).append(NEWLINE);
content.append(HOST).append(NEWLINE);
content.append(MAN).append(NEWLINE);
content.append(mST).append(NEWLINE);
content.append("MX:" + mMX).append(NEWLINE);
content.append(NEWLINE);
return content.toString();
}
Below is few constants
/* New line definition */
public static final String NEWLINE = "\r\n";
public static final String ADDRESS = "239.255.255.250";
public static final int PORT = 1900;
/* Definitions of start line */
public static final String SL_NOTIFY = "NOTIFY * HTTP/1.1";
public static final String SL_MSEARCH = "M-SEARCH * HTTP/1.1";
public static final String SL_OK = "HTTP/1.1 200 OK";
/* Definitions of search targets */
public static final String ST_RootDevice = "ST: upnp:rootdevice";
public static final String ST_ContentDirectory = "ST: urn:schemas-upnp-org:service:ContentDirectory:1";
public static final String ST_ALL="ST: ssdp:all";
public static final String ST_Media="ST:urn:schemas-upnp-org:device:MediaRenderer:1";
/* Definitions of notification sub type */
public static final String NTS_ALIVE = "NTS:ssdp:alive";
public static final String NTS_BYE = "NTS:ssdp:byebye";
public static final String NTS_UPDATE = "NTS:ssdp:update";
Main class
public class SSDPSocket {
SocketAddress mSSDPMulticastGroup;
MulticastSocket mSSDPSocket;
public SSDPSocket() throws IOException {
InetAddress localInAddress = InetAddress.getLocalHost();
System.out.println("Local address: " + localInAddress.getHostAddress());
mSSDPMulticastGroup = new InetSocketAddress(SSDP.ADDRESS, SSDP.PORT);
mSSDPSocket = new MulticastSocket(new InetSocketAddress(localInAddress,
0));
NetworkInterface netIf = NetworkInterface
.getByInetAddress(localInAddress);
mSSDPSocket.joinGroup(mSSDPMulticastGroup, netIf);
}
/* Used to send SSDP packet */
public void send(String data) throws IOException {
DatagramPacket dp = new DatagramPacket(data.getBytes(), data.length(),
mSSDPMulticastGroup);
mSSDPSocket.send(dp);
}
/* Used to receive SSDP packet */
public DatagramPacket receive() throws IOException {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
mSSDPSocket.receive(dp);
return dp;
}
public void close() {
if (mSSDPSocket != null) {
mSSDPSocket.close();
}
}
/* For test purpose */
public static void main(String[] args) {
SSDPSearchMsg search = new SSDPSearchMsg(SSDP.ST_Media);
System.out.println(search.toString());
SSDPSocket sock;
try {
sock = new SSDPSocket();
sock.send(search.toString());
while (true) {
DatagramPacket dp = sock.receive();
String c = new String(dp.getData());
System.out.println(c);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Can anyone please suggest a solution for this problem?
I just worked on an SSDP Java client and studied the spec carefully.
You are missing an "MX" header. If the header MX is not set, the SSDP Service "SHOULD" not respond to your request.
Therefore, try adding an "MX: 1" header and see where this goes.
The Schneider database was of good help for this issue.
Also, you can take a look at the ssdp client if you still are trying to use it.
I have created an sql database with a table containing information about Airplanes, I want to be able to take this information and insert it into an ArrayList of type Aircraft(object) although the different info in the sql table are different primitive types........can this be done?`package uk.ac.qub.sqldbflights;
This is the Aircraft object with all the attributes which are the
public class Aircraft {
/**
* private String containing the airline name of the aircraft
* -Can't be blank
*/
private int aircraft_number;
/**
* private String containing the flight number belonging to the aircraft
* -Can't be blank
*/
private String airline_company;
/**
* private String containing the aircrafts city of origin
* -Can't be blank
*/
private String departure_airport;
/**
* private int which holds the aircrafts fuel level
* -Must be over 0 and less than 100
*/
private float passenger_number;
/**
* private int containing the number of passengers aboard the aircraft
* -Must be over 0 and less than 300
*/
private float fuel_percentage;
/**
* private Boolean indicting wether the aircraft is in the landing queue or not
*/
private int flight_time_remaining;
/**
* private Boolean indicating wether the aircraft is landed or not
*/
private boolean in_queue;
private boolean is_landed;
public Aircraft() {
}
/**
* Song creation
* #param name -not null
* #param artist -not null
* #param album -not null
* #param genre- not null and one of Pop, Dance, Rock
* #throws IllegalArgumentException
*/
public Aircraft(int aircraft_number, String airline_company, String departure_airport, int passenger_number, float fuel_percentage, int flight_time_remaining, boolean in_queue, boolean is_landed)
throws IllegalArgumentException {
try {
// set name
this.setAircraft_number(aircraft_number);
this.setAirline_company(airline_company);
this.setDeparture_airport(departure_airport);
this.setPassenger_number(passenger_number);
this.setFuel_percentage(fuel_percentage);
this.setFlight_time_remaining(flight_time_remaining);
this.setIn_queue(in_queue);
this.setIs_landed(is_landed);
} catch (IllegalArgumentException ex) {
System.out.println("Unable to create song due to arguments passed");
throw ex;
}}
public int getAircraft_number() {
return aircraft_number;
}
public void setAircraft_number(int aircraft_number) {
this.aircraft_number = aircraft_number;
}
public String getAirline_company() {
return airline_company;
}
public void setAirline_company(String airline_company) {
this.airline_company = airline_company;
}
public String getDeparture_airport() {
return departure_airport;
}
public void setDeparture_airport(String departure_airport) {
this.departure_airport = departure_airport;
}
public float getPassenger_number() {
return passenger_number;
}
public void setPassenger_number(float passenger_number) {
this.passenger_number = passenger_number;
}
public float getFuel_percentage() {
return fuel_percentage;
}
public void setFuel_percentage(float fuel_percentage) {
this.fuel_percentage = fuel_percentage;
}
public int isFlight_time_remaining() {
return flight_time_remaining;
}
public void setFlight_time_remaining(int flight_time_remaining) {
this.flight_time_remaining = flight_time_remaining;
}
public boolean isIn_queue() {
return in_queue;
}
public void setIn_queue(boolean in_queue) {
this.in_queue = in_queue;
}
public boolean isIs_landed() {
return is_landed;
}
public void setIs_landed(boolean is_landed) {
this.is_landed = is_landed;
}
}
This is the code which makes the connection to the sql DB and trys to add the info to an arraylist...
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class FlightsDbtoArrayList {
ArrayList<Aircraft> allFlights = new ArrayList<Aircraft>();
public static void main(String[] args) {
// Entering username to verify connection to SQL Server
String url = "jdbc:mysql://";
Connection con;
Statement statement1;
try {
Class.forName("com.mysql.jdbc.Driver");
//Catching any errors and printing a message to the user
} catch(java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
try {
// Entering username and password to verify connection to SQL Server
con = DriverManager.getConnection(url);
//Creating platform for a SQL query Statement
statement1 = con.createStatement();
//Creating and executing the designed SQL query statement
ResultSet results1 = statement1.executeQuery("SELECT aircraft_number, airline_company, departure_airport, passenger_number, fuel_Percentage, flight_time_remaining, in_queue, is_landed FROM flights");
//Displaying the results of the query to screen
printResults(results1);
con.close();
statement1.close();
} catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
}
/**
* Method to display the results of the three SQL queries
* #param results
* #throws SQLException
*
*
*/
public ArrayList<Aircraft> allFlights() {
return allFlights;
}
/**
* set songs on the system
* #param allSongs
*/
public void setSongs(ArrayList<Aircraft> allSongs) {
allSongs = this.allFlights;
}
private static void printResults(ResultSet results) throws SQLException {
while (results.next()) {
int aircraft_number = results.getInt("aircraft_number");
String airline_company = results.getString("airline_company");
String departure_airport = results.getString("departure_airport");
int passenger_number = results.getInt("passenger_number");
float fuel_percentage = results.getFloat("fuel_percentage");
int flight_time_remaining = results.getInt("flight_time_remaining");
boolean in_queue = results.getBoolean("in_queue");
boolean is_landed = results.getBoolean("is_landed");
Aircraft a1;
ArrayList<Aircraft> allFlights = new ArrayList<Aircraft>();
a1 = new Aircraft(aircraft_number, airline_company, departure_airport, passenger_number, fuel_percentage, flight_time_remaining, in_queue, is_landed);
allFlights.add(a1);
System.out.println(allFlights);
}
}
}
`
Yes it is definitely possible to have list of objects(Aircraft) derived from database. But in this case your while loop inside the PrintResult has some errors.
You are creating list allFights within the while loop which will create new list in each iteration and add a1 to it so in the end you will only have a list with one aircraft details in it.
System.out.println(allFlights) will not give much desired output (or it might), but I would advice you should override toString() method in your AirCraft class.
Try to change your PrintResult method as following.
private static void printResults(ResultSet results) throws SQLException {
ArrayList<Aircraft> allFlights = new ArrayList<Aircraft>();
Aircraft a1;
while (results.next()) {
int aircraft_number = results.getInt("aircraft_number");
String airline_company = results.getString("airline_company");
String departure_airport = results.getString("departure_airport");
int passenger_number = results.getInt("passenger_number");
float fuel_percentage = results.getFloat("fuel_percentage");
int flight_time_remaining = results.getInt("flight_time_remaining");
boolean in_queue = results.getBoolean("in_queue");
boolean is_landed = results.getBoolean("is_landed");
a1 = new Aircraft(aircraft_number, airline_company, departure_airport, passenger_number, fuel_percentage, flight_time_remaining, in_queue, is_landed);
allFlights.add(a1);
//Instead of this line System.out.println(allFlights);
//write following code
For(AirCraft aircraft : allFlights){
System.out.println(aircraft.toString());
}
}
}
Edit 2: Write the following method in your AirCraft class.
#Override
Public String toString(){
String string;
//Write some code here so that you can represent you object using this method
//for example I am adding just the aircraft_number
string = getAircraft_number()+"";
return string;
}
Important: The toString() method I wrote is just an example you need to learn how to correctly write toString() method for any of your class. this and this are good starting point to learn that. And stop worrying about your your list of allFlights because as per this code it is getting created but you can not print it the way you are trying to.
I tried to save data to json string in a txt file using Gson and then restore it using Gson either. Things go well if I do it in eclipse. But when packaged to jar, Gson throws Exceptions.
Here is the code for saving the file.
String gsonStr = gson.toJson(masterShips); // masterShips is ArrayList<Ship>
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter("D:\\master_ship.txt"));
writer.write(gsonStr);
} catch (IOException e) {
System.err.println(e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
Then I read the file in eclipse using this code (and it works):
Scanner in = new Scanner(new FileReader("D:\\master_ship.txt"));
String str = in.nextLine();
Log.toDebug(str);
in.close();
JsonParser parser = new JsonParser();
JsonElement je = parser.parse(str);
JsonArray ja = je.getAsJsonArray();
for (int i=0; i<ja.size(); ++i) {
...
}
But after packaged into jar and run in cmd, Exception occurs:
Exception in thread "main" com.google.gson.JsonSyntaxException: com.google.gson.
stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malform
ed JSON at line 1 column 4
at com.google.gson.JsonParser.parse(JsonParser.java:65)
at com.google.gson.JsonParser.parse(JsonParser.java:45)
at kan.util.Master.loadMasterShip(Master.java:44)
at kan.util.Master.load(Master.java:27)
at kan.Main.main(Main.java:22)
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLeni
ent(true) to accept malformed JSON at line 1 column 4
at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1505)
at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1386)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:531)
at com.google.gson.stream.JsonReader.peek(JsonReader.java:414)
at com.google.gson.JsonParser.parse(JsonParser.java:60)
... 4 more
According to the hint of the Exception, I changed my code and it still works in eclipse:
Scanner in = new Scanner(new FileReader("D:\\master_ship.txt"));
String str = in.nextLine();
in.close();
Reader reader = new StringReader(str);
JsonReader jr = new JsonReader(reader);
jr.setLenient(true);
JsonParser parser = new JsonParser();
JsonElement je = parser.parse(jr);
JsonArray ja = je.getAsJsonArray();
for (int i=0; i<ja.size(); ++i) {
...
}
But jar failed and throws
Exception in thread "main" java.lang.IllegalStateException: This is not a JSON A
rray.
at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:106)
at kan.util.Master.loadMasterShip(Master.java:58)
at kan.util.Master.load(Master.java:30)
at kan.Main.main(Main.java:22)
As suggested by Sotirios I cut the length of the arraylist down, and when I increase the number of ships to 4, things go wrong. Here is the json:
[{"id":1,"name":"睦月","type":2,"rank":2,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":254,"range":1,"powerups":[1,1,0,0]},{"id":2,"name":"如月","type":2,"rank":1,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":255,"range":1,"powerups":[0,1,0,0]},{"id":6,"name":"長月","type":2,"rank":1,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":258,"range":1,"powerups":[0,1,0,0]},{"id":7,"name":"三日月","type":2,"rank":1,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":260,"range":1,"powerups":[0,1,0,0]}]
↑ colunm 473
Exception in thread "main" com.google.gson.JsonSyntaxException: com.google.gson.
stream.MalformedJsonException: Unterminated object at line 1 column 473
at com.google.gson.internal.Streams.parse(Streams.java:56)
at com.google.gson.JsonParser.parse(JsonParser.java:84)
at kan.util.Master.loadMasterShip(Master.java:55)
at kan.util.Master.load(Master.java:30)
at kan.Main.main(Main.java:22)
Caused by: com.google.gson.stream.MalformedJsonException: Unterminated object at
line 1 column 473
at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1505)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:480)
at com.google.gson.stream.JsonReader.hasNext(JsonReader.java:403)
at com.google.gson.internal.bind.TypeAdapters$25.read(TypeAdapters.java:
666)
at com.google.gson.internal.bind.TypeAdapters$25.read(TypeAdapters.java:
659)
at com.google.gson.internal.bind.TypeAdapters$25.read(TypeAdapters.java:
642)
at com.google.gson.internal.Streams.parse(Streams.java:44)
... 4 more
Can anyone help me with this, you will be reaally preciated!
Use this class
import java.util.List;
public class GsonResponse
{
public int id;
public String name;
public int type;
public int rank;
public int fuelMax;
public int bulletMax;
public int slotNum;
public int speed;
public int afterLv;
public int afterId;
public int range;
public List<Integer> powerups;
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the type
*/
public int getType() {
return type;
}
/**
* #param type the type to set
*/
public void setType(int type) {
this.type = type;
}
/**
* #return the rank
*/
public int getRank() {
return rank;
}
/**
* #param rank the rank to set
*/
public void setRank(int rank) {
this.rank = rank;
}
/**
* #return the fuelMax
*/
public int getFuelMax() {
return fuelMax;
}
/**
* #param fuelMax the fuelMax to set
*/
public void setFuelMax(int fuelMax) {
this.fuelMax = fuelMax;
}
/**
* #return the bulletMax
*/
public int getBulletMax() {
return bulletMax;
}
/**
* #param bulletMax the bulletMax to set
*/
public void setBulletMax(int bulletMax) {
this.bulletMax = bulletMax;
}
/**
* #return the slotNum
*/
public int getSlotNum() {
return slotNum;
}
/**
* #param slotNum the slotNum to set
*/
public void setSlotNum(int slotNum) {
this.slotNum = slotNum;
}
/**
* #return the speed
*/
public int getSpeed() {
return speed;
}
/**
* #param speed the speed to set
*/
public void setSpeed(int speed) {
this.speed = speed;
}
/**
* #return the afterLv
*/
public int getAfterLv() {
return afterLv;
}
/**
* #param afterLv the afterLv to set
*/
public void setAfterLv(int afterLv) {
this.afterLv = afterLv;
}
/**
* #return the afterId
*/
public int getAfterId() {
return afterId;
}
/**
* #param afterId the afterId to set
*/
public void setAfterId(int afterId) {
this.afterId = afterId;
}
/**
* #return the range
*/
public int getRange() {
return range;
}
/**
* #param range the range to set
*/
public void setRange(int range) {
this.range = range;
}
/**
* #return the powerups
*/
public List<Integer> getPowerups() {
return powerups;
}
/**
* #param powerups the powerups to set
*/
public void setPowerups(List<Integer> powerups) {
this.powerups = powerups;
}
}
just add below code where u parse
String strJson = "[{\"id\":1,\"name\":\"睦月\",\"type\":2,\"rank\":2,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":254,\"range\":1,\"powerups\":[1,1,0,0]},{\"id\":2,\"name\":\"如月\",\"type\":2,\"rank\":1,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":255,\"range\":1,\"powerups\":[0,1,0,0]},{\"id\":6,\"name\":\"長月\",\"type\":2,\"rank\":1,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":258,\"range\":1,\"powerups\":[0,1,0,0]},{\"id\":7,\"name\":\"三日月\",\"type\":2,\"rank\":1,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":260,\"range\":1,\"powerups\":[0,1,0,0]}]";
GsonResponse gsonResponse = null;
try {
gsonResponse = new Gson().fromJson(strJson,
GsonResponse.class);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Google Maps output=kml broken?
I started to get Error when I'm trying to retrieve Google Directions using KML data since few days. The Error seems that the URL I'm requesting doesn't retreieve KML data anymore, it returns a whole page. I followed this in order to achieve that.
What is the solution for this? Is there any alternatives?
Update:
Since Android Google Maps v2 is now used, the code needs to be adjusted to work on v2 maps which can be found here.
Original Answer:
This way of extracting the Google Directions from Google by parsing the KML file is no longer available since 27 July 2012 (because Google has changed the structure of retrieving Google Directions, now you can only get it by JSON or XML), it is time to migrate your code to JSON instead of KML.
I did it by creating 6 classes like this:
Parser.java:
public interface Parser {
public Route parse();
}
XMLParser.java:
public class XMLParser {
// names of the XML tags
protected static final String MARKERS = "markers";
protected static final String MARKER = "marker";
protected URL feedUrl;
protected XMLParser(final String feedUrl) {
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
//Log.e(e.getMessage(), "XML parser - " + feedUrl);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
//Log.e(e.getMessage(), "XML parser - " + feedUrl);
return null;
}
}
}
Segment.java:
public class Segment {
/** Points in this segment. **/
private GeoPoint start;
/** Turn instruction to reach next segment. **/
private String instruction;
/** Length of segment. **/
private int length;
/** Distance covered. **/
private double distance;
/**
* Create an empty segment.
*/
public Segment() {
}
/**
* Set the turn instruction.
* #param turn Turn instruction string.
*/
public void setInstruction(final String turn) {
this.instruction = turn;
}
/**
* Get the turn instruction to reach next segment.
* #return a String of the turn instruction.
*/
public String getInstruction() {
return instruction;
}
/**
* Add a point to this segment.
* #param point GeoPoint to add.
*/
public void setPoint(final GeoPoint point) {
start = point;
}
/** Get the starting point of this
* segment.
* #return a GeoPoint
*/
public GeoPoint startPoint() {
return start;
}
/** Creates a segment which is a copy of this one.
* #return a Segment that is a copy of this one.
*/
public Segment copy() {
final Segment copy = new Segment();
copy.start = start;
copy.instruction = instruction;
copy.length = length;
copy.distance = distance;
return copy;
}
/**
* #param length the length to set
*/
public void setLength(final int length) {
this.length = length;
}
/**
* #return the length
*/
public int getLength() {
return length;
}
/**
* #param distance the distance to set
*/
public void setDistance(double distance) {
this.distance = distance;
}
/**
* #return the distance
*/
public double getDistance() {
return distance;
}
}
Route.java:
public class Route {
private String name;
private final List<GeoPoint> points;
private List<Segment> segments;
private String copyright;
private String warning;
private String country;
private int length;
private String polyline;
public Route() {
points = new ArrayList<GeoPoint>();
segments = new ArrayList<Segment>();
}
public void addPoint(final GeoPoint p) {
points.add(p);
}
public void addPoints(final List<GeoPoint> points) {
this.points.addAll(points);
}
public List<GeoPoint> getPoints() {
return points;
}
public void addSegment(final Segment s) {
segments.add(s);
}
public List<Segment> getSegments() {
return segments;
}
/**
* #param name the name to set
*/
public void setName(final String name) {
this.name = name;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param copyright the copyright to set
*/
public void setCopyright(String copyright) {
this.copyright = copyright;
}
/**
* #return the copyright
*/
public String getCopyright() {
return copyright;
}
/**
* #param warning the warning to set
*/
public void setWarning(String warning) {
this.warning = warning;
}
/**
* #return the warning
*/
public String getWarning() {
return warning;
}
/**
* #param country the country to set
*/
public void setCountry(String country) {
this.country = country;
}
/**
* #return the country
*/
public String getCountry() {
return country;
}
/**
* #param length the length to set
*/
public void setLength(int length) {
this.length = length;
}
/**
* #return the length
*/
public int getLength() {
return length;
}
/**
* #param polyline the polyline to set
*/
public void setPolyline(String polyline) {
this.polyline = polyline;
}
/**
* #return the polyline
*/
public String getPolyline() {
return polyline;
}
}
GoogleParser.java:
public class GoogleParser extends XMLParser implements Parser {
/** Distance covered. **/
private int distance;
public GoogleParser(String feedUrl) {
super(feedUrl);
}
/**
* Parses a url pointing to a Google JSON object to a Route object.
* #return a Route object based on the JSON object.
*/
public Route parse() {
// turn the stream into a string
final String result = convertStreamToString(this.getInputStream());
//Create an empty route
final Route route = new Route();
//Create an empty segment
final Segment segment = new Segment();
try {
//Tranform the string into a json object
final JSONObject json = new JSONObject(result);
//Get the route object
final JSONObject jsonRoute = json.getJSONArray("routes").getJSONObject(0);
//Get the leg, only one leg as we don't support waypoints
final JSONObject leg = jsonRoute.getJSONArray("legs").getJSONObject(0);
//Get the steps for this leg
final JSONArray steps = leg.getJSONArray("steps");
//Number of steps for use in for loop
final int numSteps = steps.length();
//Set the name of this route using the start & end addresses
route.setName(leg.getString("start_address") + " to " + leg.getString("end_address"));
//Get google's copyright notice (tos requirement)
route.setCopyright(jsonRoute.getString("copyrights"));
//Get the total length of the route.
route.setLength(leg.getJSONObject("distance").getInt("value"));
//Get any warnings provided (tos requirement)
if (!jsonRoute.getJSONArray("warnings").isNull(0)) {
route.setWarning(jsonRoute.getJSONArray("warnings").getString(0));
}
/* Loop through the steps, creating a segment for each one and
* decoding any polylines found as we go to add to the route object's
* map array. Using an explicit for loop because it is faster!
*/
for (int i = 0; i < numSteps; i++) {
//Get the individual step
final JSONObject step = steps.getJSONObject(i);
//Get the start position for this step and set it on the segment
final JSONObject start = step.getJSONObject("start_location");
final GeoPoint position = new GeoPoint((int) (start.getDouble("lat")*1E6),
(int) (start.getDouble("lng")*1E6));
segment.setPoint(position);
//Set the length of this segment in metres
final int length = step.getJSONObject("distance").getInt("value");
distance += length;
segment.setLength(length);
segment.setDistance(distance/1000);
//Strip html from google directions and set as turn instruction
segment.setInstruction(step.getString("html_instructions").replaceAll("<(.*?)*>", ""));
//Retrieve & decode this segment's polyline and add it to the route.
route.addPoints(decodePolyLine(step.getJSONObject("polyline").getString("points")));
//Push a copy of the segment to the route
route.addSegment(segment.copy());
}
} catch (JSONException e) {
Log.e(e.getMessage(), "Google JSON Parser - " + feedUrl);
}
return route;
}
/**
* Convert an inputstream to a string.
* #param input inputstream to convert.
* #return a String of the inputstream.
*/
private static String convertStreamToString(final InputStream input) {
final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
final StringBuilder sBuf = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sBuf.append(line);
}
} catch (IOException e) {
Log.e(e.getMessage(), "Google parser, stream2string");
} finally {
try {
input.close();
} catch (IOException e) {
Log.e(e.getMessage(), "Google parser, stream2string");
}
}
return sBuf.toString();
}
/**
* Decode a polyline string into a list of GeoPoints.
* #param poly polyline encoded string to decode.
* #return the list of GeoPoints represented by this polystring.
*/
private List<GeoPoint> decodePolyLine(final String poly) {
int len = poly.length();
int index = 0;
List<GeoPoint> decoded = new ArrayList<GeoPoint>();
int lat = 0;
int lng = 0;
while (index < len) {
int b;
int shift = 0;
int result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
decoded.add(new GeoPoint(
(int) (lat*1E6 / 1E5), (int) (lng*1E6 / 1E5)));
}
return decoded;
}
}
RouteOverlay.java:
public class RouteOverlay extends Overlay {
/** GeoPoints representing this routePoints. **/
private final List<GeoPoint> routePoints;
/** Colour to paint routePoints. **/
private int colour;
/** Alpha setting for route overlay. **/
private static final int ALPHA = 120;
/** Stroke width. **/
private static final float STROKE = 4.5f;
/** Route path. **/
private final Path path;
/** Point to draw with. **/
private final Point p;
/** Paint for path. **/
private final Paint paint;
/**
* Public constructor.
*
* #param route Route object representing the route.
* #param defaultColour default colour to draw route in.
*/
public RouteOverlay(final Route route, final int defaultColour) {
super();
routePoints = route.getPoints();
colour = defaultColour;
path = new Path();
p = new Point();
paint = new Paint();
}
#Override
public final void draw(final Canvas c, final MapView mv,
final boolean shadow) {
super.draw(c, mv, shadow);
paint.setColor(colour);
paint.setAlpha(ALPHA);
paint.setAntiAlias(true);
paint.setStrokeWidth(STROKE);
paint.setStyle(Paint.Style.STROKE);
redrawPath(mv);
c.drawPath(path, paint);
}
/**
* Set the colour to draw this route's overlay with.
*
* #param c Int representing colour.
*/
public final void setColour(final int c) {
colour = c;
}
/**
* Clear the route overlay.
*/
public final void clear() {
routePoints.clear();
}
/**
* Recalculate the path accounting for changes to
* the projection and routePoints.
* #param mv MapView the path is drawn to.
*/
private void redrawPath(final MapView mv) {
final Projection prj = mv.getProjection();
path.rewind();
final Iterator<GeoPoint> it = routePoints.iterator();
prj.toPixels(it.next(), p);
path.moveTo(p.x, p.y);
while (it.hasNext()) {
prj.toPixels(it.next(), p);
path.lineTo(p.x, p.y);
}
path.setLastPoint(p.x, p.y);
}
}
And then you do this inside the Activity that includes the Map:
1-Add this function:
private Route directions(final GeoPoint start, final GeoPoint dest) {
Parser parser;
//https://developers.google.com/maps/documentation/directions/#JSON <- get api
String jsonURL = "http://maps.googleapis.com/maps/api/directions/json?";
final StringBuffer sBuf = new StringBuffer(jsonURL);
sBuf.append("origin=");
sBuf.append(start.getLatitudeE6()/1E6);
sBuf.append(',');
sBuf.append(start.getLongitudeE6()/1E6);
sBuf.append("&destination=");
sBuf.append(dest.getLatitudeE6()/1E6);
sBuf.append(',');
sBuf.append(dest.getLongitudeE6()/1E6);
sBuf.append("&sensor=true&mode=driving");
parser = new GoogleParser(sBuf.toString());
Route r = parser.parse();
return r;
}
2- Add this in onCreate() function:
MapView mapView = (MapView) findViewById(R.id.mapview); //or you can declare it directly with the API key
Route route = directions(new GeoPoint((int)(26.2*1E6),(int)(50.6*1E6)), new GeoPoint((int)(26.3*1E6),(int)(50.7*1E6)));
RouteOverlay routeOverlay = new RouteOverlay(route, Color.BLUE);
mapView.getOverlays().add(routeOverlay);
mapView.invalidate();
EDIT: If you get an exception, please use directions() function in an AsyncTask to avoid network processing on the UI thread.