According to an google example, i write an android client for a connection protocol based on TCP Socket server can send and receive information and it works good. But now I want it to become a background service for these transactions, after I left the application it also can notify me the message in time, I think a couple of days, but without success, someone can give me some help? Very grateful!
MainActivity
public class MainActivity extends Activity implements
Handler.Callback, ChatFragment.MessageTarget {
public static final String TAG = "rolingbaby";
public static final int MESSAGE_READ = 0x400 + 1;
public static final int MESSAGE_SEND = 0x400 + 2;
public static final String SERVER_URL = "192.168.191.2";
public static final int SERVER_PORT = 7838;
private Handler handler = new Handler(this);
private ChatFragment chatFragment;
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
InetAddress address = InetAddress.getByName(SERVER_URL);
Log.d(TAG, "Connected success!");
new MyTask1(((ChatFragment.MessageTarget) this).getHandler(),
address).execute();
} catch (UnknownHostException e) {
e.printStackTrace();
}
chatFragment = new ChatFragment();
getFragmentManager().beginTransaction()
.add(R.id.container, chatFragment, "trans")
.commit();
}
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
Log.d(TAG, readMessage);
(chatFragment).pushMessage("Rec: " + readMessage);
break;
case MESSAGE_SEND:
Object obj = msg.obj;
(chatFragment).setChatManager((ChatManager) obj);
}
return true;
}
#Override
protected void onPause() {
super.onPause();
finish();
}
}
Pivotal code in ChatFragment
public interface MessageTarget {
public Handler getHandler();
}
public void setChatManager(ChatManager obj) {
chatManager = obj;
}
public void pushMessage(String readMessage) {
adapter.add(readMessage);
adapter.notifyDataSetChanged();
}
MyTask
public class MyTask extends AsyncTask<Void, Void, Void>{
private static final String TAG = "ClientSocketHandler";
private Handler handler;
private ChatManager chat;
private InetAddress mAddress;
private static final int timeOut = 5000;
public MyTask(Handler handler, InetAddress serverAddress) {
this.handler = handler;
this.mAddress = serverAddress;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
Socket socket = new Socket();
try {
socket.bind(null);
socket.connect(new InetSocketAddress(mAddress.getHostAddress(),
MainActivity.SERVER_PORT), timeOut);
Log.d(TAG, "Launching the I/O handler");
chat = new ChatManager(socket, handler);
new Thread(chat).start();
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return null;
}
public ChatManager getChat() {
return chat;
}
}
ChatManager
public class ChatManager implements Runnable {
private Socket socket = null;
private Handler handler;
public ChatManager(Socket socket, Handler handler) {
this.socket = socket;
this.handler = handler;
}
private InputStream iStream;
private OutputStream oStream;
private static final String TAG = "ChatHandler";
public static String readMessage;
#Override
public void run() {
try {
iStream = socket.getInputStream();
oStream = socket.getOutputStream();
byte[] buffer = new byte[1024];
int bytes;
handler.obtainMessage(MainActivity.MESSAGE_SEND, this)
.sendToTarget();
while (true) {
try {
// Read from the InputStream
bytes = iStream.read(buffer);
if (bytes == -1) {
break;
}else{
readMessage = new String(buffer, "UTF-8");
}
// Send the obtained bytes to the UI Activity
Log.d(TAG, "Rec:" + String.valueOf(buffer));
handler.obtainMessage(MainActivity.MESSAGE_READ,
bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void write(byte[] buffer) {
try {
oStream.write(buffer);
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
}
Related
I have two classes:
MainActivity.class
ScreenCapture.class
and want getOutputStream(); from a Socket that is located on MainActivity.class.
Then i do:
MainActivity.INSTANCE.clientSocket.getOutputStream();
but is failing in this line ^, i not left logcat here because my logcat not is catching all events correctly, but from this description hope that someone can help.
MainActivity
public class MainActivity extends AppCompatActivity {
public static final MainActivity INSTANCE = new MainActivity();
public Socket clientSocket;
private final int SERVERPORT = 101;
private final String SERVER_IP = "192.168.15.13";
/////////////////////////////////////////////// CLIENTSOCKET //////////////////////////////////////////////////////
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
clientSocket = new Socket(serverAddr, SERVERPORT);
new Thread(new CommsThread()).start();
} catch (Exception e1) {
System.out.println(e1.toString());
}
}
}
class CommsThread implements Runnable {
#Override
public void run() {
try {
System.out.println("Waiting for server request");
while(clientSocket.isConnected()){
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())),true);
if (reader.ready()) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
if(line != null && !line.trim().isEmpty()) {
if(line.equalsIgnoreCase("screen")){
// Do something
out.flush();
}
if(line.equalsIgnoreCase("exit")) break;
}
}
}
Thread.sleep(100);
}
System.out.println("Shutting down Socket!!");
clientSocket.close();
} catch (Exception e1) {
System.out.println(e1.toString());
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new ClientThread()).start();
}
ScreenCapture
public class ScreenCaptureClass {
#UiThread
public boolean takeScreenshot(#NonNull Context context) {
//...
imageReader.setOnImageAvailableListener(new OnImageAvailableListener() {
#Override
public void onImageAvailable(final ImageReader reader) {
new AsyncTask<Void, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(final Void... params) {
// ...
OutputStream outs = MainActivity.INSTANCE.clientSocket.getOutputStream(); // <= Error is here
}
}
}
}
}
}
Try to pass the socket's reference to your ScreenCaptureClass, you can try the following things:
You can pass your socket through the ScreenCaptureClass constructor (probably the best way).
Inside your ScreenCaptureClass you can add a static variable like private static OutputStream outputStream and a setter called from your MainActivity :
public static void setOutputStream(OutputStream os) {
outputStream = os;
}
I have this client and server communication program. I got the idea from Android-er website.
This codes send a one random number when the customer pressing the connection button and I want to send new random number of every five minutes when the client had been connected with server.
Client code:
public class MainActivity extends AppCompatActivity {
TextView textResponse;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonClear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText)findViewById(R.id.address);
editTextPort = (EditText)findViewById(R.id.port);
buttonConnect = (Button)findViewById(R.id.connect);
buttonClear = (Button)findViewById(R.id.clear);
textResponse = (TextView)findViewById(R.id.response);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonClear.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
textResponse.setText("");
}});
}
View.OnClickListener buttonConnectOnClickListener = new View.OnClickListener(){
#Override
public void onClick(View arg0) {
MyClientTask myClientTask = new MyClientTask(
editTextAddress.getText().toString(),
Integer.parseInt(editTextPort.getText().toString()));
myClientTask.execute();
}};
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
MyClientTask(String addr, int port){
dstAddress = addr;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
/*
* notice:
* inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
and this is the code of server:
public class MainActivity extends AppCompatActivity {
TextView info, infoip, msg, randGen;
String message = "";
ServerSocket serverSocket;
String vRand="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
info = (TextView) findViewById(R.id.info);
infoip = (TextView) findViewById(R.id.infoip);
msg = (TextView) findViewById(R.id.msg);
randGen= (TextView)findViewById(R.id.viewRand);
infoip.setText(getIpAddress());
Thread socketServerThread = new Thread(new SocketServerThread());
socketServerThread.start();
}
public String rGenerate() {
Random rand= new Random();
int number= rand.nextInt(500-251)+251;
vRand = String.valueOf(number);
//randGen.setText(vRand);
return vRand;
}
#Override
protected void onDestroy() {
super.onDestroy();
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerThread extends Thread {
static final int SocketServerPORT = 8080;
int count = 0;
#Override
public void run() {
try {
serverSocket = new ServerSocket(SocketServerPORT);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
info.setText("I'm waiting here: "
+ serverSocket.getLocalPort());
}
});
while (true) {
Socket socket = serverSocket.accept();
count++;
message += "#" + count + " from " + socket.getInetAddress()
+ ":" + socket.getPort() + "\n";
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(
socket, count);
socketServerReplyThread.run();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerReplyThread extends Thread {
private Socket hostThreadSocket;
int cnt;
SocketServerReplyThread(Socket socket, int c) {
hostThreadSocket = socket;
cnt = c;
}
#Override
public void run() {
OutputStream outputStream;
String num =rGenerate();
try {
outputStream = hostThreadSocket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.print(num);
printStream.close();
message += num + "\n";
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message += "Something wrong! " + e.toString() + "\n";
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
}
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
}
You can use handler to perform tasks at specific delay. I assumed you know how to send the random numbers using sockets so i wont mess socket codes
Button button = (Button) findViewById(R.id.start_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
sendData();
handler.postDelayed(this, 15000);
}
}, 15000);
}
});
private void sendData(){
new Worker().execute();
}
private class Worker extends AsyncTask<Void, Void, String>{
private static final String TAG = "Worker";
#Override
protected String doInBackground(Void... params) {
return "Hello There";
}
#Override
protected void onPostExecute(String s) {
Log.i(TAG, s);
}
}
You can use a Handler to do something in a certain time period. Try this
Handler customHandler = new android.os.Handler();
static final int SOCKET_VERIFY_TIME = 5000; //milliseconds
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
customHandler.postDelayed(updateTimerThread, SOCKET_VERIFY_TIME);
...
}
private Runnable updateTimerThread = new Runnable() {
public void run()
{
if(socket != null) {
if(socket.connected()) {
socket.emit("eventNumber", randNumber);
}
}
customHandler.postDelayed(this, SOCKET_VERIFY_TIME);
}
};
if you want stop updates use this
customHandler.removeCallbacks(updateTimerThread);
In your Client
public class MainActivity extends AppCompatActivity {
TextView textResponse;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonClear;
Handler customHandler = new android.os.Handler();
static final int SOCKET_VERIFY_TIME = 5000; //milliseconds
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText)findViewById(R.id.address);
editTextPort = (EditText)findViewById(R.id.port);
buttonConnect = (Button)findViewById(R.id.connect);
buttonClear = (Button)findViewById(R.id.clear);
textResponse = (TextView)findViewById(R.id.response);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonClear.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
textResponse.setText("");
}});
/***** Events Socket ***********/
socket = IO.socket(new URI(URL_SERVER));
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
yourActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// Socket is connect. Do something here
/******************* Set Handler delay ******************/
customHandler.postDelayed(updateTimerThread, SOCKET_VERIFY_TIME);
/************************************************/
}
});
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(final Object... args) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// Socket is disconnect. Do something here
customHandler.removeCallbacks(updateTimerThread); // stop handler updates
}
});
}
})
}
View.OnClickListener buttonConnectOnClickListener = new View.OnClickListener(){
#Override
public void onClick(View arg0) {
MyClientTask myClientTask = new MyClientTask(
editTextAddress.getText().toString(),
Integer.parseInt(editTextPort.getText().toString()));
myClientTask.execute();
}};
private Runnable updateTimerThread = new Runnable() {
public void run()
{
if(socket != null) {
if(socket.connected()) {
socket.emit("eventNumber", randNumber);
}
}
customHandler.postDelayed(this, SOCKET_VERIFY_TIME);
}
};
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
MyClientTask(String addr, int port){
dstAddress = addr;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
/*
* notice:
* inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
I am looking for a way to send received data (receive while flag is set) from a socket service to an activity that is bound to the service. What is the best way to do this ? Handlers , AsyncTask or something else ?
this is the SocketClass I am using to start a connection and handle the incoming messages :
class connectSocket implements Runnable {
#Override
public void run() {
running= true;
try {
socket = new Socket(serverAddr, SERVERPORT);
try {
mBufferOut = new ObjectOutputStream(socket.getOutputStream());
mBufferIn = new ObjectInputStream(socket.getInputStream());
while(running){
msg = (Message) mBufferIn.readObject();
}
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
Update :
public class SocketService extends Service {
private static final String TAG = "com.oos.kiesa.chat";
public static final String SERVERIP = "192.168.X.X";
public static final int SERVERPORT = 4444;
private ObjectOutputStream mBufferOut;
private ObjectInputStream mBufferIn;
Socket socket;
InetAddress serverAddr;
boolean mRun;
Object msg;
public Integer command;
#Override
public IBinder onBind(Intent intent) {
return myBinder;
}
private final IBinder myBinder = new LocalBinder();
public class LocalBinder extends Binder {
public SocketService getService() {
return SocketService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
}
public void IsBoundable(){
Toast.makeText(this,"is boundable", Toast.LENGTH_LONG).show();
}
public void sendMessage(String message) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(message);
mBufferOut.flush();
}
}
public void sendMessage(Message message) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(message);
mBufferOut.flush();
}
}
public void sendMessage(User user) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(user);
mBufferOut.flush();
}
}
public void sendMessage(int command) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeInt(command);
mBufferOut.flush();
}
}
#Override
public int onStartCommand(Intent intent,int flags, int startId){
super.onStartCommand(intent, flags, startId);
System.out.println("I am in on start");
Runnable connect = new connectSocket();
new Thread(connect).start();
return START_STICKY;
}
public void stopClient() throws IOException{
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mBufferIn = null;
mBufferOut = null;
socket.close();
}
class connectSocket implements Runnable {
#Override
public void run() {
mRun = true;
try {
socket = new Socket(serverAddr, SERVERPORT);
try {
mBufferOut = new ObjectOutputStream(socket.getOutputStream());
mBufferIn = new ObjectInputStream(socket.getInputStream());
while(mRun){
switch(command.intValue()){
case Constants.ADD_MESSAGE:
msg = (Message) mBufferIn.readObject(); // send message to Activity
break;
}
}
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
try {
socket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
}
Some guidance / examples would be greatly appreciated
I am sending you mine, hope it will help :
class SocketRequestHandler extends Thread {
static String EOF = "<EOF>";
TCPResponseModel tcpResponseDS;
Activity activity;
boolean doSkip = false;
String responseStringComplete = "";
Socket clientSocekt;
OutputStream clientSocketOutputStream;
PrintWriter clinetSocketPrintWriter;
DataInputStream clientSocketInputStream;
private SocketRequestHandler(TCPResponseModel tcpResponseDS, Activity activity, SaloonListener listener) {
this.tcpResponseDS = tcpResponseDS;
this.activity = activity;
this.listener = listener;
moreStores = tcpResponseDS.StoresFound;
}
public static SocketRequestHandler pingAll(Activity activity, TCPResponseModel tcpResponseDS, SaloonListener listener) {
SocketRequestHandler requestHandler = new SocketRequestHandler(tcpResponseDS, activity, listener);
requestHandler.start();
return requestHandler;
}
private void closeStreams() {
try {
clientSocekt.close();
clientSocketInputStream.close();
clinetSocketPrintWriter.close();
clientSocketOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
String pingingHost = "URL_TO_PING";
clientSocekt = new Socket(pingingHost, 12000);
clientSocketOutputStream = clientSocekt.getOutputStream();
clinetSocketPrintWriter = new PrintWriter(clientSocketOutputStream);
String firstPing = "{\"RequestId\":" + tcpResponseDS.RequestId + "}<EOF>";
clinetSocketPrintWriter.println(firstPing);
clinetSocketPrintWriter.flush();
byte[] bytes;
String pingStr = "";
clientSocketInputStream = new DataInputStream(clientSocekt.getInputStream());
while (true) {
bytes = new byte[1024];
clientSocketInputStream.read(bytes);
bytes = trim(bytes);
if (bytes.length > 0 && !doSkip) {
String newString = new String(bytes, "UTF-8");
String decoded = pingStr + newString;
pingStr = checkForMessage(decoded);
responseStringComplete += newString;
}
if (doSkip) {
break;
}
}
closeStreams();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.print(responseStringComplete);
}
}
}
To broadcast chat data just do :
msg = (Message) mBufferIn.readObject(); // Do code after this line
Intent localIntent = new Intent("CHAT_MESSAGE");
localIntent.putExtra("message", msg);
LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
Now in the activity where you are showing the chat list you can do
class ReceiveMessages extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals("CHAT_MESSAGE")) {
runOnUiThread(new Runnable() {
#Override
public void run() {
String chatMessage = getIntent().getStringExtra("message");
//get data from intent and update your chat list.
}
});
}
}
}
ReceiveMessages myReceiver;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your code
myReceiver = new ReceiveMessages();
}
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver,
new IntentFilter("CHAT_MESSAGE"));
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
}
public class AsyncHttpClient {
public AsyncHttpClient() {
}
public static class SocketIORequest {
private String mUri;
private String mEndpoint;
private List<BasicNameValuePair> mHeaders;
public SocketIORequest(String uri) {
this(uri, null);
}
public SocketIORequest(String uri, String endpoint) {
this(uri, endpoint, null);
}
public SocketIORequest(String uri, String endpoint, List<BasicNameValuePair> headers) {
mUri = Uri.parse(uri).buildUpon().encodedPath("/socket.io/1/").build().toString();
mEndpoint = endpoint;
mHeaders = headers;
}
public String getUri() {
return mUri;
}
public String getEndpoint() {
return mEndpoint;
}
public List<BasicNameValuePair> getHeaders() {
return mHeaders;
}
}
public static interface StringCallback {
public void onCompleted(final Exception e, String result);
}
public static interface WebSocketConnectCallback {
public void onCompleted(Exception ex, WebSocketClient webSocket);
}
public void executeString(final SocketIORequest socketIORequest, final StringCallback stringCallback) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
AndroidHttpClient httpClient = AndroidHttpClient.newInstance("android-websockets-2.0");
HttpPost post = new HttpPost(socketIORequest.getUri());
addHeadersToRequest(post, socketIORequest.getHeaders());
try {
HttpResponse res = httpClient.execute(post);
String responseString = readToEnd(res.getEntity().getContent());
if (stringCallback != null) {
stringCallback.onCompleted(null, responseString);
}
} catch (IOException e) {
if (stringCallback != null) {
stringCallback.onCompleted(e, null);
}
} finally {
httpClient.close();
httpClient = null;
}
return null;
}
private void addHeadersToRequest(HttpRequest request, List<BasicNameValuePair> headers) {
if (headers != null) {
Iterator<BasicNameValuePair> it = headers.iterator();
while (it.hasNext()) {
BasicNameValuePair header = it.next();
request.addHeader(header.getName(), header.getValue());
}
}
}
}.execute();
}
private byte[] readToEndAsArray(InputStream input) throws IOException {
DataInputStream dis = new DataInputStream(input);
byte[] stuff = new byte[1024];
ByteArrayOutputStream buff = new ByteArrayOutputStream();
int read = 0;
while ((read = dis.read(stuff)) != -1) {
buff.write(stuff, 0, read);
}
return buff.toByteArray();
}
private String readToEnd(InputStream input) throws IOException {
return new String(readToEndAsArray(input));
}
I am working on an android chat application based on sockets. I am using the following code to implement this:
NetClient.java
public class NetClient {
/**
* Maximum size of buffer
*/
public static final int BUFFER_SIZE = 2048;
private Socket socket = null;
private PrintWriter out = null;
private BufferedReader in = null;
private String host = null;
private int port = 3000;
// private int port;
/**
* Constructor with Host, Port
*
* #param host
* #param port
*/
public NetClient(String host, int port) {
this.host = host;
this.port = port;
}
private void connectWithServer() {
Log.e("Server", "Connecting with server");
try {
if (socket == null) {
System.out.println("Socket is null");
socket = new Socket(this.host, this.port);
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void disConnectWithServer() {
Log.e("Server", "Disconnecting with server");
if (socket != null) {
if (socket.isConnected()) {
try {
in.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void sendDataWithString(String message) {
Log.e("Send data", "Sendind data to server");
if (message != null) {
connectWithServer();
out.write(message);
out.flush();
}
}
public String receiveDataFromServer() {
Log.e("Receive data", "Receivind data from the server");
try {
String message = "";
int charsRead = 0;
char[] buffer = new char[BUFFER_SIZE];
while ((charsRead = in.read(buffer)) != -1) {
message += new String(buffer).substring(0, charsRead);
}
//Log.e("ServerResponse", message);
disConnectWithServer(); // disconnect server
return message;
} catch (IOException e) {
return "Error receiving response: " + e.getMessage();
}
}
}
ChatActivity.java
public class ChatActivity extends Activity {
private EditText edtMsg;
private Button btnSend;
private String serverIpAddress = "192.168.2.250";
private int port = 3000;
private boolean connected = false;
private Handler handler = new Handler();
private BufferedReader in = null;
private PrintWriter out = null;
public static final int BUFFER_SIZE = 2048; // Max. size of buffer
private Socket socket = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
edtMsg = (EditText) findViewById(R.id.edtMessage);
btnSend = (Button) findViewById(R.id.btnSendMessage);
btnSend.setOnClickListener(connectListener);
}
private View.OnClickListener connectListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"clicked",Toast.LENGTH_LONG).show();
Log.e("Button", "Button clicked");
if (!connected) {
if (!serverIpAddress.equals("")) {
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
};
public class ClientThread implements Runnable {
public void run() {
NetClient nc = new NetClient(serverIpAddress, port);
String message = edtMsg.getText().toString().trim();
Log.e("Msg", message);
nc.sendDataWithString(message);
String response = nc.receiveDataFromServer();
Log.e("Server Response ", response);
}
}
}
I am not able to verify whether the data has been posted to server or not as i am getting unexpected result from the server.
Logcat
E/Server Response﹕ [ 12-01 14:56:01.313 302: 1017 V/qcbassboost ]
I think i am doing some mistake in the use of socket.Please help me to resolve the issue.
i have this code in android .my code is for reply to multicast msg.it work normaly when i open this application for first.but i use the button back for android and i open for second,this application work more than one and reply more than one reponse .
public class MainActivity extends Activity {
TextView info, infoip, msg;
String message = "";
ServerSocket serverSocket;
String s;
String ipserver;
String replyip;
int i;
int j;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
info = (TextView) findViewById(R.id.info);
infoip = (TextView) findViewById(R.id.infoip);
msg = (TextView) findViewById(R.id.msg);
i=0;
j=1;
infoip.setText(getIpAddress());
WifiManager manager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
WifiInfo infor =manager.getConnectionInfo();
String addr=infor.getMacAddress();
this.s=addr;
Thread t = new Thread (new SocketServerThread());
if(!t.isAlive()){
t.start();
}
}
#Override
protected void onRestart(){
}
#Override
protected void onDestroy() {
super.onDestroy();
i=1;
j=0;
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerThread extends Thread {
static final int SocketServerPORT = 7000;
int count = 0;
#Override
public void run() {
try {
serverSocket = new ServerSocket(SocketServerPORT);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
info.setText("\n+I'm waiting here: "
+ serverSocket.getLocalPort()+"\n \n");
}
});
while (true) {
MulticastSocket sock = new MulticastSocket(12345);
InetAddress addr = InetAddress.getByName("224.0.0.1");
sock.joinGroup(addr);
DatagramPacket packet;
byte [] buffer= new byte[256];
packet = new DatagramPacket(buffer, buffer.length);
sock.receive(packet);
String Message = new String (packet.getData(),0,packet.getLength());
replyip =packet.getSocketAddress().toString().substring(0, 13);
message+=Message+replyip;
sock.close();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(replyip, count);
if(i==0 )
{
socketServerReplyThread.run();
}
if(j==0){
socketServerReplyThread.run();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerReplyThread extends Thread {
String ips;
SocketServerReplyThread(String ip, int c) {
ips=ip;
}
#Override
public void run() {
try {
Socket s=new Socket(ips.toString(),12345);
DataOutputStream dos =new DataOutputStream(s.getOutputStream());
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String a = telephonyManager.getDeviceId();
dos.writeUTF(a);
dos.flush();
dos.close();
s.close();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message += "Something wrong! " + e.toString() + "\n";
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
}
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
}
When you press the back button your Application is still in-memory (verify with "adb shell ps"). When you start it again your onCreate gets called. Now you have two instances of SocketServerThread consuming the incoming connections.
Android destroys and recreates the Activity for lots of reasons you might not expect, for example when you rotate the screen. So you have to be careful about keeping data in an Activity.
You should move your networking code out of the Activity and into its own class. Use a singleton or factory pattern to make sure there is only one SocketServerThread.
The problem here is while(true) line in your thread's run method. As many times Activity is created, new Thread is being created and its being executed in infinite loop. If you launch app "n" times, n threads will be created.
Note that socketServerReplyThread.run(); call does not starts a Thread. Its a simple method call.
isAlive check in below code is use-less as a new Thread object has created above it.
Thread t = new Thread(new SocketServerThread());
if (!t.isAlive()) {
t.start();
}
To fix this issue, you can have a flag to check whether activity is destroyed or not. and run loop till activity is destroyed. This will make sure that Thread will have no task once activity is destroyed.
while(isDestroyed){
// do task
}
protected void onDestroy() {
super.onDestroy();
isDestroyed = true;
}
I have edited your code below to make sure that multiple threads are not created.
public class MainActivity extends Activity {
TextView info, infoip, msg;
String message = "";
ServerSocket serverSocket;
String s;
String ipserver;
String replyip;
int i;
int j;
private boolean mIsDestroyed = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
info = (TextView) findViewById(R.id.info);
infoip = (TextView) findViewById(R.id.infoip);
msg = (TextView) findViewById(R.id.msg);
i=0;
j=1;
infoip.setText(getIpAddress());
WifiManager manager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
WifiInfo infor =manager.getConnectionInfo();
String addr=infor.getMacAddress();
this.s=addr;
Thread t = new Thread (new SocketServerThread());
if(!t.isAlive()){
t.start();
}
}
#Override
protected void onRestart(){
}
#Override
protected void onDestroy() {
super.onDestroy();
mIsDestroyed = true;
i=1;
j=0;
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerThread extends Thread {
static final int SocketServerPORT = 7000;
int count = 0;
#Override
public void run() {
try {
serverSocket = new ServerSocket(SocketServerPORT);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
info.setText("\n+I'm waiting here: "
+ serverSocket.getLocalPort()+"\n \n");
}
});
while (mIsDestroyed == false) {
MulticastSocket sock = new MulticastSocket(12345);
InetAddress addr = InetAddress.getByName("224.0.0.1");
sock.joinGroup(addr);
DatagramPacket packet;
byte [] buffer= new byte[256];
packet = new DatagramPacket(buffer, buffer.length);
sock.receive(packet);
String Message = new String (packet.getData(),0,packet.getLength());
replyip =packet.getSocketAddress().toString().substring(0, 13);
message+=Message+replyip;
sock.close();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(replyip, count);
if(i==0 )
{
socketServerReplyThread.run();
}
if(j==0){
socketServerReplyThread.run();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerReplyThread extends Thread {
String ips;
SocketServerReplyThread(String ip, int c) {
ips=ip;
}
#Override
public void run() {
try {
Socket s=new Socket(ips.toString(),12345);
DataOutputStream dos =new DataOutputStream(s.getOutputStream());
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String a = telephonyManager.getDeviceId();
dos.writeUTF(a);
dos.flush();
dos.close();
s.close();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message += "Something wrong! " + e.toString() + "\n";
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
}
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
}
Try with Singleton pattern as mentioned below:
public class MySingleton implements Runnable {
private static MySingleton sInstance;
private boolean mIsThreadStarted = false;
// Use this method to access object of this class. Only single object of
// this class will be created and thread will be started only once.
public static synchronized MySingleton getInstance() {
if (sInstance == null) {
sInstance = new MySingleton();
}
return sInstance;
}
private MySingleton() {
// Remove below call if you want start it later.
startThread();
}
// Call this method whenever thread is to be started.
public void startThread() {
if (mIsThreadStarted) {
// Already started.
return;
}
Thread t = new Thread(this);
t.start();
mIsThreadStarted = true;
}
#Override
public void run() {
// Your logic here, which should be running continuously.
while (true) {
// This loop will be running continuously till the app is running.
// You will need to Implement Callback/Listener mechanism to pass
// events to Activity.
}
}
}