I would like to modify dynamically an ImageView (setImageResource) in ServerSocket
I used :
public class MainActivity extends AppCompatActivity {
private SocketServer server;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
server = new SocketServer(MainActivity.this);
}
}
public class SocketServer {
private final Context context;
public SocketServer(Context context) {
this.context = context;
new Thread(new SocketServerThread()).start();
}
private class SocketServerThread implements Runnable {
private String read;
private BufferedInputStream reader = null;
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress("192.168.1.1", 11000));
while (true) {
Socket socket;
socket = serverSocket.accept();
//On attend la demande du client
reader = new BufferedInputStream(socket.getInputStream());
read = Strings.getBuffered(reader);
((Activity) context).runOnUiThread(new Runnable() {
final ImageView ls_fp = (ImageView) ((Activity) context).findViewById(R.id.ls_fp);
#Override
public void run() {
if(read != "1")
ls_fp.setImageResource(R.mipmap.ls_fp_light);
else
ls_fp.setImageResource(R.mipmap.ls_fp);
}
});
}
} catch (IOException e) {
Log.e(Log.TAG.SOCKETSERVER, "SocketServerThread", e);
}
}
}
}
And this code work perfectly fine
But, when in change to another activity and i rerun activity base, the image source not change.
Could you help me ?
Related
I called postValue() but MutableLivdata does not update its value.
When I print Log in UserInfoViewModel at setNetworkObj() and setUserName(), value from parameter nothing wrong(parameter arrived well).
But userName.getValue() print null.
So I tried postValue() in Handler and runOnUiThread but nothing work either.
I'd really appreciate it if you could tell me how to figure it out.
this is my code..
UserInfoViewModel.java
public class UserInfoViewModel extends ViewModel {
private MutableLiveData<NetworkObj> networkObj = new MutableLiveData<>();
private MutableLiveData<String> userName = new MutableLiveData<>();
public MutableLiveData<NetworkObj> getNetworkObj() {
return networkObj;
}
public void setNetworkObj(NetworkObj networkObj) {
this.networkObj.postValue(networkObj);
}
public MutableLiveData<String> getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName.postValue(userName);
}
}
LoginActivity.java
public class LoginActivity extends AppCompatActivity {
private ActivityLoginBinding binding;
private UserInfoViewModel userInfoViewModel;
public Socket socket;
public ObjectInputStream ois;
public ObjectOutputStream oos;
private NetworkUtils networkUtils;
private NetworkObj networkObj;
private String userName ="";
final String ip_addr = "10.0.2.2"; // Emulator PC의 127.0.0.1
final int port_no = 30000;
Handler mHandler = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
binding = ActivityLoginBinding.inflate(getLayoutInflater());
super.onCreate(savedInstanceState);
setContentView(binding.getRoot());
userInfoViewModel = new ViewModelProvider(this).get(UserInfoViewModel.class);
mHandler = new Handler();
binding.btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
userName = binding.etName.getText().toString();
new Thread() {
public void run() {
try {
socket = new Socket(ip_addr, port_no);
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
networkObj = new NetworkObj(socket, ois, oos);
networkUtils = new NetworkUtils(networkObj);
mHandler.post(new Runnable() {
#Override
public void run() {
userInfoViewModel.setNetworkObj(networkObj);
userInfoViewModel.setUserName(userName);
}
});
ChatMsg obj = new ChatMsg(userName, "100", "Hello");
networkUtils.sendChatMsg(obj, networkObj);
startMainActivity();
} catch (IOException e) {
Log.w("Login", e);
}
}
}.start();
}
});
}
public void startMainActivity() {
startActivity(new Intent(this, MainActivity.class));
}
}
I am having a problem with creating a socket and sending messages from an android app to a raspberry pi. I used this example from the following site: http://android-er.blogspot.nl/2016/05/android-client-example-2-communicate.html , this to understand how sockets work. But while I use AsyncTask, I still get an android.os.NetworkOnMainThreadException. This is my MainActivity:
public class MainActivity extends AppCompatActivity {
EditText editTextAddress, editTextPort, editTextMsg;
Button buttonConnect, buttonDisconnect, buttonSend;
TextView textViewState, textViewRx;
ClientHandler clientHandler;
ClientThread clientThread;
#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);
editTextMsg = (EditText) findViewById(R.id.msgtosend);
buttonConnect = (Button) findViewById(R.id.connect);
buttonDisconnect = (Button) findViewById(R.id.disconnect);
buttonSend = (Button)findViewById(R.id.send);
textViewState = (TextView)findViewById(R.id.state);
textViewRx = (TextView)findViewById(R.id.received);
buttonDisconnect.setEnabled(false);
buttonSend.setEnabled(false);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonDisconnect.setOnClickListener(buttonDisConnectOnClickListener);
buttonSend.setOnClickListener(buttonSendOnClickListener);
clientHandler = new ClientHandler(this);
}
View.OnClickListener buttonConnectOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View arg0) {
MainActivity.this.startService(new Intent(MainActivity.this,
ClientThread.class));
clientThread = new ClientThread(
editTextAddress.getText().toString(),
Integer.parseInt(editTextPort.getText().toString()),
clientHandler);
clientThread.execute();
buttonConnect.setEnabled(false);
buttonDisconnect.setEnabled(true);
buttonSend.setEnabled(true);
}
};
View.OnClickListener buttonDisConnectOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(clientThread != null){
clientThread.setRunning(false);
}
}
};
String msgToSend;
View.OnClickListener buttonSendOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(clientThread != null){
msgToSend = editTextMsg.getText().toString();
clientThread.txMsg(msgToSend);
}
}
};
private void updateState(String state){
textViewState.setText(state);
}
private void updateRxMsg(String rxmsg){
textViewRx.append(rxmsg + "\n");
}
private void clientEnd(){
clientThread = null;
textViewState.setText("clientEnd()");
buttonConnect.setEnabled(true);
buttonDisconnect.setEnabled(false);
buttonSend.setEnabled(false);
}
public static class ClientHandler extends Handler {
public static final int UPDATE_STATE = 0;
public static final int UPDATE_MSG = 1;
public static final int UPDATE_END = 2;
private MainActivity parent;
public ClientHandler(MainActivity parent) {
super();
this.parent = parent;
}
#Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_STATE:
parent.updateState((String)msg.obj);
break;
case UPDATE_MSG:
parent.updateRxMsg((String)msg.obj);
break;
case UPDATE_END:
parent.clientEnd();
break;
default:
super.handleMessage(msg);
}
}
}
}
This the ClientThread.java code:
public class ClientThread extends AsyncTask<Void, Void, Void>{
String dstAddress;
int dstPort;
private boolean running;
MainActivity.ClientHandler handler;
Socket socket;
PrintWriter printWriter;
BufferedReader bufferedReader;
public ClientThread(String addr, int port, MainActivity.ClientHandler handler) {
super();
dstAddress = addr;
dstPort = port;
this.handler = handler;
}
public void setRunning(boolean running){
this.running = running;
}
private void sendState(String state){
handler.sendMessage(
Message.obtain(handler,
MainActivity.ClientHandler.UPDATE_STATE, state));
}
public void txMsg(String msgToSend){
if(printWriter != null){
printWriter.println(msgToSend);
}
}
#Override
protected Void doInBackground(Void... arg0) {
System.out.println("In doinbackground");
sendState("connecting...");
running = true;
try {
socket = new Socket(dstAddress, dstPort);
sendState("connected");
OutputStream outputStream = socket.getOutputStream();
printWriter = new PrintWriter(outputStream, true);
InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader =
new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
while (running) {
//bufferedReader block the code
String line = bufferedReader.readLine();
if (line != null) {
handler.sendMessage(
Message.obtain(handler,
MainActivity.ClientHandler.UPDATE_MSG, line));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (printWriter != null) {
printWriter.close();
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
handler.sendEmptyMessage(MainActivity.ClientHandler.UPDATE_END);
return null;
}
}
This is the error I'm getting:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.zerocj.projectsocked, PID: 2415
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
at java.net.SocketOutputStream.write(SocketOutputStream.java:157)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at java.io.PrintWriter.newLine(PrintWriter.java:482)
at java.io.PrintWriter.println(PrintWriter.java:629)
at java.io.PrintWriter.println(PrintWriter.java:740)
at com.example.zerocj.projectsocked.ClientThread.txMsg(ClientThread.java:47)
at com.example.zerocj.projectsocked.MainActivity$3.onClick(MainActivity.java:85)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22260)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
You're calling your txMsg() method from a click listener which runs on the UI thread. And this method seems to be writing to a Writer that wired up to a socket.
If your wanna exchange messages back and forth between background thread and UI thread, maybe a better idea that an AsyncTask would be a Thread with Looper and handlers to pass the messages along from one thread to the other.
Please check your stack trace. It says use strict mode in your code
int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT > 8)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
// Where you get exception write that code inside this.
}
Thanks hope this help you.
I'm trying for sometime now and I cant figure it out why this is not working.
CLIENT:
public class MainActivity extends AppCompatActivity {
private Socket socket;
public static final int PORT = 6000;
public static final String server_IP = "192.168.2.30";
public String mensagem = null;
public String mensagem_final = null;
Button btn_conetar;
TextView txt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_conetar = (Button) findViewById(R.id.btn_conetar);
txt = (TextView) findViewById(R.id.txt);
Thread t = new Thread() {
public void run() {
try {
while(!isInterrupted())
{
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
txt.setText(mensagem_final);
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
}
public void onClick(View view)
{
new Thread((new ClientThread())).start();
//Intent i = new Intent(MainActivity.this,Main2Activity.class);
// startActivity(i);
}
//Thread que inicia o socket
class ClientThread implements Runnable
{
#Override
public void run() {
try
{
InetAddress serveradress = InetAddress.getByName(server_IP);
Log.e("TCP","A conetar...");
socket = new Socket(serveradress,PORT);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((mensagem = in.readLine()) != null)
{
mensagem_final += mensagem;
}
if(in.readLine() == null)
{
Log.e("TCP","Nao tem mensagens");
}
Log.e("MSG",mensagem);
socket.close();
}
catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
Server:
Servidor servidor = new Servidor();
servidor.serverthread();
class Servidor
{
public void serverthread()
{
Thread serverthread = new Thread(server);
serverthread.Start();
}
public void server()
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
TcpListener tcplistener = new TcpListener(IPAddress.Any, 6000);
tcplistener.Start();
TcpClient tcpclient = tcplistener.AcceptTcpClient();
byte[] data = new byte[1024];
NetworkStream ns = tcpclient.GetStream();
string welcome = "Ola";
data = Encoding.ASCII.GetBytes(welcome);
ns.Write(data, 0, data.Length);
}
}
Any idea why I cant receive the string "Ola" in my android application? It doesnt give me any error, it just doesnt do anything.
My internet's default adress is 192.168.2.1.
Good links are also welcome.
MainActivity.java
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client();
try {
client.connect("192.168.1.10",5555);
} catch (IOException e) {
e.printStackTrace();
}
}
public void displayServerAnswer(String answer){
TextView textView = (TextView)findViewById(R.id.mainTextView);
textView.setText(answer);
}
...
Client.java
import java.net.Socket;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Observable;
public class Client extends Observable implements Runnable {
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
private boolean connected;
private int port=5555; //default port
private String hostName="localhost";//default host name
public Client() {
connected = false;
}
public void connect(String hostName, int port) throws IOException {
if(!connected)
{
this.hostName = hostName;
this.port = port;
socket = new Socket(hostName,port);
//get I/O from socket
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream(),true);
connected = true;
//initiate reading from server...
Thread t = new Thread(this);
t.start(); //will call run method of this class
}
}
public void sendMessage(String msg) throws IOException
{
if(connected) {
pw.println(msg);
} else throw new IOException("Not connected to server");
}
public void run() {
String msg = ""; //holds the msg recieved from server
try {
while(connected && (msg = br.readLine())!= null)
{
//In Here I want to call MainActivity.displayServerAnswer()
//notify observers//
this.setChanged();
//notify+send out recieved msg to Observers
this.notifyObservers(msg);
}
}
catch(IOException ioe) { }
finally { connected = false; }
}
...
}
In the place I specified, I want to be able to display the server answer.
How can I get access to MainActivity instance that created client object, in order to call its method?
#hopia answer is pretty good. you also can implement the Listener Design pattern
public class Client extends Observable implements Runnable {
public interface ClientListener {
public void onAction();
}
private ClientListener mListener;
public Client(ClientListener listener) {
mListener = listener;
}
public class MainActivity extends ActionBarActivity implements ClientListener {
#Override
public void onAction(){
....do whatever you need
}
...
}
You can pass an acvtivity reference to your client in either a constructor or a set accessor method.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(this);
try {
client.connect("192.168.1.10",5555);
} catch (IOException e) {
e.printStackTrace();
}
}
And in your java object:
MainActivity activity;
public Client(MainActivity activity) {
connected = false;
this.activity = activity;
}
...
public void run() {
String msg = ""; //holds the msg recieved from server
try {
while(connected && (msg = br.readLine())!= null)
{
//In Here I want to call MainActivity.displayServerAnswer()
activity.displayServerAnswer();
//notify observers//
this.setChanged();
//notify+send out recieved msg to Observers
this.notifyObservers(msg);
}
}
catch(IOException ioe) { }
finally { connected = false; }
}
How about passing the activity instance as an argument to the Client's constructor?
// MainActivity
Client client = new Client(this);
// Client
public Client(Activity activity) {
this.activity = activity;
connected = false;
}
I am working on a chat application. Currently i did like that when i open the ChatActvity, all sockets are registered and the chatting works... Now i want to change the coding structure.. I want to open the sockets in a class, not in Activity class and i need to add a listener to that class. How i implement this..?
private class Chatroom {
private static void initialise() {
// Initialising the sockets and registering listeners to each socket
}
}
I want to notify in my activity class when the socket listeners in the Chatroom class get called..
here is probably what you need :
public class RequestSender extends AsyncTask<String, Void, String> {
private final static String serverIP = "192.168.1.1";
private final static Integer serverPort = 1234;
private ServerResponseListener listener = null;
public void setServerResponseListener(ServerResponseListener listener){
this.listener=listener;
}
public interface ServerResponseListener {
public void onResponseReceive(String response);
}
#Override
protected String doInBackground(String... params) {
Socket socket = null;
try {
socket = new Socket(serverIP, serverPort);
} catch (IOException e) {
// return "server is unreachable" message or something
}
PrintWriter requestWriter = new PrintWriter(socket.getOutputStream());
BufferedReader resultReader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String request = params[0] //for example
requestWriter.println(request);
requestWriter.flush();
String result = null;
while ((result = resultReader.readLine()) != null) {}
return result;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
listener.onResponseReceive(result);
}
}
here is example how to execute AsynchTask from Activity :
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestSender requestSender = new RequestSender();
requestSender.setServerResponseListener(new RequestSender.ServerResponseListener(){
#override
public void onResponseReceive(String response){
//
}
});
requestSender.execute("message");
}
}
read this : http://developer.android.com/reference/android/os/AsyncTask.html