2 questions about socket programming with Android

I gave examples that I found on the Internet for socket programming, and I'm trying to create my own Android client for an Arduino server with Ethernet support. However, I have 2 problems. Firstly, the code for my main activity:

package com.domiflichi.TesterProject; import java.io.BufferedWriter; // output import java.io.BufferedReader; // input import java.io.InputStreamReader; // input import java.io.OutputStreamWriter; // output import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class TesterProjectMain extends Activity implements OnClickListener { private Button connectPhones; private TextView myTextView; // represents the 'status text' private String serverIpAddress = ""; private boolean connected = false; private Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.client); connectPhones = (Button) findViewById(R.id.connect_phones); connectPhones.setOnClickListener(connectListener); connectPhones.setOnClickListener(this); myTextView = (TextView) findViewById(R.id.text1); } // This was created when using the 'implements OnClickListener' in the class public void onClick(View v) { if (v.getId() == R.id.connect_phones) { if (!connected) { serverIpAddress = "192.168.0.178"; if (!serverIpAddress.equals("")) { Thread cThread = new Thread(new ClientThread()); cThread.start(); connectPhones.setEnabled(false); // Once the button is pressed, disable it. :) } } } else if (v.getId() == R.id.status_req) { // CODE HERE FOR STATUS REQUEST BUTTON? } else if (v.getId() == R.id.cmd_toggle) { // CODE HERE FOR TOGGLE DOOR BUTTON? } else if (v.getId() == R.id.cmd_crack) { // CODE HERE FOR CRACK BUTTON? } else if (v.getId() == R.id.disconnect) { // CODE HERE FOR DISCONNECT BUTTON? } } public class ClientThread implements Runnable { public void run() { try { InetAddress serverAddr = InetAddress.getByName(serverIpAddress); Log.d("ClientActivity", "C: Connecting..."); Socket socket = new Socket(serverAddr, 23); connected = true; while (connected) { try { Log.d("ClientActivity", "C: Sending command."); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); out.println("mypass*"); Log.d("ClientActivity", "C: Sent."); BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream())); final StringBuilder total = new StringBuilder(); String line; while ((line = r.readLine()) != null) { total.append(line); Log.d("Server response", line.toString()); } handler.post(new Runnable() { public void run() { if (total.toString().contentEquals("status:open")) { myTextView.setText(R.string.status_open); } else { myTextView.setText(R.string.status_closed); } } }); connected = false; } catch (Exception e) { Log.e("ClientActivity", "S: Error", e); } } socket.close(); Log.d("ClientActivity", "C: Closed."); } catch (Exception e) { Log.e("ClientActivity", "C: Error", e); connected = false; } } } } 

So my 2 questions:

  • I do not know how to make my buttons interact with the socket, where I send commands to my server. After I connected, I have (4) buttons that should send various commands through the socket (which runs in a separate thread, which was launched by pressing the "connect" button I have). (Look for the link "// CODE HERE FOR STATEMENT APPLICATION REQUIREMENTS?", Where did I expect to put the code for the various buttons)

  • I need to move

    'handler.post (new Runnable () {'

block of code in my main loop:

 (while ((line = r.readLine()) != null) { total.append(line); Log.d("Server response", line.toString()); } 

However, when I do this and change:

 if (total.toString().contentEquals("status:open")) { 

to

 if (line.toString().contentEquals("status:open")) { 

(because I want to actually read only one line at a time), Eclipse complains about the following message: You cannot reference a non-finite variable string inside an inner class defined by another method.

And if I try to change the line above this ...: String; in a static line string;

Eclipse complains about the following line:

while ((line = r.readLine ())! = null) {

saying: The final local variable string may have already been assigned

I can’t even believe that I have reached the point that I am a complete beginner, but now I hit the wall.

+4
source share
1 answer

For your second question: create a new final to use in your runnable

 while ((line = r.readLine()) != null) { total.append(line); Log.d("Server response", line.toString()); final String status = line; handler.post(new Runnable() { public void run() { if (status.contentEquals("status:open")) { myTextView.setText(R.string.status_open); } else { myTextView.setText(R.string.status_closed); } } }); } 

For your first question: You have chosen a rather difficult task. Your topic should check some of the conditions that you set outside so that the thread can decide what it needs to do next. From these buttons you can change, for example. AtomicInteger , which is 0 if you do nothing, 1 if you want to turn on the light, 2 ... etc.

Your topic will check the value, reset to 0 (in one .getAndSet(0) ) and do what it should do.

Edit: how it will look

Topic

 public class LoopingNetworkThread extends Thread { public static final int TASK_END = -1; public static final int TASK_NOOP = 0; public static final int TASK_LIGHTS_ON = 1; public static final int TASK_LIGHTS_OFF = 2; private final AtomicInteger mNextTask = new AtomicInteger(0); /* Executed in this threads context */ @Override public void run() { openSocket(); int currentTask; while ((currentTask = mNextTask.getAndSet(TASK_NOOP)) != TASK_END) { switch (currentTask) { case TASK_LIGHTS_ON: sendLightsOn(); break; case TASK_LIGHTS_OFF: sendLightsOff(); break; default: keepAlive(); break; } // depending on your requirements sleep some time inbetween. try { Thread.sleep(100); } catch (InterruptedException e) { // ignore } } // the while ends once you set task to TASK_END closeSocket(); } private void openSocket() { } private void closeSocket() { } private void keepAlive() { } private void sendLightsOn() { } private void sendLightsOff() { } /* Executed in a different thread context */ public int setNextTask(int task){ // return what we overwrite here, maybe that is useful. return mNextTask.getAndSet(task); } } 

your activity

 public class YourActivity extends Activity { private LoopingNetworkThread mThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mThread = new LoopingNetworkThread(); View startButton = findViewById(R.id.button1); View stopButton = findViewById(R.id.button2); startButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mThread.start(); } }); stopButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mThread.setNextTask(LoopingNetworkThread.TASK_END); } }); } } 
+2
source

Source: https://habr.com/ru/post/1402144/


All Articles