this is my code.(actually copied from opensource)
package com.example.realtest;
import android.content.Context;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class MainActivity extends AppCompatActivity {
public TextView Toptext;
public Button StartButton;
public Button StopButton;
public Button ConnButton;
private Socket socket;
public TextView temphum;
// fixme: TAG
String TAG = "socketTest";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
temphum = (TextView)findViewById(R.id.temphum);
ConnButton = findViewById(R.id.button1);
StartButton = findViewById(R.id.button2);
StopButton = findViewById(R.id.button3);
final EditText ipNumber = findViewById(R.id.ipText);
Log.i(TAG, "Application createad");
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);
}
ConnButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), "Connect 시도", Toast.LENGTH_SHORT).show();
String addr = ipNumber.getText().toString().trim();
ConnectThread thread = new ConnectThread(addr);
//키보드 자동 내리기
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(ipNumber.getWindowToken(), 0);
thread.start();
}
});
// fixme: 버튼 ClickListener
StartButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
StartThread sthread = new StartThread();
StartButton.setEnabled(false);
StopButton.setEnabled(true);
sthread.start();
}
});
StopButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
StopThread spthread = new StopThread();
StartButton.setEnabled(true);
StopButton.setEnabled(false);
spthread.start();
}
});
}
// fixme: Start 버튼 클릭 시 데이터 송/수신.
class StartThread extends Thread{
int bytes;
public StartThread(){
}
public void run(){
// 데이터 수신
try {
Log.d(TAG, "데이터 수신 준비");
//TODO:수신 데이터(프로토콜) 처리
while (true) {
byte[] buffer = new byte[64];
InputStream input = socket.getInputStream();
bytes = input.read(buffer);
String sensor = new String(buffer);
Log.d(TAG, "data = " sensor);
}
}catch(IOException e){
e.printStackTrace();
Log.e(TAG,"수신 에러");
}
}
}
// fixme: Stop 버튼 클릭 시 데이터 송신.
class StopThread extends Thread{
public StopThread(){
}
public void run(){
// 데이터 송신
try {
String OutData = "AT STOP\n";
byte[] data = OutData.getBytes();
OutputStream output = socket.getOutputStream();
output.write(data);
Log.d(TAG, "AT STOP\\n COMMAND 송신");
} catch (IOException e) {
e.printStackTrace();
}
}
}
// fixme: Socket Connect.
class ConnectThread extends Thread {
String hostname;
public ConnectThread(String addr) {
hostname = addr;
}
public void run() {
try { //클라이언트 소켓 생성
int port = 9999;
socket = new Socket(hostname, port);
Log.d(TAG, "Socket 생성, 연결.");
Toptext = findViewById(R.id.text1);
runOnUiThread(new Runnable() {
@Override
public void run() {
InetAddress addr = socket.getInetAddress();
String tmp = addr.getHostAddress();
Toptext.setText(tmp " 연결 완료");
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_LONG).show();
ConnButton.setEnabled(false);
StartButton.setEnabled(true);
}
});
} catch (UnknownHostException uhe) { // 소켓 생성 시 전달되는 호스트(www.unknown-host.com)의 IP를 식별할 수 없음.
Log.e(TAG, " 생성 Error : 호스트의 IP 주소를 식별할 수 없음.(잘못된 주소 값 또는 호스트 이름 사용)");
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Error : 호스트의 IP 주소를 식별할 수 없음.(잘못된 주소 값 또는 호스트 이름 사용)", Toast.LENGTH_SHORT).show();
Toptext.setText("Error : 호스트의 IP 주소를 식별할 수 없음.(잘못된 주소 값 또는 호스트 이름 사용)");
}
});
} catch (IOException ioe) { // 소켓 생성 과정에서 I/O 에러 발생.
Log.e(TAG, " 생성 Error : 네트워크 응답 없음");
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Error : 네트워크 응답 없음", Toast.LENGTH_SHORT).show();
Toptext.setText("네트워크 연결 오류");
}
});
} catch (SecurityException se) { // security manager에서 허용되지 않은 기능 수행.
Log.e(TAG, " 생성 Error : 보안(Security) 위반에 대해 보안 관리자(Security Manager)에 의해 발생. (프록시(proxy) 접속 거부, 허용되지 않은 함수 호출)");
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Error : 보안(Security) 위반에 대해 보안 관리자(Security Manager)에 의해 발생. (프록시(proxy) 접속 거부, 허용되지 않은 함수 호출)", Toast.LENGTH_SHORT).show();
Toptext.setText("Error : 보안(Security) 위반에 대해 보안 관리자(Security Manager)에 의해 발생. (프록시(proxy) 접속 거부, 허용되지 않은 함수 호출)");
}
});
} catch (IllegalArgumentException le) { // 소켓 생성 시 전달되는 포트 번호(65536)이 허용 범위(0~65535)를 벗어남.
Log.e(TAG, " 생성 Error : 메서드에 잘못된 파라미터가 전달되는 경우 발생.(0~65535 범위 밖의 포트 번호 사용, null 프록시(proxy) 전달)");
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), " Error : 메서드에 잘못된 파라미터가 전달되는 경우 발생.(0~65535 범위 밖의 포트 번호 사용, null 프록시(proxy) 전달)", Toast.LENGTH_SHORT).show();
Toptext.setText("Error : 메서드에 잘못된 파라미터가 전달되는 경우 발생.(0~65535 범위 밖의 포트 번호 사용, null 프록시(proxy) 전달)");
}
});
}
}
}
@Override
protected void onStop() { //앱 종료시
super.onStop();
try {
socket.close(); //소켓을 닫는다.
} catch (IOException e) {
e.printStackTrace();
}
}
}
this code receives temperature and humidity data (like "temperature : 27 C, humidity 40%") from raspberrypi every 30 seconds.
i wanna show this data on textview, so i added textview(temphum) and used temphum.setText("data = " sensor);
to fill the textview with sensor data in this part
while (true) {
byte[] buffer = new byte[64];
InputStream input = socket.getInputStream();
bytes = input.read(buffer);
String sensor = new String(buffer);
Log.d(TAG, "data = " sensor);
temphum.setText("data = " sensor);
}
but when i run this code, an error occurs.
I think because I used temphum.setText("data = " sensor);
in while(true)
, java is puzzled.
I think i should consider remaining sensor data in textview cause it receives new data every 30 seconds.(deleting it or refreshing receiving part or somehow..)
actually I'm a newbie for coding, and I dont know how to make this code works well.
help me please.
CodePudding user response:
Let's start off with
if (SDK_INT > 8) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
NEVER DO THIS. What this does is allow all sorts of behavior that is actually illegal and will probably break your program. Without these lines, your program would immediately crash and tell you what you did wrong. With these lines, you see this.
In fact I'd go a step farther- any site or source that uses this code should not be trusted for anything. Use another place to learn from. They'll be teaching you bad habits at best.
The reason your data wasn't showing up is that you can't change UI elements on any thread other than the main thread. It doesn't work. Normally you get a crash which tells you that, but by turning off strict mode you got it to run- it just won't actually work. To do this, post a message to a handler on the UI thread and call setText there. And remove the strict mode setting so that in the future your program properly warns you of things like this.
CodePudding user response:
You should notice that changing the View (set value or sth.) is in the scope:
runOnUiThread(new Runnable() {
public void run() {
//Toptext.setText("네트워크 연결 오류");
....
temphum.setText("data = " sensor);
}
});
You can follow and try it. Also as @Gabe Sechan said please remove that code.