i'm trying to use Java Serial Communication to read measured values from a serial device. The task is to send the ASCII Code for 9 (57 in decimal) to the device and it will return the current value that is measured. In first place, I want to make sure that some value is correctly send back. So far, the connection works and when i changed the getListeningEvents() method to check for SerialPort.LISTENING_EVENT_DATA_WRITTEN it worked and showed me my phrase "Reading possible", but in this case this only shows that data got transferred.
So the number is send correctly, but I can't get an answer and the program gets stuck after printing "Written".
In many examples i saw the method notifyOnDataAvailable() for the SerialPort class, but i can't find it in the documentation anymore and i'm not sure if i have to use any other methods to initialize the listener. So my question is, what is wrong about my program, especially my EventListener, that it can't receive or identify the returned value?
Here is my code:
public class ConnectionNew implements SerialPortDataListener {
private SerialPort serialPort = null;
private java.io.OutputStream output = null;
private InputStream input = null;
private SerialPort [] ports = null;
public static void main(String[] args) {
ConnectionNew connect = new ConnectionNew();
connect.connectPort();
connect.initIOStream();
connect.initListener();
connect.writeData();
}
public void connectPort() {
ports = SerialPort.getCommPorts();
System.out.println("Select a port: ");
int i = 1;
for (SerialPort port : ports) {
System.out.println(i++ + ": " + port.getSystemPortName());
}
Scanner s = new Scanner(System.in);
int chosenPort = s.nextInt();
serialPort = ports[chosenPort - 1];
if (serialPort.openPort()) {
System.out.println("Port opened successfully");
} else {
System.out.println("Unable to open the port");
return;
}
}
public boolean initIOStream(){
input = serialPort.getInputStream();
output = serialPort.getOutputStream();
System.out.println("Streams Connected");
return true;
}
public void initListener() {
serialPort.addDataListener(this);
}
public void writeData(){
try {
output.write(57);
output.flush();
System.out.println("Written");
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_RECEIVED;
}
#Override
public void serialEvent(SerialPortEvent arg0) {
System.out.println("Reading possible");
}
}
I'm very happy about any hints, thanks in advance!!
You need to get the data from the event:
public void serialEvent(SerialPortEvent e) {
byte[] data = e.getReceivedData​();
// ...
}
Related
I am trying to make a plugin that has a 'global' configuration file. Right now, I'm trying to use Plugin Messaging to send the entire configuration file through a string, to another server. I have followed the guide at https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/ and have put my own little twist on what is sent. I'm trying to send the plugin message within a spigot plugin so maybe that is the problem. Here is the code is a summary of the code I use to send it (I took out readFile(), clearFile() and writeFile(), let me know if you want those):
public class Main extends JavaPlugin implements PluginMessageListener {
public void onEnable() {
this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
this.getServer().getMessenger().registerIncomingPluginChannel(this, "BungeeCord", this);
}
public void onDisable() {}
public void updateConfig() {
String updateConfig = "";
for (String s : readFile(this.getDataFolder() + "/config.yml")) {
if (updateConfig.equals("")) {
updateConfig = s;
} else {
updateConfig = updateConfig + " |n| " + s;
}
}
Bukkit.getLogger().info("Sending config update...");
sendUpdateconfig(updateConfig);
}
public void sendUpdateconfig(String update) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
try {
out.writeUTF("Forward");
out.writeUTF("ALL");
out.writeUTF("FooServer");
ByteArrayOutputStream msgbytes = new ByteArrayOutputStream();
DataOutputStream msgout = new DataOutputStream(msgbytes);
msgout.writeUTF(update);
msgout.writeShort(295);
out.writeShort(msgbytes.toByteArray().length);
out.write(msgbytes.toByteArray());
Player player = Iterables.getLast(Bukkit.getOnlinePlayers());
player.getServer().sendPluginMessage(this, "BungeeCord", out.toByteArray());
Bukkit.getLogger().info("Sent " + update);
Bukkit.getLogger().info("Short sent: 295");
Bukkit.getLogger().info("Sent through player " + player.getName());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
Bukkit.getLogger().info("Recieved message...");
if (!channel.equals("BungeeCord")) {
return;
}
try {
Bukkit.getLogger().info("Recieved message...");
ByteArrayDataInput in = ByteStreams.newDataInput(message);
String subChannel = in.readUTF();
if (!subChannel.equals("FooServer")) {
Bukkit.getLogger().info("Loading message....");
short len = in.readShort();
byte[] msgbytes = new byte[len];
in.readFully(msgbytes);
DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes));
String somedata = msgin.readUTF();
short somenumber = msgin.readShort();
if (somenumber == 295) {
Bukkit.getLogger().info("Updating config...");
String[] toWrite = somedata.split(" |n| ");
String path = (this.getDataFolder() + "/config.yml");
clearFile(path);
for (String s : toWrite) {
writeFile(path, s);
}
Bukkit.getLogger().info("Config updated!");
}
} else {
Bukkit.getLogger().info("Message sent by this plugin.");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
The way I send the message is just by calling, updateConfig(); When that is called, onPluginMessageReceived is never run.
Is there something I'm doing wrong? Can plugin messages only be sent by a bungeecord plugin? Thanks in advance. If you have any questions about the code, let me know.
Don't work beacause it's write ( String server to send to, or ALL to send to every server (except the one sending the plugin message)) ! For use it you can use our own channel or redis
I'm trying to intercept packets and be able to block them from incoming/outgoing, for a specific domain
In order to do that i made my (java) program adds the domain to the hosts file with a redirection to my own public ipv4 adress (this doesnt matter it just can't be the real IP and i must be able to intercept it, redirecting to my own IP makes sure nobody else in the world receives it). Secondly, i make the program listen to that signal and resend it on a different source port to the real server. (Checksum changes have been taken care of) Now the plan is to receive the response and do the exact same thing, but now by editting the source ip (my own public IP in this case) and the destination port
This should create a program where i'm a kind of middle men between a connection
But it doesnt work as expected, the moment im getting a response of the server (flags SYN/ACK), it's automatically sending them back a RST flag (IPv4/TCP) from the random chosen port by me which isnt the same as the port of the real client
I don't know if there are better ways to do this (there probably are) and how to prevent the problem I'm having, I couldn't really find similiar things to this on the internet. Any kind of help/hints would be appreciated
Keep in mind that I'm using jnetpscape at this moment and it would be nice to continue at what i'm doing right now
EDIT (code):
this is the "HConnection" class (not fully showed but all essential things):
public class HConnection {
private volatile int state = -1; // current state of the program
private volatile boolean HostFileEdited = false;
private volatile String domain = null;
private volatile boolean waitingConnection = false;
private volatile String ipOfDomain = null; // string of the server adress
private volatile byte[] ipofdomb; //4 bytes of the server adress
private volatile String myIpAdr = null; //my IP adress
private volatile byte[] myIpb; //my public IP in 4 bytes
private volatile byte[] port = null; //port of proxy
private volatile byte[] falseport = null; //port of client
private volatile ServerSocket server;
public HConnection() {
try {
server = new ServerSocket(0);
byte[] tempPortb = ByteBuffer.allocate(4).putInt(server.getLocalPort()).array();
System.out.println(server.getLocalPort());
port = new byte[]{tempPortb[2], tempPortb[3]};
(new Thread() {
public void run() {
try {
server.accept();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}).start();
state = 0;
} catch (UnknownHostException e) {System.out.println("fail");} catch (IOException e) {System.out.println("fail");}
}
public String getPublicIP () {
try{
myIpAdr = new BufferedReader(new InputStreamReader(new URL("http://checkip.amazonaws.com/").openStream())).readLine();
System.out.println(myIpAdr);
InetAddress ip = InetAddress.getByName(myIpAdr);
myIpb = ip.getAddress();
return myIpAdr;
}
catch (Exception e){}
return null;
}
public void setUrl(String domain) {
this.domain = domain;
}
public int getState() {
return state;
}
public void prepare() {
try{
URL urlofsite = new URL("https://"+domain);
InetAddress address = InetAddress.getByName(urlofsite.getHost());
ipOfDomain = address.getHostAddress();
System.out.println(ipOfDomain);
ipofdomb = address.getAddress();
addToHostsFile(getPublicIP() + "\t" + domain);
state = 1;
}
catch(Exception e){}
}
public void abort() {
removeFromHostsFile(domain);
HostFileEdited = false;
state = -1;
try {
server.close();
} catch (IOException e) { }
waitingConnection = false;
}
public void awaitConnection() {
if (state == 1) {
waitingConnection = true;
System.out.println("stap1");
StringBuilder errbuf = new StringBuilder(); // For any error msgs
int snaplen = 64 * 1024; // Capture all packets, no truncation
int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
int timeout = 0; // 10 seconds in millis
Pcap pcap = Pcap.openLive("wlp4s0", snaplen, flags, timeout, errbuf);
if (pcap == null) {
System.err.printf("Error while opening device for capture: "
+ errbuf.toString());
return;
}
PcapHeader hdr = new PcapHeader(JMemory.POINTER);
JBuffer buf = new JBuffer(JMemory.POINTER);
int id = JRegistry.mapDLTToId(pcap.datalink());
while (HostFileEdited && waitingConnection && state == 1 && pcap.nextEx(hdr, buf) == Pcap.NEXT_EX_OK) {
PcapPacket packet = new PcapPacket(hdr, buf);
try {
packet.scan(id);
TcpPacket pkt = new TcpPacket(packet);
if (pkt.isTcp()) {
if (pkt.destinationIPequals(myIpAdr) && pkt.getDestinationPort() == 443 && (falseport == null || Arrays.equals(pkt.getSourcePortb(), falseport))) {
if (falseport == null) {
falseport = pkt.getSourcePortb();
}
pkt.changeDestinationIP(ipofdomb);
pkt.changeSourcePort(port);
pkt.iPchecksumFix();
pkt.tcPchecksumFix();
ByteBuffer b = ByteBuffer.wrap(pkt.getPacketInBytes());
System.out.println("10");
System.out.println("OUT"+ (pcap.sendPacket(b)));
}
else if (pkt.sourceIPequals(ipOfDomain) && pkt.getSourcePort() == 443 && falseport != null && Arrays.equals(pkt.getDestinationPortb(),port) ) {
pkt.changeSourceIP(myIpb);
pkt.changeDestinationPort(falseport);
pkt.iPchecksumFix();
pkt.tcPchecksumFix();
ByteBuffer b = ByteBuffer.wrap(pkt.getPacketInBytes());
System.out.println("IN"+ pcap.sendPacket(b));
}
}
}
catch (Exception e) {}
}
System.out.println("stap2");
if (state == 1 && waitingConnection == true) state = 2;
waitingConnection = false;
}
}
}
The "awaitConnection()" method is were currently most things are happening. But this will only be the beginning of my program
HConnection is called from the main class (SWT Designer):
private Button btnNewButton_1;
private HConnection connectie;
private void btnConnect_clicked(SelectionEvent e) throws InterruptedException {
if (btnNewButton_1.getText().equals("Connect")) {
String Url = combo.getText();
connectie = new HConnection();
connectie.setUrl(Url);
connectie.prepare();
lblNewLabel_2.setText("Waiting -> client");
new Thread(new Runnable() {
public void run() {
connectie.awaitConnection();
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (connectie.getState() == 2) {
lblNewLabel_2.setText("Replacing URL");
}
else {
lblNewLabel_2.setText("Failed");
connectie.abort();
btnNewButton_1.setText("Connect");
}
}
});
if (connectie.getState() == 2) {
// go on with the rest of the program
}
}
}).start();
btnNewButton_1.setText("Abort");
}
else if(btnNewButton_1.getText().equals("Abort")) {
connectie.abort();
lblNewLabel_2.setText("Aborted");
btnNewButton_1.setText("Connect");
}
}
The following code accepts a connection, but doesn't maintain a reference to the resulting Socket instance. This Socket is eligible for garbage collection, and when that happens, it is automatically closed. A client sending data to that socket will then receive an RST.
public void run() {
try {
server.accept();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
So after a long period of research, I was able to make my RFID scanner work and detect the ports of my computer. I had to split the code into 2 class files because of two jar files having different features:
one is for reading the ID and the other is for reading the port.
Now that I had them, all I had to do is to call them into my main GUI project.
The issue I am facing right now is that the child wont wait for the ID to be scanned and instead give me a null value in return. I want to make this work so I can just call my child classes into my Main Project.
here are my codes:
RFID_Reader.java
import javax.swing.JOptionPane;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
public class RFID_Reader {
static SerialPort serialPort;
static String output;
public String FinalOutput;
//this probably is redundant and I am willing to remove it.
public void checkConnection(){
RFID_Scan_HW jCom = new RFID_Scan_HW();
serialPort = new SerialPort(jCom.collect_Ports(""));
startReading();
}
//Configuring the serialPort
public void startReading(){
try {
serialPort.openPort();
serialPort.setParams(SerialPort.BAUDRATE_9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
//verbose, just to get the output with no words.
serialPort.writeBytes("\002v0\003".getBytes());
serialPort.closePort();
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
int mask = SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR;
serialPort.setEventsMask(mask);
serialPort.addEventListener(new SerialPortReader());
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
//re-scan devices in port. if the device is not found, just try again.
public void rescanConnection(){
RFID_Scan_HW jCom = new RFID_Scan_HW();
if(jCom.collect_Ports("")==""){
JOptionPane.showMessageDialog(null, "No Scanner found. Please try again");
}else{
serialPort = new SerialPort(jCom.collect_Ports(""));
startReading();
}
}
//read the input from the device.
class SerialPortReader implements SerialPortEventListener{
#Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()){
if(event.getEventValue() == 22){
try{
byte[] bytes = serialPort.readBytes(22);
String card = new String(bytes);
String results[] = card.split(",");
String processed ="";
char[] cutdown = results[3].toCharArray();
for(int i=0; i<cutdown.length-1; i++){
processed +=cutdown[i];
}
String result = results[2]+"-"+processed;
FinalOutput = result;
}catch (SerialPortException ex) {
System.out.println(ex);
}
}else{
}
}
}
}
}
RFID_Scan_HW.java
import com.fazecast.jSerialComm.SerialPort;
public class RFID_Scan_HW {
String masterPort = "";
public String collect_Ports(String x){
SerialPort ports[] = SerialPort.getCommPorts();
String[] portList = new String[ports.length];
for(int i=0; i<ports.length; i++){
String check = ports[i].getDescriptivePortName();
if(check.startsWith("Prolific USB-to-Serial Comm Port")==true){
masterPort = ports[i].getSystemPortName();
}
}
return masterPort;
}
public void displayPorts(){
SerialPort ports[] = SerialPort.getCommPorts();
for(SerialPort port : ports){
System.out.println(port.getDescriptivePortName());
}
}
}
And here now is how I called them using a Button:
private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {
RFID_Reader rf = new RFID_Reader();
String ID="null";
rf.checkConnection();
ID = rf.FinalOutput;
JOptionPane.showMessageDialog(null, "The ID is: "+ID);
}
and the result: The ID is: null
now here is what I wanted to happen.
When I press the button, the button will wait for the scanner before prompting the ID from the card.
I'm pretty sure I'm doing this wrong so please help me out.
Use threads and synchronize them using synchronized keywords. 1st thread will wait for connection to be established, ID to be scanned and available. Then it notifies 2nd thread which will read/write data to RFID device.
Also consider using serial communication manager library as it has many powerful APIs that may be used as is in your project. Also share details about your RFID hardware.
I'm simply trying to send a message to another object but its not exactly changing unless I'm missing a important factor. I have one class to set the number and another class which gets, the class that gets is dependent on the correct number being set however although the set method returns 0 one the command line, the other object returns 1 when using the get method. This is the close class whihc holds both of the methods, each method is called from class A and Class B
public class Close {
static int close =1;
public synchronized void setClose(int x, Client)
{
/*
while(turn !=0){
try{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}*/
close = x;
System.out.println("set "+close);
}
public synchronized int getClose(ClientHandeler)
{
int x;
/*
while(turn==0){
try{
wait();
}catch(Exception e)
}
}*/
System.out.println("get "+close);
x = close;
return x;
}
}
This is the handler class in which i wish to get the close integer from
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientHandler implements Runnable {
private BufferedReader reader;
private Socket sock;//refering to socket class
//listens for the socket
private Server server; // call-back reference to transmit message to all clients
Client c = new Client();
public ClientHandler(Socket clientSocket, Server serv) {
try {
sock = clientSocket;
server = serv;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
String message;
try {
int x = c.c.getClose(this);
while(x!=0){
x = c.c.getClose(this);//calls client and within client there is the close
System.out.println(x);
Thread ct= Thread.currentThread();
ct.sleep(3000);
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
server.tellEveryone(message);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Probably they both do not use the same Close object.
Close close = new Close();
Then make sure that both use the same close object!
If that is not possible, field close can be made static:
public class Close {
static int close;
You could just use an AtomicInteger.
public class Close {
AtomicInteger close = new AtomicInteger(1);
public void setClose(int x)
{
/*
while(turn !=0){
try{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}*/
close.set(x);
System.out.println("set "+close.get());
}
public int getClose()
{
int x;
/*
while(turn==0){
try{
wait();
}catch(Exception e)
}*/
System.out.println("get "+close.get());
x = close.get();
return x;
}
Try...
static int close = 1;
This way there will only be one copy of the int close, for all instances of the Close class. Adding the code where you use this class would help, I'm guessing that you are instantiating new copies for each operation, which is causing your issues.
I don't really understand your problem. May you give a little snippet on how you are using this class?
However, it look very likely that you are not accessing the same instance form your so-called class A and B.
It is just like A is writing something on one paper, and B is reading ANOTHER piece of paper. Of course things written by A is not readable by B.
This pertains to my earlier post "http://stackoverflow.com/questions/8788825/linux-udp-server-unreachable-from-window-7", which has been solved. Now I am moving to my original job of connecting AVD to Linux server.
I am using the following code for connecting to the server
import java.net.*;
class UDPClient {
public final static int DesitnationPort = 9999;
private int mCounter;
private DatagramSocket mClientSocket;
private InetAddress mServerIPAddress;
private byte[] mDataBuffer;
private DatagramPacket mSendPacket;
private DatagramPacket mReceivePacket;
//Constructor
public UDPClient() {
//Time to make the private data good one
mCounter =1;
try {
mServerIPAddress = InetAddress.getByName("192.168.2.2");
}
catch(UnknownHostException e)
{
System.out.println("Host cannot be resolved :( ");
}
System.out.println("Host has been resolved The IP is valid one ");
try {
mClientSocket = new DatagramSocket();
}
catch(SocketException e)
{
System.out.println("Socket could not be created :( ==> " + e.getMessage());
}
System.out.println("Socket has been created ");
String temp = "This is from the Client == To my Dear Sever :) counter = " + mCounter;
mDataBuffer = temp.getBytes();
mSendPacket = new DatagramPacket(mDataBuffer, mDataBuffer.length, mServerIPAddress, DesitnationPort);
System.out.println("Datagram has been made now ");
System.out.println("Data ==>"+ mSendPacket.getData());
System.out.println("Data ==>"+ mSendPacket.getPort());
System.out.println("Data ==>"+ mSendPacket.getSocketAddress());
System.out.println("Data ==>"+ mSendPacket.getLength());
}
public void SendDataToServer(){
try {
if(!mClientSocket.isClosed()) {
String temp = "This is from the Client == To my Dear Sever :) counter = " + mCounter;
mDataBuffer = temp.getBytes();
mSendPacket = new DatagramPacket(mDataBuffer, mDataBuffer.length, mServerIPAddress, DesitnationPort);
mClientSocket.send(mSendPacket);
System.out.println("Send the packet");
mCounter++;
}
else {
System.out.println("Socket is closed");
}
}
catch(Exception e)
{
System.out.println("Could not send the data :( ==> " + e.getMessage());
}
}
public void ReceiveDataFromServer() {
byte[] tembuff = new byte[1024];
mReceivePacket = new DatagramPacket(tembuff, tembuff.length);
try {
if(!mClientSocket.isClosed()) {
mClientSocket.receive(mReceivePacket);
}
else {
System.out.println("Socket is closed");
}
}
catch(Exception e)
{
System.out.println("Could not Receive the data :( ");
return;
}
String data = new String(mReceivePacket.getData());
System.out.println(" Received the Data => " + data);
}
}
This code works well when I simply use the class in java program like this :-
class TryingWithClient {
public static void main(String a[]) {
UDPClient mClient = new UDPClient();
while(true) {
System.out.println("While Starting");
mClient.SendDataToServer();
mClient.ReceiveDataFromServer();
}
}
}
When I use the same code in AVD project I get a Null pointer exception at the following line :-
public void SendDataToServer(){
try {
if(!mClientSocket.isClosed()){ //<==# this call Null exception occurs
After browsing internet & android development sites I came to conclusion that I am missing the GMS / GPS functionality which I added to my AVD. Still I am unable to get any clue about this.
Here is my code which calls the above UDPClient.
public class StreamingProjectActivity extends Activity {
/** Called when the activity is first created. */
//All buttons
//private static final String LOG_TAG = "StreamingTest";
private StreamButton mStreamButton = null;
private UDPClient mClient= null;
class StreamButton extends Button {
boolean mStartStreaming = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onStream(mStartStreaming);
if (mStartStreaming) {
setText("Stop Streaming");
} else {
setText("Start recording");
}
mStartStreaming = !mStartStreaming;
}
};
public StreamButton(Context ctx) {
super(ctx);
setText("Start Streaming");
setOnClickListener(clicker);
}
}//class StreamButton Ends
#Override
public void onCreate(Bundle icicle) {
try {
mClient = new UDPClient();
System.out.println("==========> Client created sucessfully :) <====== ");
super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this);
mStreamButton = new StreamButton(this);
ll.addView(mStreamButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
System.out.println("Trying Step 2 now ");
}
catch(Exception e)
{
System.out.println("Activity could not be launched :( ");
}
}
//public StreamingTest()
public StreamingProjectActivity(){
System.out.println("Constructor ====>");
System.out.println("Constructor <====");
}//Constructor
private void onStream(boolean start) {
if (start)
{
mClient.SendDataToServer();
mClient.ReceiveDataFromServer();
try
{
Thread.sleep(4000);
}catch (InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
}//onStream
}
Kindly help.
Ok, first of all: never ever print a catched exception with System.out.println("some msg " + e.getMessage()); Please use Log.e(TAG, "my message", e); for that. So you will actually see a stack trace.
Second: I bet that this code throws an error (check if you see the print in your LogCat output):
try {
mClientSocket = new DatagramSocket();
} catch(SocketException e) {
System.out.println("Socket could not be created :( ==> " + e.getMessage());
}
That is the only reason that mClientSocket still might be null. As this call might go wrong, you should consider checking for null before you check if the socket is closed.
The problem in my earlier solution was that I was mixing the GUI & network operations in the same thread which is called "StricMode.ThreadPolicy" (although, my problem is only part of what is mentioned in the jargon).
I was getting these exceptions "android.os.NetworkOnMainThreadException & android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099) " which I could make out only after I applied WarrenFaith's suggestion (Thanks Warren).
These are thrown only on violation of "StricMode".
Solution : Simply separate the UI work from the network. I had to write the following code for this :
enum ClientThreadStates {
eUndefined,
eStopped,
eRunning,
eIdle,
eSendToServer,
eReadFromServer
}
public class ClientThread extends Thread {
private UDPClient mClient= null;
private ClientThreadStates mStateOfTheThread = ClientThreadStates.eUndefined;
private static String mLOG_TAG;
public ClientThread(String s){
mLOG_TAG = s;
mStateOfTheThread = ClientThreadStates.eStopped;
mClient = new UDPClient(s);
start();
}//constructor
public void SetState(ClientThreadStates paramState) {
mStateOfTheThread = paramState;
}
public ClientThreadStates GetState() {
return mStateOfTheThread;
}
private void Action(ClientThreadStates s) {
synchronized(s) {
switch(mStateOfTheThread) {
case eRunning: //fall
case eIdle: break;
case eSendToServer: mClient.SendDataToServer(); break;
case eReadFromServer: mClient.ReceiveDataFromServer(); break;
}
try {
mStateOfTheThread.wait();
}
catch( InterruptedException e ){
Log.e(mLOG_TAG, "Got Exception at wait <==", e);
}
}
}
public void run() {
mStateOfTheThread = ClientThreadStates.eRunning;
System.out.println("In Thread.run .. The State is " + mStateOfTheThread);
while(ClientThreadStates.eStopped.compareTo(mStateOfTheThread) < 0){ //state >stopped
Action(mStateOfTheThread);
}//while
}//run
}//class ClientThread
Finally synchronize on the two threads on the state like this :
private void onStream(boolean start) {
ClientThreadStates State = mClientThread.GetState();
synchronized(State) {
if (start) {
mClientThread.SetState(ClientThreadStates.eSendToServer);
}
else {
mClientThread.SetState(ClientThreadStates.eReadFromServer);
}
try {
State.notify();
}
catch( IllegalMonitorStateException e ) {
Log.e(LOG_TAG, "Got Exception # notify <==", e);
}
}
}//onStream
}//StreamingProjectActivity
Now the code runs perfectly.
Thanks.
Ashutosh