As part of my lab this week I am suppose to convert a socket based chat application to RMI. So far I managed to connect server and client together and transfer data between them but the transfer is not continuous. What I mean is that when the client first connects t the server it broadcasts a message "X has entered the conversation" but that is all. Anything I type after that wont get broadcasted. I am about to pull out my hair. Please help.
public class ChatServer extends UnicastRemoteObject implements ChatMessage {
private static final long serialVersionUID = 1L;
private String sender;
private String message;
private ChatMessageType t;
public ChatServer() throws RemoteException {
super();
}
#Override
public void Message(String sender, ChatMessageType t, String message)
throws RemoteException {
this.sender = sender;
this.message = message;
this.t = t;
}
#Override
public String getSender() throws RemoteException {
return sender;
}
#Override
public String getMessage() throws RemoteException {
return message;
}
#Override
public ChatMessageType getType() throws RemoteException {
return t;
}
public String ToString() throws RemoteException{
String strMessage;
switch (t) {
case SETUP:
strMessage = sender + " has entered the conversation.";
break;
case TEARDOWN:
strMessage = sender + " has left the conversation.";
break;
case MESSAGE:
strMessage = sender + ": " + message;
break;
default:
strMessage = "";
}
return strMessage;
}
// driver.
public static void main(String arg[]) {
try {
ChatServer c = new ChatServer();
Registry registry = LocateRegistry.createRegistry(1099);
registry.rebind("Server", c);
System.out.println("Server bound in registry");
} catch (Exception e) {
System.out.println("Server error: " + e.getMessage());
e.printStackTrace();
}
}
}
public class ChatClient implements ActionListener {
// static private Socket c;
static ChatMessage obj = null;
// static private ObjectInputStream in;
// static private ObjectOutputStream out;
static private String name;
static private String host;
static private Integer port;
/**
* Launches this application
*/
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (args.length != 3) {
System.out
.println("Client requires exactly three args to run.");
System.exit(-1);
}
name = args[0];
host = args[1];
port = new Integer(args[2]);
final ChatClient application = new ChatClient();
application.getJFrame().setVisible(true);
try {
System.out.println("client: connecting to server...");
// c = new Socket(host, port);
obj = (ChatMessage) Naming.lookup("//" + host + ":" + port
+ "/Server");
System.out.println("client: connected!");
} catch (Exception e) {
System.out.println("client: " + e.getMessage());
System.exit(-1);
}
try {
// out = new ObjectOutputStream(c.getOutputStream());
// in = new ObjectInputStream(c.getInputStream());
// announce to other clients that you're here
// out.writeObject(new ChatMessage(name,
// ChatMessageType.SETUP, ""));
obj.Message(name, ChatMessageType.SETUP, "");
} catch (Exception e) {
}
// set up the client's listener as an anonymous thread that's
// always running
// new Thread(new Runnable(){
// public void run()
// {
// while(true)
// {
try {
System.out.println(name + ": waiting for data");
ChatMessage m = (ChatMessage) Naming.lookup("//" + host
+ ":" + port + "/Server");
System.out.println(name + ": data received");
application.updateTextArea(m.ToString());
} catch (Exception e) {
}
// }
// }
// }).start();
}
});
}
public void updateTextArea(final String message) {
conversation.setText(conversation.getText() + message + "\n");
// this will guarantee that the bottom of the conversation is visible.
conversation.setCaretPosition(conversation.getText().length());
}
// send button has been pressed, send the message to the server.
public void actionPerformed(ActionEvent e) {
if (send.getText().equals("Send")) {
try {
System.out.println(name + ": sending data");
// ChatMessage m = new ChatMessage(name,
// ChatMessageType.MESSAGE, message.getText());
// out.writeObject(m);
obj.Message(name, ChatMessageType.MESSAGE, message.getText());
message.setText(""); // clear the text box.
System.out.println(name + ": data sent");
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}
}
enum ChatMessageType{
SETUP,
MESSAGE,
TEARDOWN
}public interface ChatMessage extends Remote{
public String getSender() throws RemoteException;
public String getMessage() throws RemoteException;
public ChatMessageType getType() throws RemoteException;
public void Message(String sender, ChatMessageType t, String message) throws RemoteException;
public String ToString() throws RemoteException;
I realize this question is pretty old and you probably figured out an answer for this, but, I thought I'd share an approach I took for going from Java sockets to RMI. Maybe it is useful for others looking to do the same thing.
I basically abstracted out the socket portion into a "Tunnel" object that represents a communication path between hosts. And the tunnel consists of several "channels", that represent a one-way communication between the source and destination.
You can check out more details at my blog here: http://www.thecodespot.com/?p=1
Related
I'm trying to implement a fake broker (actually it is an mqtt publisher client in an mqtt subscriber's callback). There are 3 separated publisher clients which are publishing random numbers between 0 and 1. This fake broker just summarizes this random numbers, and publishes away to an other topic. (Maybe not in the right way, but for now it is ok) This solution is working but after a few incoming messages this broker stops to work. I Tried to debug it, but I found only ClassNotFound Exceptions... Here is my FakeBroker and it's Callback implementation.
public class FakeBroker implements Runnable{
public static final String BROKER_URL = "";
public static final String TOPIC_FAKE_A = "";
public static final String TOPIC_FAKE_B = "";
public static final String TOPIC_FAKE_C = "";
public static final String USER_NAME = "";
public static final char[] USER_PSW = "".toCharArray();
private MqttClient client;
private MqttConnectOptions options;
private SubscriberCallback callback;
public FakeBroker() {
options = new MqttConnectOptions();
options.setUserName(USER_NAME);
options.setPassword(USER_PSW);
options.setCleanSession(false);
callback = new SubscriberCallback();
try {
client = new MqttClient(BROKER_URL, MqttClient.generateClientId()+"-sub");
client.setCallback(callback);
} catch (MqttException e) {
e.printStackTrace();
System.exit(1);
}
}
public void start() {
try {
client.connect(options);
System.out.println("Fake Broker are connected to the cloud.");
client.subscribe(TOPIC_FAKE_A);
client.subscribe(TOPIC_FAKE_B);
client.subscribe(TOPIC_FAKE_C);
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void run() {
start();
}
}
And here is it's Callback
public class SubscriberCallback implements MqttCallback {
public static final String BROKER_URL = "";
public static final String TOPIC_FAKE_BROKER = "";
public static final String USER_NAME = "";
public static final char[] USER_PSW = "".toCharArray();
private MqttClient client;
private MqttConnectOptions options;
private int counter = 1;
private int result = 0;
public SubscriberCallback() {
try {
client = new MqttClient(BROKER_URL, "4-pub");
options = new MqttConnectOptions();
options.setPassword(USER_PSW);
options.setUserName(USER_NAME);
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void connectionLost(Throwable throwable) {
}
#Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
System.out.println("Message Arrived. Topic " + topic + " message: " +mqttMessage + " ---- Message Counter: " + counter);
int number = Integer.parseInt(mqttMessage.toString());
result += number;
if (counter%3 == 0) {
publishAway(new MqttMessage(Integer.toString(result).getBytes()));
result = 0;
}
incrementCounter();
}
private void publishAway(MqttMessage mqttMessage) throws MqttException {
client.connect(options);
final MqttTopic topicFakeBroker = client.getTopic(TOPIC_FAKE_BROKER);
topicFakeBroker.publish(mqttMessage);
client.disconnect();
System.out.println("Fake broker got the message " + mqttMessage + " and published away to" + topicFakeBroker.getName());
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
private void incrementCounter() {
counter++;
}
}
Of course I use valid BROKER_URL and TOPICS but these informations are confidential. Thanks for Your answers! :)
I have an JavaFx application that has no stage. It only runs at system tray. Basically it listen to a service and show notification according to it.
The connection between app and service is done using Socket.
However, service can send a priority message, which will be shown first than others.
The problem: I have all my messages in a PriorityQueue but I don't know how to handle a notification await for the other finish to show. Is that the best approach? Is the architecture correct? Also, since TrayNotification class will show a Scene, I'm afraid of having problems with UI Thread.
This is Message class:
public class Message implements Comparable<Message> {
private int priority;
private String notificationType;
private String title;
private String message;
public Message() {
}
public Message (int priority, String notificationType, String title, String message) {
this.priority = priority;
this.notificationType = notificationType;
this.title = title;
this.message = message;
}
public void setPriority(int priority) {
this.priority = priority;
}
public int getPriority() {
return this.priority;
}
public void setNotificationType(String notificationType) {
this.notificationType = notificationType;
}
public NotificationType getNotificationType() {
if (this.notificationType.equals(NotificationType.CUSTOM.toString())) {
return NotificationType.CUSTOM;
}
else if (this.notificationType.equals(NotificationType.ERROR.toString())) {
return NotificationType.ERROR;
}
else if (this.notificationType.equals(NotificationType.INFORMATION.toString())) {
return NotificationType.INFORMATION;
}
else if (this.notificationType.equals(NotificationType.NOTICE.toString())) {
return NotificationType.NOTICE;
}
else if (this.notificationType.equals(NotificationType.SUCCESS.toString())) {
return NotificationType.SUCCESS;
}
else if (this.notificationType.equals(NotificationType.WARNING.toString())) {
return NotificationType.WARNING;
}
else {
throw new IllegalArgumentException("Invalid notification type.");
}
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return this.title;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
#Override
public int compareTo(Message otherMessage) {
return Integer.compare(this.priority, otherMessage.getPriority());
}
}
My application class, SystemtrayLauncher, has this code on start method, after configuring tray:
/** Start to listen to service **/
ServiceConnector connector = new ServiceConnector(8888);
new Thread(connector).start();
ServiceConnector (which I think needs to be improved to handle PriorityQueue):
public class ServiceConnector extends Task<Void> {
private ServerSocket socket;
private int port;
public static PriorityQueue<Message> messageQueue = new PriorityQueue<>();
public ServiceConnector(int port) {
this.port = port;
}
public void connect() {
try {
System.out.println("Opening connection...");
socket = new ServerSocket(this.port);
socket.setSoTimeout(0);
System.out.println("Connection opened at port " + this.port);
while (true) {
System.out.println("Awaiting service connection...");
Socket service = socket.accept();
System.out.println(
"Service at " + service.getInetAddress().getHostAddress() + " connected");
Message message = MessageListener.getMessage(service);
if (message != null) {
messageQueue.offer(message);
// get top priority message
Platform.runLater(() -> MessageListener.notifyUser(messageQueue.peek()));
}
else {
CustomAlert dialog = new CustomAlert(Alert.AlertType.ERROR);
dialog.setContentText(SystemConfiguration.LOCALE.getString("MESSAGE_ERROR"));
dialog.showAndWait();
}
service.close();
}
} catch (IOException exc) {
exc.printStackTrace();
}
}
#Override
protected Void call() throws Exception {
this.connect();
return null;
}
}
MessageListener
public class MessageListener {
private static TrayNotification trayNotification;
public static Message getMessage(Socket service) {
System.out.println("Processing message...");
try {
BufferedReader inputReader =
new BufferedReader(new InputStreamReader(service.getInputStream()));
/**
* JSON format:
* {
* "priority": "1 for urgent and greater with less priority",
* "notificationType": "ERROR|INFORMATION|NOTICE|SUCCESS|WARNING",
* "title": "A string to be show as notification windows title",
* "message": "A string to be show as message"
* }
*/
JSONObject jsonMessage = new JSONObject(inputReader.readLine());
Message message = new Message();
message.setPriority(jsonMessage.getInt("priority"));
message.setNotificationType(jsonMessage.getString("notificationType"));
message.setTitle(jsonMessage.getString("title"));
message.setMessage(jsonMessage.getString("message"));
inputReader.close();
service.close();
System.out.println("Message with priority " + message.getPriority() + " processed.");
return message;
} catch (IOException exc) {
exc.printStackTrace();
return null;
}
}
/**
* Notify user with processed service message.
* #param message
*
*/
public static void notifyUser(Message message) {
System.out.println("Priority: " + message.getPriority());
trayNotification = new TrayNotification();
trayNotification.setAnimationType(AnimationType.POPUP);
trayNotification.setRectangleFill(Paint.valueOf("#0277BD"));
trayNotification.setImage(new Image(SystemConfiguration.ICON));
trayNotification.setNotificationType(message.getNotificationType());
trayNotification.setTitle(message.getTitle());
trayNotification.setMessage(message.getMessage());
trayNotification.showAndDismiss(Duration.seconds(3.5));
ServiceConnector.messageQueue.poll();
}
}
I have a server that contains an ArrayList in " ServerInfo " and when I try to take from ClientRMI an element of the ArrayList(in ServerInfo) for example adf.getSGM ( 0 ).incrementCount( ) ;
"count" does not increase it's as if every time I call it instantiates a new class SGM
in a few words I want to interact from ClientRMI with ArrayList that is on ServerInfo (SORRY FOR ENGLISH)
Hear are the classes :
SERVER
public class ServerRMI {
public static void main(String[] args) {
Registry registry = null;
String name = "ServerInfo";
try {
System.out.println("Init RMI");
ServerInfoInterface sir = ServerInfo.getInstance();
ServerInfoInterface stub = (ServerInfoInterface) UnicastRemoteObject.exportObject(sir, 0);
registry = LocateRegistry.createRegistry(9000);
registry.bind(name, stub);
System.out.println("RMI OK");
System.out.println("Init SGM...");
for(int i=0;i<3;i++){
ServerInfo.getInstance().addSGM(new SGM());
}
System.out.println("Init SGM OK");
} catch (Exception e) {
System.out.println("RMI Error"+e.toString());
registry = null;
}
}
}
public class ServerInfo implements ServerInfoInterface{
private ArrayList<SGM> sgmHandler = new ArrayList<SGM>();
// Singleton pattern
private static ServerInfo instance;
// Singleton pattern
public static ServerInfo getInstance() {
if (instance == null){
System.out.println("ServerInfo new instance");
instance = new ServerInfo();
}
return instance;
}
#Override
public synchronized void addSGM(SGM sgm) throws RemoteException {
sgmHandler.add(sgm);
}
#Override
public synchronized SGM getSGM(int i) throws RemoteException {
return sgmHandler.get(i);
}
}
public interface ServerInfoInterface extends Remote{
public void addSGM(SGM sgm) throws RemoteException;
public SGM getSGM(int i) throws RemoteException;
}
public class SGM implements Serializable{
/**
*
*/
private static final long serialVersionUID = -4756606091542270097L;
private int count=0;
public void incrementCount(){
count++;
}
public void decrementCount(){
count--;
}
public int getCount(){
return count;
}
}
CLIENT
public class ClientRMI {
private ServerInfoInterface sgmInterface;
public void startServer() {
String name = "ServerInfo";
Registry registry;
try {
registry = LocateRegistry.getRegistry(9000);
try {
sgmInterface = (ServerInfoInterface) registry.lookup(name);
sgmInterface.getSGM(0).incrementCount();
System.out.println(sgmInterface.getSGM(0).getCount()); // always 0
} catch (AccessException e) {
System.out.println("RIM AccessException"+ e.toString());
} catch (RemoteException e) {
System.out.println("RIM RemoteException"+ e.toString());
} catch (NotBoundException e) {
System.out.println("RIM NotBoundException"+ e.toString());
}
} catch (RemoteException e) {
System.out.println("RIM RemoteException registry"+ e.toString());
}
}
}
You're creating an SGM at the server, passing it via Serialization to the client, incrementing its count at the client, and then expecting that count to be magically increased at the server.
It can't work.
You will have to make SGM a remote object, with its own remote interface, or else provide a remote method in the original remote interface to increment the count of a GSM, specified by index.
I want to send multiple SMS' via using smslib. I make a Java class to send SMS in a loop. But it works only one time. then it returns the following exception:
org.smslib.GatewayException: Comm library exception:
java.lang.RuntimeException: javax.comm.PortInUseException:
Port currently owned by org.smslib
at org.smslib.modem.SerialModemDriver.connectPort(SerialModemDriver.java:102)
at org.smslib.modem.AModemDriver.connect(AModemDriver.java:114)
at org.smslib.modem.ModemGateway.startGateway(ModemGateway.java:189)
at org.smslib.Service$1Starter.run(Service.java:276)
This is my class:
import javax.swing.JOptionPane;
import org.smslib.AGateway;
import org.smslib.IOutboundMessageNotification;
import org.smslib.OutboundMessage;
import org.smslib.Service;
import org.smslib.modem.SerialModemGateway;
public class SendSMS1 {
private static String id;
private static String port;
private static int bitRate;
private static String modemName;
private static String modemPin;
private static String SMSC;
public static void doIt(String number, String text) {
try {
OutboundMessage msg;
OutboundNotification outboundNotification = new OutboundNotification();
SerialModemGateway gateway = new SerialModemGateway(id, port, bitRate, modemName, "E17u-1");
gateway.setInbound(true);
gateway.setOutbound(true);
gateway.setSimPin(modemPin);
Service.getInstance().setOutboundMessageNotification(outboundNotification);
Service.getInstance().addGateway(gateway);
Service.getInstance().startService();
msg = new OutboundMessage(number, text);
Service.getInstance().sendMessage(msg);
System.out.println(msg);
Service.getInstance().stopService();
} catch (Exception ex) {
if (ex.getStackTrace()[2].getLineNumber() == 189) {
JOptionPane.showMessageDialog(null,
"Port currently owned by usb Modem's application. \n Please close it & run the programm again.",
"Port Exception",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
} else {
JOptionPane.showMessageDialog(null,
ex.getMessage(),
"Sending faile",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
}
}
}
public static class OutboundNotification implements IOutboundMessageNotification {
public void process(AGateway gateway, OutboundMessage msg) {
System.out.println("Outbound handler called from Gateway: " + gateway.getGatewayId());
System.out.println(msg);
}
}
public static void main(String[] args) throws Exception {
String number = "+94772347634", text = "Hello world";
modemName = "Huwawi";
port = "COM4";
bitRate = 115200;
modemPin = "0000";
SMSC = "+947500010";
for (int i = 0; i < 5; i++) {
SendSMS1 app = new SendSMS1();
app.doIt(number, text);
}
}
}
Please give me advice, what should I do differently?
I don't know the smslib, but I imagine everything until startService should only happen once, not each time you want to send a message, as follows:
class SendSMS1
{
public SendSMS1(String modemName, String port, int bitRate,
String modemPin, String SMSC)
{
OutboundNotification outboundNotification = new OutboundNotification();
SerialModemGateway gateway = new SerialModemGateway(id, port, bitRate, modemName, "E17u-1");
gateway.setInbound(true);
gateway.setOutbound(true);
gateway.setSimPin(modemPin);
Service.getInstance().setOutboundMessageNotification(outboundNotification);
Service.getInstance().addGateway(gateway);
Service.getInstance().startService();
}
public static void doIt(String number, String text) {
try {
OutboundMessage msg = new OutboundMessage(number, text);
Service.getInstance().sendMessage(msg);
System.out.println(msg);
Service.getInstance().stopService();
} catch (Exception ex) {
if (ex.getStackTrace()[2].getLineNumber() == 189) {
JOptionPane.showMessageDialog(null,
"Port currently owned by usb Modem's application. \n Please close it & run the programm again.",
"Port Exception",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
} else {
JOptionPane.showMessageDialog(null,
ex.getMessage(),
"Sending faile",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
String number = "+94772347634", text = "Hello world";
SendSMS1 app = new SendSMS1("Huwawi", "COM4", 115200, "0000", "+947500010");
for (int i = 0; i < 5; i++) {
app.doIt(number, text);
}
}
}
You must remove the gateway.
can use this-
Service.getInstance().removeGateway(gateway);
you should insert it in doIt method, after - Service.getInstance().stopService();
Change this.It's Working
public static void main(String[] args) throws Exception {
Calendar now = Calendar.getInstance();
String ar=(dateFormat.format(now.getTime()));
String text = "We are the Future of Science "+" "+ar;
SendSMS app = new SendSMS("Huawei", "COM20", 115200, "0000", "+9477000003");
for (int i = 0; i < 1; i++) {
String[] numbers = {"+num","+num","+num","+num","+num","+num","+num","+num"};
for (String item : numbers) {
Service.getInstance().startService();
app.doIt(item, text);
Service.getInstance().stopService();
}}
}
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