I'm setting up a TCP/IP communication between an android app and an ESP8266 module connected to Arduino uno. I'm using AT commands to set up the server as follows:
AT+CWMODE=1
AT+CIPMUX=1
AT+CIPSERVER=1,80
I get OK for each.
I want send an int to the app : 0 or 1 , the app read the int and then sends the text typed in the editText to the ESP8266
Now, here is my app code:
public class MainActivity extends AppCompatActivity {
TextView tv;
EditText txt;
EditText txt2;
Button b;
string response;
private static Socket s ;
private static PrintWriter printWriter;
String message="";
private static String ip="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b = (Button) findViewById(R.id.button);
txt = (EditText) findViewById(R.id.editText);
tv = (TextView) findViewById(R.id.textView) ;
txt2=(EditText)findViewById(R.id.editText2);
}
class myTask extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params)
{
try
{ s= new Socket(ip,80);
//READING THE INPUT
BufferedReader in = new BufferedReader(new
InputStreamReader(s.getInputStream()));
while(in!=null) {
response = in.readLine();
}
//SENDING THE MESSAGE
printWriter= new PrintWriter(s.getOutputStream());
printWriter.write(message);
printWriter.flush();
post_send();
// closing all connections
// printWriter.close();
// in.close();
// s.close();
}catch(IOException e)
{e.printStackTrace();}
return null;
}
}
public void send_text(View v)
{
message= txt.getText().toString();
ip=txt2.getText().toString();
myTask mt = new myTask();
mt.execute();
Toast.makeText(getApplicationContext(),"MT
LAUNCHED",Toast.LENGTH_LONG).show();
}
public void post_send(){
Toast.makeText(getApplicationContext(),response
,Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(),"Data
sent",Toast.LENGTH_LONG).show();
}
}
I have 1 button to create the socket and receive any data and then send a text.
When I click on the button I get the following message on the serial monitor:
0, connected
so I type:
AT+CIPSEND=0,4
I get :
SEND OK
but none of the toasts show
help me? What am I doing wrong ?
s = new Socket(ip, 80);
If you execute that code in the onClick() of an onClickListener you will get an NetworkOnMainThreadException. Which lets your app crash.
All internet code (also the connecting and reading) should be executed from a thread or AsyncTask.
Your writing is already in an AsyncTask. Which is the way to go.
Related
first of all excuse my english, because i am not good in english. I'm looking for a way to retrieve information in android send from a nodeJS server with socket io. I have the impression that it is a problem of version. my code compiles very well, I do not manage to retrieve the information contained in a JS object.
here is the server code
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var data ={"msg": "hello i am the server"};
io.on('connection',function(socket){
console.log('one user connected '+socket.id);
socket.on('message',function(obj){
console.log(obj.text);
socket.emit('take', data);
})
socket.on('disconnect',function(){
console.log('one user disconnected '+socket.id);
})
})
http.listen(3000,function(){
console.log('server listening on port 3000');
})
the information I'm looking for is 'data'
here is the java code I use, I prefer to put the whole code in case the problem is elsewhere
public class MainActivity extends AppCompatActivity {
private Socket socket;
public String ReceiveMsg ="message par defaut ";
{
try {
socket = IO.socket("http://192.168.43.168:3000");
socket.connect();
} catch (URISyntaxException e) {
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = (EditText) findViewById(R.id.editText);
TextView textView = (TextView) findViewById(R.id.textView);
Button but = (Button) findViewById(R.id.button);
socket.connect();
String msg = takemsg(editText);
sendMsg(msg);
socket.on("take", handleIncomingMessages);
textView.setText(getAz(ReceiveMsg));
}
public String takemsg(EditText editText){
String msg = "message par defaut ";
msg = editText.getText().toString();
return msg;
}
public void sendMsg(String msg ){
JSONObject obj = new JSONObject();
try{
obj.put("text", msg);
socket.emit("message", obj);
}catch (JSONException e){
}
}
private Emitter.Listener handleIncomingMessages = new Emitter.Listener(){
#Override
public void call(final Object... args){
runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
try {
ReceiveMsg = data.getString("msg");
} catch (JSONException e) {
}
}
});
}
};
}
First I think we need more data.
What are the outputs of the server? Is connecting well?, check if your code in android is running.
If it's not connecting try setting the port with opts
...
try {
IO.Options opts = IO.Options();
opts.port = 3000;
socket = IO.socket("http://192.168.43.168", opts);
socket.connect();
} catch (URISyntaxException e) {
...
check if your service is alive. for services exists some returns that allows to maintain your service working.
https://developer.android.com/reference/android/app/Service.html#START_STICKY
we must put in the manifest
<uses-permission android:name="android.permission.INTERNET" />
to allow the application to use the network
I am trying to communicate between a C# TCP server, and an Android TCP client. I am new to android so used the second part of this tutorial to create the android client:
http://www.myandroidsolutions.com/2012/07/20/android-tcp-connection-tutorial/#.V8uZISgrKUk
Everything works fine, and I can send little text messages between my phone and my computer, however this tutorial requires that the client app have the server IP hard coded into the program, and for obvious reasons this is going to cause issues if I actually wanted to make an app that uses this.
Outside of this tutorial I have added a second EditText ("#id/ipTxt") and a second button ("#id/setIp")
As I don't want to make anybody read through the whole tutorial, here are the important parts summarized:
Main Activity:
public class MyActivity extends Activity
{
private ListView mList;
private ArrayList<String> arrayList;
private MyCustomAdapter mAdapter;
private TCPClient mTcpClient;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
arrayList = new ArrayList<String>();
final EditText editText = (EditText) findViewById(R.id.editText);
Button send = (Button)findViewById(R.id.send_button);
//relate the listView from java to the one created in xml
mList = (ListView)findViewById(R.id.list);
mAdapter = new MyCustomAdapter(this, arrayList);
mList.setAdapter(mAdapter);
// connect to the server
new connectTask().execute("");
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = editText.getText().toString();
//add the text in the arrayList
arrayList.add("c: " + message);
//sends the message to the server
if (mTcpClient != null) {
mTcpClient.sendMessage(message);
}
//refresh the list
mAdapter.notifyDataSetChanged();
editText.setText("");
}
});
}
public class connectTask extends AsyncTask<String,String,TCPClient> {
#Override
protected TCPClient doInBackground(String... message) {
//we create a TCPClient object and
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//in the arrayList we add the messaged received from server
arrayList.add(values[0]);
// notify the adapter that the data set has changed. This means that new message received
// from server was added to the list
mAdapter.notifyDataSetChanged();
}
}
}
TCPClient class:
public class TCPClient {
private String serverMessage;
public static final String SERVERIP = "192.168.0.102"; //your computer IP address
public static final int SERVERPORT = 4444;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
PrintWriter out;
BufferedReader in;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TCPClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
* #param message text entered by client
*/
public void sendMessage(String message){
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
}
}
public void stopClient(){
mRun = false;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVERPORT);
try {
//send the message to the server
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.e("TCP Client", "C: Sent.");
Log.e("TCP Client", "C: Done.");
//receive the message which the server sends back
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
while (mRun) {
serverMessage = in.readLine();
if (serverMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(serverMessage);
}
serverMessage = null;
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
My theory would be to stop the connectTask process every time the "setIp" button is clicked and create a new one, but that seems like a very inefficient way to do it, plus I don't know how I would go about doing that :(
Any Ideas?
Change your SERVERIP and SERVERPORT constants into non-static variables instead, and then initialize them using additional input values to your TCPClient constructor, or as input parameters to AsyncTask.execute() (which will then be passed as input parameters to your doInBackground() method).
Don't call execute() until you have first determined those values, either from your app's stored configuration, or from the user in the UI.
When you do start a new task, save the object to a variable in your main code (which you are not currently doing). To cancel the connection, you can then call the AsyncTask.cancel() method on that variable. Make sure your connectTask.doInBackground() and TCPClient.run() code checks the AsyncTask.isCancelled() method periodically so they can exit as soon as possible when it returns true. This technique is mentioned in the AsyncTask documentation.
After the connectTask object finishes running, you can create a new one with different input values.
I'm using asynctask to make connection between client (runnning on my android device) and server(running on my pc). When i launch the app i have to click on button to connect them, and my server pc program should show me in console device if client is connected but doesn't appear; my android client doesn't connect to my pc server.
Android client:
public class MainActivity extends ActionBarActivity {
Button send;
EditText txt;
TextView testo;
String response = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
send = (Button) findViewById(R.id.send);
//txt = (EditText) findViewById(R.id.editText);
testo = (TextView) findViewById(R.id.textView1);
}
class AddStringTask extends AsyncTask<Void, String, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... unused) {
try {
Socket socketClient = new Socket("10.10.0.151",4321); //ipaddress of my pc server
} catch (UnknownHostException e) {
e.printStackTrace();
response = e.toString();
} catch (IOException e) {
e.printStackTrace();
response = e.toString();
}
testo.setText(response);
return (null);
}
#SuppressWarnings("unchecked")
#Override
protected void onProgressUpdate(String... item) {
}
#Override
protected void onPostExecute(Void unused) {
testo.setText(response);
}
}
public void buttonClick(View v){
new AddStringTask().execute();
}
}
Pc server:
public class Server {
public static Socket connection;
public static void main(String[] args) throws IOException {
System.out.println("Starting server on port number: 4321...");
ServerSocket server = new ServerSocket(4321);
while(true){
System.out.println("Waiting for clients...");
connection = server.accept();
System.out.println("Connected to: "+connection.getInetAddress().getHostAddress());
connection.close();
}
}
}
In my AndroidManifest.xml i've just added
<uses-permission android:name="android.permission.INTERNET"/>
If i launch client from pc in my server console i see the device connected but on android doesn't work..why?
Thanks
It's most likely the ip in the android side is wrong. use a private ip eg: 192.168.1.x. theese types of ip require you be on the same network. i think what you're trying to do is access the server from outside of the network and that requires port fkrwarding.
I want to use AsyncTask for receiving ArrayList's(in this case) from Java server. To be sure, that I received something from server I'm trying to display it with Toast.
The Code is following:
public class MainActivity extends Activity {
private DataReceiving dRec;
private DataTransfer dTrans;
private EditText inputData;
private Button sendParametersBtn;
private Button startComputationBtn;
private TextView displayText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inputData=(EditText) findViewById(R.id.InputText);
sendParametersBtn=(Button) findViewById(R.id.button1);
startComputationBtn=(Button) findViewById(R.id.button2);
displayText=(TextView) findViewById(R.id.textView1);
sendParametersBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
dRec = new DataReceiving();
dRec.execute();
}
});
private class DataReceiving extends AsyncTask<Void, Void, ArrayList>
{
#Override
protected ArrayList doInBackground(Void... params) {
ArrayList b = new ArrayList();
try {
b = receive();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b;
}
protected void onPostExecute(ArrayList result) {
super.onPostExecute(result);
Toast toast=Toast.makeText(getApplicationContext(), result.toString(), Toast.LENGTH_SHORT);
toast.show();
}
public ArrayList receive () throws IOException, ClassNotFoundException
{
ServerSocket s= new ServerSocket(8888);
Socket incoming =s.accept();
ObjectInputStream ios = new ObjectInputStream(incoming.getInputStream());
ArrayList b = (ArrayList) ios.readObject();
ios.close();
incoming.close();
s.close();
return b;
}
While clicking the sendParametersBtn nothing happening.
P.S. I can successfully transmit from Android to Server. So its not a connection or permission problem.
Thank you for help
Hi If your getting some thing from server you have to call web server url for fetching data. After data arrives response have some type it will JSON/XML if they are restful services if they are SOAP services they are in envelope. So after response return get that and parse them as per logic.
Look for HTTP get/post (for ping to server and get data )and parsing (JSON/XML).
Figured out! I removed receive method into doInBackground.
I'm trying to write a server/client app in android using sockets and i handle the client socket in AsyncTask (server is not android, just ordinary java).I get the exception when I'm trying to read from the server.I found out that when I delete android:targetSdkVersion="16" from android manifest the exception goes away and I can read from the server.
I don't understand why is that? could anyone help me clarify this? I also have problems understanding how the asynctask method doInBackground and my own methods relate. Does conhandler.execute() run doInBackground() and then just waits until I call the other methods? thanks for help.
public class ConnectionHandler extends AsyncTask<Void, Void, Void>{
public static String serverip = "10.0.2.2";
public static int serverport = 5000;
Socket s;
PrintWriter out;
BufferedReader in;
protected Void doInBackground(Void... params) {
try {
s = new Socket(serverip, serverport);
Log.i("AsyncTank", "doInBackgoung: Created Socket");
}...
if (s.isConnected()) {
try {
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(s.getOutputStream(), true);
Log.i("AsyncTank", "doInBackgoung: Socket created, Streams assigned");
} ....
}
public void writeToStream(String message) {
try {
if (s.isConnected()){
out.println(message);
} else {
Log.i("AsynkTask", "writeToStream : Cannot write to stream, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "writeToStream : Writing failed");
}
}
public String readFromStream() {
try {
if (s.isConnected()) {
Log.i("AsynkTask", "readFromStream : Reading message");
String ret=in.readLine();
Log.i("AsynkTask", "readFromStream : read "+ret);
return ret;
} else {
Log.i("AsynkTask", "readFromStream : Cannot Read, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "readFromStream : Reading failed"+e.getClass());
}
return null;
}
}
this is my main activity
public class MainActivity extends Activity {
private EditText view_email;
private EditText view_password;
TextView result;
ConnectionHandler conhandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conhandler = new ConnectionHandler();
conhandler.execute();
}
public void register(View view) {
view_email= (EditText) findViewById(R.id.email);
view_password = (EditText) findViewById(R.id.password);
String email=view_email.getText().toString();
String password=view_password.getText().toString();
conhandler.writeToStream("register");
conhandler.writeToStream(email);
conhandler.writeToStream(password);
String res=conhandler.readFromStream(); //here's the exception
result=(TextView) findViewById(R.id.result);
result.setText(res);
}
}
There are two Solution of this Problem.
1) Don't write network call in Main UIThread, Use Async Task for that.
2) Write below code into your MainActivity file after setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
And below import statement into your java file.
import android.os.StrictMode;
android.os.NetworkOnMainThreadException
this eror comes With HoneyComb(3.0 or Later).
you can not perform a networking operation on its main thread as documentation says. to getting ride of this you must use handler or asynctask. AFAIK There is no another way to do it.
you can See this for More Details WHY ICS Crashes your App
Try Using Below Code Snippet
new Thread(){
public void run(){
//do your Code Here
}
}.start();