I used code from this tutorial https://causeyourestuck.io/2016/04/27/node-js-android-tcpip/, but got the such errors:
Cannot resolve method 'send(java.lang.String)'
Cannot resolve method 'disconnect()'
Problem in Client.java class, which I created from tutorial (link above), but I can't resolve this problem.
MainActivity.java
void doIt() {
Client socket = new Client("192.168.0.8", 1234);
socket.setClientCallback(new Client.ClientCallback () {
#Override
public void onMessage(String message) {
}
#Override
public void onConnect(Socket socket) {
socket.send("Hello World!\n");
socket.disconnect();
}
#Override
public void onDisconnect(Socket socket, String message) {
}
#Override
public void onConnectError(Socket socket, String message) {
}
});
socket.connect();
}
Client.java
public class Client {
private Socket socket;
private OutputStream socketOutput;
private BufferedReader socketInput;
private String ip;
private int port;
private ClientCallback listener=null;
public Client(String ip, int port){
this.ip=ip;
this.port=port;
}
public void connect(){
new Thread(new Runnable() {
#Override
public void run() {
socket = new Socket();
InetSocketAddress socketAddress = new InetSocketAddress(ip, port);
try {
socket.connect(socketAddress);
socketOutput = socket.getOutputStream();
socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
new ReceiveThread().start();
if(listener!=null)
listener.onConnect(socket);
} catch (IOException e) {
if(listener!=null)
listener.onConnectError(socket, e.getMessage());
}
}
}).start();
}
public void disconnect(){
try {
socket.close();
} catch (IOException e) {
if(listener!=null)
listener.onDisconnect(socket, e.getMessage());
}
}
public void send(String message){
try {
socketOutput.write(message.getBytes());
} catch (IOException e) {
if(listener!=null)
listener.onDisconnect(socket, e.getMessage());
}
}
private class ReceiveThread extends Thread implements Runnable{
public void run(){
String message;
try {
while((message = socketInput.readLine()) != null) { // each line must end with a \n to be received
if(listener!=null)
listener.onMessage(message);
}
} catch (IOException e) {
if(listener!=null)
listener.onDisconnect(socket, e.getMessage());
}
}
}
public void setClientCallback(ClientCallback listener){
this.listener=listener;
}
public void removeClientCallback(){
this.listener=null;
}
public interface ClientCallback {
void onMessage(String message);
void onConnect(Socket socket);
void onDisconnect(Socket socket, String message);
void onConnectError(Socket socket, String message);
}
}
That's because you're calling those methods on Socket (which comes from your callback) and not on your Client (which is in another scope) because they have the same name and java will use the smallest variable scope.
Change the name of your callback variable or the name of your Client variable and it should work when using the correct one :)
Ex:
void doIt() {
final Client myClient = new Client("192.168.0.8", 1234);
myClient.setClientCallback(new Client.ClientCallback () {
#Override
public void onMessage(String message) {
}
#Override
public void onConnect(Socket socket) {
myClient.send("Hello World!\n");
myClient.disconnect();
}
#Override
public void onDisconnect(Socket socket, String message) {
}
#Override
public void onConnectError(Socket socket, String message) {
}
});
myClient.connect();
}
Related
I have successfully established connection between two devices but to transfer data of files I have to create socket, and I have constantly failed to do so. After making errors I got to know that sockets work on different thread other then main thread. so I created threads but then I get null pointer exception means the value is vacant and I don't know how??
here's what I have tried form different source and tutorials.
senddatatry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msg=trytext.getText().toString();
receivedata.write(msg);
}
});
final WifiP2pManager.ConnectionInfoListener connectionInfoListener = new WifiP2pManager.ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
inetAddress = info.groupOwnerAddress;
if (info.groupFormed && info.isGroupOwner) {
deviceStatus.setText("Host");
ServerClass serverClass = new ServerClass();
serverClass.start();
} else if (info.groupFormed) {
deviceStatus.setText("Client");
Thread thread1 = new Thread() {
#Override
public void run() {
super.run();
clientClass = new ClientClass(inetAddress);
clientClass.start();
}
};
thread1.start();
}
}
};
public class ServerClass extends Thread{
Socket socket;
ServerSocket serverSocket;
#Override
public void run() {
super.run();
try {
serverSocket=new ServerSocket(8888);
socket=serverSocket.accept();
InputStream input=socket.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(input));
final String msg=reader.readLine();
handler.post(new Runnable() {
#Override
public void run() {
deviceStatus.setText(msg);
}
});
Log.d("server","test");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ClientClass extends Thread{
Socket socket;
OutputStream outputStream;
final String hstname;
public ClientClass(InetAddress address)
{
this.hstname=address.getHostName();
}
#Override
public void run() {
super.run();
if(hstname!=null){
try {
socket.connect(new InetSocketAddress(hstname,8888),1000);
outputStream=socket.getOutputStream();
receivedata=new receivedata(outputStream);
receivedata.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class receivedata extends Thread{
OutputStream outputStream;
public receivedata (OutputStream stream){
this.outputStream=stream;
}
#Override
public void run() {
super.run();
Log.d("start","thread working");
}
public void write(String msg){
PrintWriter writer=new PrintWriter(outputStream,true);
writer.println(msg);
}
}
I have added button on clicklistner from where string is received and I have added server class, client class and where they have been initialized
I have gone through all possible way I knew but I failed.
Please anyone suggest me how can successfully create socket to transfer data. please It's a humble request, I tried but I don't know. So if you could suggest or help me with this, it would be a great favor
I have designed a code which leads to application not responding.
I have used okhttp3.WebSocket for continuous input stream of data on which i am deciding to start an IntentService which will be fetching data from server.
I have an IntentService; in onHandleIntent i am giving an service call for fetching data from the server(roughly 3 calls).
For Service call i am using AsyncTask of android inside which my WebConnectionManger class runs on different thread.
Inside websocket i am getting details of a particular record for which i am going to fetch the details from the service call.
For 5-6 such records my application runs fine, but if records get 80-100 my application do not respond at all and i get ANR.
I am using simple plain TCP request for this.
can any on tells me what is the actual issue and how i can get rid of it?
any help is appreciated.
i am pasting the code of WebSocket, AsyncTask(rest two have same implementation), WebConnectionManger class and IntentService class.
WebSocket.class
public class WebSocket {
public static boolean isConnected;
public static String TO_UPDATE = "toOrderUpdate";
#SuppressLint("StaticFieldLeak")
private static WebSocket _instance;
private static OkHttpClient client;
private static WebSocket webSocket = null;
private Context mContext;
private AppPreferences preferences;
private WebSocket() {
client = new OkHttpClient();
}
public WebSocket(Context context) {
client = new OkHttpClient();
mContext = context;
preferences = new AppPreferences(mContext);
init(mContext);
}
public static WebSocket getInstance(Context mContext) {
if (_instance == null) {
_instance = new WebSocket(mContext);
}
return _instance;
}
public static void closeWebSocket() {
if (isConnected) {
webSocket.close(1001, LOGOUT);
_instance = null;
webSocket = null;
isConnected = false;
}
}
public void init(Context context) {
if (webSocket == null) {
preferences = new AppPreferences(context);
Request request = new Request.Builder()
.url(preferences.getWSUrl() + ":" + preferences.getWSPort() + "/" + preferences.getUserID())
.build();
WebSocketMessageListener messageListener = new WebSocketMessageListener();
webSocket = client.newWebSocket(request, messageListener);
isConnected = true;
}
}
private class WebSocketMessageListener extends WebSocketListener {
// private static final int NORMAL_CLOSURE_STATUS = 1000;
#Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
Log.i("******", "Socket Open");
}
#Override
public void onMessage(WebSocket webSocket, String response) {
try {
super.onMessage(webSocket, response);
Log.i("******", "Message Received " + response);
// Logger.log("OnMessage : " + response);
ModelAdvertisements modelAdvertisements = DecoderJSONWebSocket.decode(response);
Intent intentForService = new Intent(mContext, WebSocketService.class);
int transCode = Integer.parseInt(modelAdvertisements.getTC());
Intent mwBroadcastIntent = new Intent();
switch (transCode) {
case 1005:
mwBroadcastIntent.setAction(Constants.IntentKeys.KEY_LOGICAL_SESSION_START_END);
mContext.sendBroadcast(mwBroadcastIntent);
break;
case 1004:
case 1006:
case 1007:
intentForService.putExtra(TO_UPDATE, true);
mContext.startService(intentForService);
break;
case 1008:
try {
mwBroadcastIntent.putExtra(KEY_AUCTION_FLOOR_SNAPSHOT, modelAdvertisements);
mwBroadcastIntent.setAction(Constants.IntentKeys.KEY_MARKET_DATASNAPSHOT);
mContext.sendBroadcast(mwBroadcastIntent);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
} catch (Exception e) {
// e.printStackTrace();
}
}
#Override
public void onClosing(WebSocket webSockett, int code, String reason) {
super.onClosing(webSockett, code, reason);
Log.i("******", "Socket Closing Reason: " + reason);
}
#Override
public void onClosed(WebSocket webSockett, int code, String reason) {
super.onClosed(webSockett, code, reason);
Log.i("******", "Socket closed reason: " + reason);
webSocket = null;
isConnected = false;
}
#Override
public void onFailure(WebSocket webSockett, Throwable t, Response response) {
super.onFailure(webSockett, t, response);
isConnected = false;
webSocket = null;
Logger.log(e);
}
}
}
WebSocketService.class
public class WebSocketService extends IntentService {
String securityId;
private Context mContext;
private String tokenId;
private String contractCode;
private int transCode;
private boolean toUpdate;
private String mktCode;
public WebSocketService() {
super("WebSocketService");
}
public WebSocketService(String name) {
super(name);
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
if (intent != null) {
tokenId = intent.getStringExtra(KEY_TOKEN_ID);
transCode = intent.getIntExtra(KEY_TRANSCODE, 0);
toUpdate = intent.getBooleanExtra(NeMLWebSocket.TO_UPDATE, false);
contractCode = intent.getStringExtra(KEY_SYMBOL);
mktCode = intent.getStringExtra(KEY_ADV_REF_ID);
}
securityId = DatabaseUtils.getSecurityIdFromFOOrders(mContext, tokenId);
performTokenMasterTask();
}
#Override
public void onCreate() {
super.onCreate();
mContext = this;
}
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
protected void performTokenMasterTask() {
synchronized (this) {
TokenMasterTask tokenMasterTask = new TokenMasterTask(mContext, new RequestCallback() {
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
if (transCode == TC_1004_WEB_SOCKET) {
Intent mwBroadcastIntent = new Intent();
mwBroadcastIntent.setAction(Constants.IntentKeys.KEY_TOKEN_SESSION_START_END);
mContext.sendBroadcast(mwBroadcastIntent);
// stopSelf();
} else if (transCode == TC_TIME_WEB_SOCKET || transCode == TC_AUCTION_WEB_SOCKET) {
performTimeSessionTask();
}
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
try {
Logger.log(transCode + "--->" + msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}, mktCode);
tokenMasterTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, tokenId);
if (transCode == TC_TIME_WEB_SOCKET || transCode == TC_AUCTION_WEB_SOCKET) {
performTimeSessionTask();
}
}
}
public void performTimeSessionTask() {
synchronized (this) {
TimeSessionMapTask timeSessionMapTask = new TimeSessionMapTask(mContext, new RequestCallback() {
ProgressDialog progressDialog;
private boolean m_ConnectionErr = false;
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
if (!m_ConnectionErr) {
if (transCode == TC_AUCTION_WEB_SOCKET) {
performFoOrderTask();
}
}
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
try {
Logger.log("Received ErrorMessage :" + msg + " \n ErrorCode :" + transCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}, modelMarket);
timeSessionMapTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, TIME_SESSION);
if (transCode == TC_AUCTION_WEB_SOCKET) {
performFoOrderTask();
}
}
}
private synchronized void performFoOrderTask() {
synchronized (mContext) {
FOOrdersTask foOrdersTask = new FOOrdersTask(mContext, new RequestCallback() {
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
}
});
foOrdersTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, tokenId);
}
}
}
TokenMasterTask.class
public class TokenMasterTask extends AsyncTask<Object, Void, ModelToken> {
private final String mktCode;
private RequestCallback _callback;
#SuppressLint("StaticFieldLeak")
private Context context;
private boolean isConnectionError;
private ModelToken modelToken;
private boolean isServerDown;
public TokenMasterTask(Context context, RequestCallback requestCallback, String mktCode) {
this.context = context;
this.mktCode = mktCode;
if (requestCallback == null) {
requestCallback = new RequestCallback() {
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
}
};
}
this._callback = requestCallback;
}
#Override
protected ModelToken doInBackground(Object... voids) {
if (voids != null && voids.length > 0) {
String tokenId = String.valueOf(voids[0]);
isConnectionError = false;
transactionCall(tokenId);
}
return modelToken;
}
private void transactionCall(String tokenId) {
try {
WebConnectionManager connectionManager = new WebConnectionManager(context, new ConnectionListener() {
#Override
public void notifyReadCompleted(String f_Response) {
modelToken = DecoderTokenRequest.decode(f_Response);
synchronized (TokenMasterTask.this) {
TokenMasterTask.this.notify();
}
}
#Override
public void notifySocketError(boolean isServerDown) {
if (!isServerDown) {
isConnectionError = true;
}
TokenMasterTask.this.isServerDown = isServerDown;
synchronized (TokenMasterTask.this) {
TokenMasterTask.this.notify();
}
}
#Override
public void onReceivePacket(int total, int current) {
_callback.onProgress(current, total);
}
});
connectionManager.modifiedHandleRequest(EncoderTokenRequest.encode(context, tokenId,mktCode).getBytes());
} catch (Exception e) {
e.printStackTrace();
Logger.log(e);
}
synchronized( TokenMasterTask.this) {
try {
TokenMasterTask.this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
protected void onPostExecute(ModelToken modelToken) {
if (isServerDown) {
_callback.onError(Constants.ErrorCode.TC_ERROR_SERVER_DOWN, "");
} else if (isConnectionError) {
_callback.onError(0, "Connection Error.");
} else if (modelToken!=null && modelToken.getErrorCode() != null && !TextUtils.isEmpty(modelToken.getErrorCode()) && !modelToken.getErrorCode().equalsIgnoreCase("200")) {
_callback.onError(Integer.parseInt(modelToken.getErrorCode()), modelToken.getError());
} else {
_callback.onComplete(modelToken);
}
super.onPostExecute(modelToken);
}
}
WebConnectionManager.class
public class WebConnectionManager {
private String m_Response = "";
byte[] m_RequestData;
boolean m_Read_Response_Completed = false;
Thread l_WorkerThread;
ConnectionListener m_ConnectionListener;
boolean m_IsFetchCompleted;
Context context;
AppPreferences preferences;
Socket mWebSocket;
public WebConnectionManager(Context mcontext, ConnectionListener f_LoginListener) {
m_ConnectionListener = f_LoginListener;
m_IsFetchCompleted = false;
context = mcontext;
preferences = new AppPreferences(context);
}
public String modifiedHandleRequest(byte[] f_RequestData) {
m_RequestData = f_RequestData;
Logger.log("" + Constants.TIME_OUT);
l_WorkerThread = new Thread(new Runnable() {
#Override
public void run() {
String encodedIP = null;
try {
if (mWebSocket == null || !mWebSocket.isBound()
|| mWebSocket.isClosed() ) {
mWebSocket = new Socket(ip, port);
mWebSocket.setKeepAlive(true);
mWebSocket.setSoTimeout(Constants.TIME_OUT);
}
if (m_RequestData == null) {
m_Read_Response_Completed = true;
if (!mWebSocket.isClosed()) {
m_ConnectionListener.notifyReadCompleted("Connected");
return;
} else {
m_ConnectionListener.notifyReadCompleted("Disconnected");
return;
}
} else {
String request = new String(m_RequestData);
Logger.log(Utils.encodePackets(request));
}
InputStream inputStream = mWebSocket.getInputStream();
try {
mWebSocket.getOutputStream().write(m_RequestData);
} catch (Exception e) {
Logger.log(e);
}
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(1048576);
byte[] buffer = new byte[1048576];
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
m_Response = byteArrayOutputStream.toString();
}
inputStream.close();
byteArrayOutputStream.close();
mWebSocket.close();
if (TextUtils.isEmpty(m_Response.toString().trim())) {
throw new IOException("Empty Response");
} else {
m_ConnectionListener.notifyReadCompleted(m_Response.toString());
}
} catch (UnknownHostException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
} catch (SocketTimeoutException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(false);
mWebSocket = null;
e.printStackTrace();
} catch (SocketException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
e.printStackTrace();
} catch (IOException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
e.printStackTrace();
} catch (Exception e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
e.printStackTrace();
}
}
});
l_WorkerThread.start();
return m_Response;
}
}
And the interfaces.
public interface ConnectionListener {
void notifyReadCompleted(String f_Response);
void notifySocketError(boolean isServerDown);
void onReceivePacket(int total, int current);
}
public interface RequestCallback {
void onStart();
void onComplete(Object object);
void onProgress(int current, int total);
void onError(int transCode, String msg);
}
You may want to check what is blocking the main thread for more than 6 seconds.
Usually ANR happens when main thread is blocked for some time. 6-10 seconds.
I'm trying Smack 4.2 on Android and I have a problem with the IncomingListener.
I created a class MyXMPP totaly dedicated to XMPP work.
( I just have one android activity. )
In this activity, in OnCreate(), I connected to XMPP server using my class MyXMPP and I retrieved my ChatManager in my a final value to place on an IncomingChatMessageListener().
Everything works well in the first try. But when I pause my activity and relaunch it, it's like the older listener remains. So at this moment, I receive messages in double.
If I pause again my application, it's like I have 3 listeners and so on.
I precise I have no problem whith connection to my server.
Here my code :
Android activity :
public class TestMessagingActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_messaging);
MyXMPPP.getInstance().init("test", "test");
MyXMPPP.getInstance().connect();
final ChatManager chatManager = MyXMPPP.getInstance().getChatManager();
chatManager.addIncomingListener(new IncomingChatMessageListener() {
#Override
public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
final AsyncTask<Message, Void, Void> mReceiveMessage = new AsyncTask<Message, Void, Void>() {
#Override
protected Void doInBackground(Message... params) {
ChatMessage chatMessage = new ChatMessage(params[0].getBody(), false);
Log.v("TAG", "index=message arrived");
Log.v("TAG", params[0].getBody());
return null;
}
#Override
protected void onPostExecute(Void res) {
}
};
mReceiveMessage.execute(message);
}
});
}
}
MyXMPP class :
public class MyXMPPP {
private static final String DOMAIN = "test.com";
private AbstractXMPPConnection connection;
private XMPPConnectionListener connectionListener = new XMPPConnectionListener();
private ChatManager chatManager;
private Presence presence;
boolean isConnected=false;
boolean chatManagerCreated=false;
private static MyXMPPP instance =null;
public synchronized static MyXMPPP getInstance() {
if(instance==null){
instance = new MyXMPPP();
}
return instance;
}
public void init(String user, String password) {
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
configBuilder.setUsernameAndPassword(user, password);
configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
configBuilder.setKeystoreType(null);
try {
configBuilder.setXmppDomain(DOMAIN);
} catch (XmppStringprepException e) {
e.printStackTrace();
}
connection = new XMPPTCPConnection(configBuilder.build());
connection.addConnectionListener(connectionListener);
}
public void connect() {
if (isConnected == false) {
AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
try {
connection.connect();
connection.login();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
};
connectionThread.execute();
}
}
public AbstractXMPPConnection getConnection() {
return connection;
}
public void createChatManager()
{
if(chatManagerCreated==false)
{
chatManager=ChatManager.getInstanceFor(connection);
chatManagerCreated=true;
Log.v("TAG", "index=chat manager created");
}
}
public ChatManager getChatManager()
{
return chatManager;
}
public void sendMessage(String message, EntityBareJid jid)
{
if(chatManagerCreated==true)
{
Chat chat = chatManager.chatWith(jid);
try {
chat.send(message);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean getIsConnected(){
return isConnected;
}
public class XMPPConnectionListener implements ConnectionListener{
#Override
public void connected(XMPPConnection connection) {
}
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
isConnected=true;
createChatManager();
presence = new Presence(Presence.Type.available, "Online", 24, Presence.Mode.available);
try {
connection.sendStanza(presence);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void connectionClosed() {
isConnected=false;
}
#Override
public void connectionClosedOnError(Exception e) {
isConnected=false;
}
#Override
public void reconnectionSuccessful() {
}
#Override
public void reconnectingIn(int seconds) {
}
#Override
public void reconnectionFailed(Exception e) {
}
}
}
Is this problem normal ?
When I put the listener to on the chatManager in the XMPP class, I don't have this problem. But I would like to do work in my activity / in my view, so having the listener here seems to be better.
I need some advice.
Thank you.
Nico.
Here I have a query related to connection between android socket and server. I'm following https://socket.io/blog/native-socket-io-and-android/ and found that it is working fine, so I replaced my local server URL with the URL in the tutorial. But here I'm always getting a connection failed or disconnection error. Here is my application class for further clarification.
public class ChatApplication extends Application {
private Socket mSocket;
{
try {
IO.Options options = new IO.Options();
options.forceNew = true;
options.reconnection = true;
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("uid", 1);
jsonObject.put("usid", 6847);
options.query = jsonObject.toString();
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("JSON", jsonObject.toString());
Log.e("OPTIONS", options.toString());
mSocket = IO.socket(Constants.CHAT_SERVER_URL, options);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public Socket getSocket() {
return mSocket;
}
}
And the code of the fragment is below. It keeps calling onDisconnect() whenever I use my local server for it.
public class MainFragment extends Fragment {
private static final String TAG = "MainFragment";
private static final int REQUEST_LOGIN = 0;
private static final int TYPING_TIMER_LENGTH = 600;
private RecyclerView mMessagesView;
private EditText mInputMessageView;
private List<Message> mMessages = new ArrayList<Message>();
private RecyclerView.Adapter mAdapter;
private boolean mTyping = false;
private Handler mTypingHandler = new Handler();
private String mUsername;
private Socket mSocket;
private Boolean isConnected = true;
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (!isConnected) {
if (null != mUsername)
mSocket.emit("add user", mUsername);
Toast.makeText(getActivity().getApplicationContext(),
R.string.connect, Toast.LENGTH_LONG).show();
isConnected = true;
}
}
});
}
};
private Emitter.Listener onDisconnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Log.i(TAG, "diconnected");
isConnected = false;
Toast.makeText(getActivity().getApplicationContext(),
R.string.disconnect, Toast.LENGTH_LONG).show();
}
});
}
};
private Emitter.Listener onConnectError = new Emitter.Listener() {
#Override
public void call(Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e(TAG, "Error connecting");
Toast.makeText(getActivity().getApplicationContext(),
R.string.error_connect, Toast.LENGTH_LONG).show();
}
});
}
};
private Emitter.Listener onNewMessage = new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
String message;
try {
username = data.getString("username");
message = data.getString("message");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
}
removeTyping(username);
addMessage(username, message);
}
});
}
};
private Emitter.Listener onUserJoined = new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
int numUsers;
try {
username = data.getString("username");
numUsers = data.getInt("numUsers");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
}
addLog(getResources().getString(R.string.message_user_joined, username));
addParticipantsLog(numUsers);
}
});
}
};
private Emitter.Listener onUserLeft = new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
int numUsers;
try {
username = data.getString("username");
numUsers = data.getInt("numUsers");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
}
addLog(getResources().getString(R.string.message_user_left, username));
addParticipantsLog(numUsers);
removeTyping(username);
}
});
}
};
private Emitter.Listener onTyping = new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
try {
username = data.getString("username");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
}
addTyping(username);
}
});
}
};
private Emitter.Listener onStopTyping = new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
try {
username = data.getString("username");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
}
removeTyping(username);
}
});
}
};
private Runnable onTypingTimeout = new Runnable() {
#Override
public void run() {
if (!mTyping) return;
mTyping = false;
mSocket.emit("stop typing");
}
};
public MainFragment() {
super();
}
// This event fires 1st, before creation of fragment or any views
// The onAttach method is called when the Fragment instance is associated with an Activity.
// This does not mean the Activity is fully initialized.
#Override
public void onAttach(Context context) {
super.onAttach(context);
mAdapter = new MessageAdapter(context, mMessages);
if (context instanceof Activity) {
//this.listener = (MainActivity) context;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
ChatApplication app = (ChatApplication) getActivity().getApplication();
mSocket = app.getSocket();
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
mSocket.on("new message", onNewMessage);
mSocket.on("user joined", onUserJoined);
mSocket.on("user left", onUserLeft);
mSocket.on("typing", onTyping);
mSocket.on("stop typing", onStopTyping);
mSocket.connect();
startSignIn();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onDestroy() {
super.onDestroy();
mSocket.disconnect();
mSocket.off(Socket.EVENT_CONNECT, onConnect);
mSocket.off(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
mSocket.off("new message", onNewMessage);
mSocket.off("user joined", onUserJoined);
mSocket.off("user left", onUserLeft);
mSocket.off("typing", onTyping);
mSocket.off("stop typing", onStopTyping);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMessagesView = (RecyclerView) view.findViewById(R.id.messages);
mMessagesView.setLayoutManager(new LinearLayoutManager(getActivity()));
mMessagesView.setAdapter(mAdapter);
mInputMessageView = (EditText) view.findViewById(R.id.message_input);
mInputMessageView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int id, KeyEvent event) {
if (id == R.id.send || id == EditorInfo.IME_NULL) {
attemptSend();
return true;
}
return false;
}
});
mInputMessageView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (null == mUsername) return;
if (!mSocket.connected()) return;
if (!mTyping) {
mTyping = true;
mSocket.emit("typing");
}
mTypingHandler.removeCallbacks(onTypingTimeout);
mTypingHandler.postDelayed(onTypingTimeout, TYPING_TIMER_LENGTH);
}
#Override
public void afterTextChanged(Editable s) {
}
});
ImageButton sendButton = (ImageButton) view.findViewById(R.id.send_button);
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
attemptSend();
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (Activity.RESULT_OK != resultCode) {
getActivity().finish();
return;
}
mUsername = data.getStringExtra("username");
int numUsers = data.getIntExtra("numUsers", 1);
addLog(getResources().getString(R.string.message_welcome));
addParticipantsLog(numUsers);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.menu_main, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_leave) {
leave();
return true;
}
return super.onOptionsItemSelected(item);
}
private void addLog(String message) {
mMessages.add(new Message.Builder(Message.TYPE_LOG)
.message(message).build());
mAdapter.notifyItemInserted(mMessages.size() - 1);
scrollToBottom();
}
private void addParticipantsLog(int numUsers) {
addLog(getResources().getQuantityString(R.plurals.message_participants, numUsers, numUsers));
}
private void addMessage(String username, String message) {
mMessages.add(new Message.Builder(Message.TYPE_MESSAGE)
.username(username).message(message).build());
mAdapter.notifyItemInserted(mMessages.size() - 1);
scrollToBottom();
}
private void addTyping(String username) {
mMessages.add(new Message.Builder(Message.TYPE_ACTION)
.username(username).build());
mAdapter.notifyItemInserted(mMessages.size() - 1);
scrollToBottom();
}
private void removeTyping(String username) {
for (int i = mMessages.size() - 1; i >= 0; i--) {
Message message = mMessages.get(i);
if (message.getType() == Message.TYPE_ACTION && message.getUsername().equals(username)) {
mMessages.remove(i);
mAdapter.notifyItemRemoved(i);
}
}
}
private void attemptSend() {
if (null == mUsername) return;
if (!mSocket.connected()) return;
mTyping = false;
String message = mInputMessageView.getText().toString().trim();
if (TextUtils.isEmpty(message)) {
mInputMessageView.requestFocus();
return;
}
mInputMessageView.setText("");
addMessage(mUsername, message);
// perform the sending message attempt.
mSocket.emit("new message", message);
}
private void startSignIn() {
// mUsername = null;
Intent intent = new Intent(getActivity(), LoginActivity.class);
startActivityForResult(intent, REQUEST_LOGIN);
}
private void leave() {
mUsername = null;
mSocket.disconnect();
mSocket.connect();
startSignIn();
}
private void scrollToBottom() {
mMessagesView.scrollToPosition(mAdapter.getItemCount() - 1);
}
}
I'm using CHAT_SERVER_URL = "http://192.168.1.14:3000/" to make connection with server but it's not working for me. It works fine when we try to make a web connection through emulator or computer system. Can anyone please give me an idea if I'm doing anything wrong.
Thanks.
After debugging at the server end too, I got to know how to hit my server to make a connection and I got that we don't require IO.Options and Options.query in every case and now it is working fine completely. So for more clarification I'm posting an answer here:
//connect to server
public void startRunning() {
try {
if (baseUrl != null) {
socket = IO.socket("http://" + baseUrl + ":3000?uid=" + userId + "&usid=" + userSessionId);
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
if (socket == null) return;
socket
.on(Socket.EVENT_CONNECT, CONNECTED)
.on(Socket.EVENT_DISCONNECT, DISCONNECTED)
.on("chat-message", CHAT_MESSAGE)
.on("chats-active", CHATS_ACTIVE)
.on("chat-logout", LOGOUT)
.on("messages-read", MESSAGE_READ)
.on("chat-login", CHAT_LOGIN);
socket.connect();
}
I am creating an android chat application using xmpp smack library.I have create a background service to listen to incoming chats and use an application class to initialize the xmpp connection object.
The problem is the chatCreated function of chat listener is called twice therefore duplicate message is shown..
This is my application class where i have created connection
Authenticate.java
public class Authenticate extends Application {
private static final String DOMAIN = StaticVariables.chatServer;
private static final String HOST = StaticVariables.chatServer;
private static final int PORT = 5222;
static AbstractXMPPConnection connection ;
String username,password;
private boolean connected;
#Override
public void onCreate() {
super.onCreate();
}
public AbstractXMPPConnection initializeXMPPTCPConnection(String username,String password) {
Log.e("APPLICATION", "username: "+username);
Log.e("APPLICATION", "password: "+password);
Log.i("APPLCATION", "initializeXMPPTCPConnection calle:");
this.username=username;
this.password=password;
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
configBuilder.setUsernameAndPassword(username, password);
configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
configBuilder.setResource("Android");
configBuilder.setServiceName(DOMAIN);
configBuilder.setHost(HOST);
configBuilder.setPort(PORT);
configBuilder.setDebuggerEnabled(true);
connection = new XMPPTCPConnection(configBuilder.build());
connection=connectConnection();
Log.e("APPLICATION", "initializeXMPPTCPConnection: "+connection.isConnected());
return connection;
}
public AbstractXMPPConnection getConnection(){
return connection;
}
public AbstractXMPPConnection connectConnection()
{
AsyncTask<Void, Void, AbstractXMPPConnection> connectionThread = new AsyncTask<Void, Void, AbstractXMPPConnection>() {
#Override
protected AbstractXMPPConnection doInBackground(Void... arg0) {
// Create a connection
try {
connection.connect().login();
Log.e("Application", "doInBackground: "+connection.isConnected());
//login();
connected = true;
//sendMsg();
} catch (IOException e) {
e.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
}
return connection;
}
#Override
protected void onPostExecute(AbstractXMPPConnection connection2) {
super.onPostExecute(connection2);
// sendMsg(message.getText().toString());
Log.e("APPLICATION", "onPostExecute: "+connection2.isConnected());
connection=connection2;
}
};
try {
connection=connectionThread.execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Log.e("Application", "connectConnection: "+connection.isConnected());
return connection;
}
public void login() {
try {
connection.login(username, password);
Log.e("APPLICATIPN", "Yey! We're connected to the Xmpp server!");
} catch (XMPPException | SmackException | IOException e) {
e.printStackTrace();
} catch (Exception e) {
}
}
}
This is the code through which i am calling connection instance
connection=((Authenticate)getApplication()).getConnection();
Listener function
public void listenChat(String name){
ChatManager manager = ChatManager.getInstanceFor(connection);
manager.addChatListener(new ChatManagerListener() {
#Override
public void chatCreated(final Chat chat, boolean createdLocally) {
System.out.println("Created chat");
chat.addMessageListener(new ChatMessageListener() {
#Override
public void processMessage(final Chat chat, final org.jivesoftware.smack.packet.Message message) {
//This is called twice
}
}
});
}
});
}
I am a beginner in android and as well in xmpp.Please tell me where i am wrong how can i resolve it
You have to fix createdLocally usage in chatCreated method.
Just add the listener if is not createdLocally like this:
public void chatCreated(Chat chat, boolean createdLocally)
{
if (!createdLocally)
{
chat.addMessageListener(new ChatMessageListener()...);
}
}