关于Android套接字编程的2个问题

关于Android套接字编程的2个问题,android,Android,我已经在互联网上找到了一些套接字编程的例子,并且正在尝试为一个支持以太网的Arduino服务器构建我自己的Android客户端。然而,我有两个问题。 首先,我的主要活动的代码: package com.domiflichi.TesterProject; import java.io.BufferedWriter; // output import java.io.BufferedReader; // input import java.io.InputStreamReader; // inpu

我已经在互联网上找到了一些套接字编程的例子,并且正在尝试为一个支持以太网的Arduino服务器构建我自己的Android客户端。然而,我有两个问题。 首先,我的主要活动的代码:

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;
}
}
}
}
所以我的两个问题是:

  • 我不知道如何让我的按钮与我向服务器发送命令的套接字交互。连接后,我有(4)个按钮,需要通过套接字发送各种命令(在单独的线程中运行,通过单击我的“连接”按钮启动)。(查找“//CODE HERE for STATUS REQUEST BUTTON?”注释,了解我希望将各种按钮的代码放在哪里)

  • 我得把车开走

    'handler.post(新的Runnable(){'

  • 我的主循环中的代码块:

    (while ((line = r.readLine()) != null) {
    total.append(line);
    Log.d("Server response", line.toString());
    }
    
    然而,当我这样做,并改变:

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

    (因为我一次只想读一行), Eclipse发出以下消息: 无法在其他方法中定义的内部类内引用非最终变量行

    如果我试图改变上面的线…: 弦线; 到 静态弦线

    Eclipse在下一行抱怨:

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

    说: 可能已经指定了最终的局部变量行


    我甚至不敢相信我已经走到了这一步,因为我是一个完全的新手,但现在我遇到了麻烦。

    关于你的第二个问题:创建一个新的
    final
    用于你的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);
                }
            }
        });
    }
    
    关于你的第一个问题: 您选择了一个相当复杂的任务。您的线程需要检查您从外部设置的一些条件,以便线程可以决定下一步需要执行的操作。从这些按钮中,您可以更改,例如,如果无需执行任何操作,则为0;如果要打开灯,则为1;等等

    您的线程将检查该值,将其重置为0(在一个
    .getAndSet(0)
    中),然后执行他应该执行的操作

    编辑:这就是它的样子

    线程

    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);
        }
    }
    
    您的活动

    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);
                }
            });
        }
    }
    

    谢谢。第一个问题:完成,没有问题了。谢谢。不过,对于我的第二个问题,谢谢你的想法/解决方案。我正在尝试实现AtomicInteger,但我认为我做错了什么。对不起,这个评论不是很友好……我将使用“回答你的问题”链接。这不是一个不友好的评论:)请看编辑,也许这能更好地解释它。嗨@zapl,你指的是什么?嘿,看起来我的原始帖子是由@Lucifer编辑的?为什么?编辑了什么?我还有一个新问题…请看下面我的最新帖子…我刚刚注意到你在@zapl中添加了一些代码…如果我能找到答案,也许这会对我有所帮助。谢谢。
    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);
                }
            });
        }
    }