I started a project where I wanted to send some colors in hex to my Arduino, which then makes an LED Strip light in that color. But my problem is, whenever I try to send something to the Arduino, I get an error in Android studio thrown by NetworkOnMainThreadException:
android.os.NetworkOnMainThreadException
W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
W/System.err: at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
W/System.err: at java.net.SocketOutputStream.write(SocketOutputStream.java:157)
W/System.err: at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
W/System.err: at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
W/System.err: at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
W/System.err: at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
W/System.err: at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
W/System.err: at java.io.BufferedWriter.flush(BufferedWriter.java:254)
W/System.err: at java.io.PrintWriter.flush(PrintWriter.java:320)
W/System.err: at com.example.marnaut.arduinoledcontroller.TCPClient.sendMessage(TCPClient.java:51)
W/System.err: at com.example.marnaut.arduinoledcontroller.ShutdownAsyncTask.onProgressUpdate(ShutdownAsyncTask.java:49)
W/System.err: at com.example.marnaut.arduinoledcontroller.ShutdownAsyncTask.onProgressUpdate(ShutdownAsyncTask.java:7)
W/System.err: at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:687)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err: at android.os.Looper.loop(Looper.java:154)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6121)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
I got the code for the app on GitHub and transformed it a bit for my needs. I have red that a SocketOutputStream error could also mean the Arduino isn't receiving anything, but it does change color when I run the app, so it received the sent message. Also when I connect just normal with telnet to the Arduino with a pc, I am able to just normal change the color. I have also tried to change the method of sending the data from println to to just print or write, but neither helped. Can someone maybe help me for I keep getting this exception?
EDIT I have tried to add a new thread policy for the AsyncTask:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);
With that I got rid of the error message but I still get Errors from the handlers... What I also didn't mention is that I use the following 2 permissions:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
MainActivity:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final int CHANGED = 0;
public static final int SENDING = 1;
public static final int SENT = 2;
public static final int CONNECTING = 3;
public static final int ERROR = 4;
public static final int SHUTDOWN = 5;
Visualizer visual;
Handler mHandler;
private TextView redValue;
private TextView greenValue;
private TextView blueValue;
private SeekBar redSlider;
private SeekBar greenSlider;
private SeekBar blueSlider;
private Button sendBtn;
private String color = "000000";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case CHANGED:
Log.d(TAG, "Color changed.");
break;
case SENDING:
Log.d(TAG, "Sending data...");
break;
case SENT:
Log.d(TAG, "Data sent.");
break;
case CONNECTING:
Log.d(TAG, "Connecting...");
break;
case ERROR:
Log.d(TAG, "Error...");
break;
case SHUTDOWN:
Log.d(TAG, "Shutdown command recieved");
break;
}
}
};
redValue = (TextView) findViewById(R.id.redValue);
greenValue = (TextView) findViewById(R.id.greenValue);
blueValue = (TextView) findViewById(R.id.blueValue);
redSlider = (SeekBar) findViewById(R.id.redSlider);
greenSlider = (SeekBar) findViewById(R.id.greenSlider);
blueSlider = (SeekBar) findViewById(R.id.blueSlider);
sendBtn = (Button) findViewById(R.id.sendBtn);
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new ShutdownAsyncTask(mHandler).execute("");
}
});
redSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
redValue.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
greenSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
greenValue.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
blueSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
blueValue.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
TCP Client:
public class TCPClient {
private static final String TAG = "TCPClient";
private final Handler mHandler;
private String ipNumber, incomingMessage, command;
private BufferedReader in;
private PrintWriter out;
private MessageCallback listener = null;
private boolean mRun = false;
public TCPClient(Handler mHandler, String command, String ipNumber, MessageCallback listener) {
this.listener = listener;
this.ipNumber = ipNumber;
this.command = command;
this.mHandler = mHandler;
}
public void sendMessage(String message) {
try {
if (out != null && !out.checkError()) {
out.write(message);
out.flush();
mHandler.sendEmptyMessageDelayed(MainActivity.SENDING, 1000);
Log.d(TAG, "Sent Message: " + message);
}
} catch (Exception e) {
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 1000);
e.printStackTrace();
}
}
public void stopClient() {
Log.d(TAG, "Client stopped!");
mRun = false;
}
public void run() {
mRun = true;
try {
Log.d(TAG, "Connecting...");
InetAddress serverAddress = InetAddress.getByName(ipNumber);
mHandler.sendEmptyMessageDelayed(MainActivity.CONNECTING, 1000);
Socket socket = new Socket(serverAddress, 23);
Log.d(TAG, "Socket created with ip: " + ipNumber);
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d(TAG, "In/Out created");
this.sendMessage(command);
mHandler.sendEmptyMessageDelayed(MainActivity.SENDING, 2000);
while (mRun) {
incomingMessage = in.readLine();
if (incomingMessage != null && listener != null)
listener.callbackMessageReceiver(incomingMessage);
//incomingMessage = null;
}
Log.d(TAG, "Received Message: " + incomingMessage);
} catch (Exception e) {
Log.d(TAG, "Error", e);
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
} finally {
out.flush();
out.close();
in.close();
socket.close();
mHandler.sendEmptyMessageDelayed(MainActivity.SENT, 3000);
Log.d(TAG, "Socket Closed");
}
} catch (Exception e) {
Log.d(TAG, "Error in socket", e);
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
}
}
boolean isRunning() {
return mRun;
}
public interface MessageCallback {
void callbackMessageReceiver(String message);
}
}
AsyncTask:
public class MyAsyncTask extends AsyncTask<String, String, TCPClient> {
private static final String COMMAND = "0xFFFF00";
private TCPClient tcpClient;
private Handler mHandler;
private static final String TAG = "MyAsyncTask";
public MyAsyncTask(Handler mHandler){
this.mHandler = mHandler;
}
@Override
protected TCPClient doInBackground(String... params) {
Log.d(TAG, "In: do in background");
try{
tcpClient = new TCPClient(mHandler, COMMAND, "192.168.0.190", new TCPClient.MessageCallback() {
@Override
public void callbackMessageReceiver(String message) {
publishProgress(message);
}
});
} catch (NullPointerException e){
Log.d(TAG, "Caught null pointer exception");
e.printStackTrace();
} catch (Exception e) {
Log.d(TAG, "Cought sth weird");
e.printStackTrace();
}
tcpClient.run();
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
for (String value : values)
Log.d(TAG, "In progress update, values: " + value);
Log.d(TAG, "#Values: " + values.length);
if(values[0].equals("Welcome!")){
tcpClient.sendMessage("0x00FF00");
tcpClient.stopClient();
mHandler.sendEmptyMessageDelayed(MainActivity.CHANGED, 2000);
}else{
tcpClient.sendMessage("0xFF0000");
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
tcpClient.stopClient();
}
}
@Override
protected void onPostExecute(TCPClient result){
super.onPostExecute(result);
Log.d(TAG, "In on post execute");
if(result != null && result.isRunning()){
result.stopClient();
}
mHandler.sendEmptyMessageDelayed(MainActivity.SENT, 4000);
}
}