this has been bugging me for a while and I'm not too sure how I can go about solving this issue.
The issue I am having is it will take several attempts of pushing a packet before the server will actually receive the packet
This is the code I have on the client (Server is Identical but the Send/Receive are reversed) and the Server gets the client IP from the packet to send a return packet
class MainTask extends AsyncTask<Void, Void, Void> {
ProgressDialog progress = null;
Context context = null;
public MainTask(ProgressDialog progress, Context context) {
this.progress = progress;
this.context = context;
}
public void onPreExecute() {
progress.show();
}
public Void doInBackground(Void... unused) {
// Send UDP Packet
String messageStr="Hello Android!";
int server_port = 12441;
DatagramSocket s = null;
DatagramPacket p = null;
InetAddress local = null;
Log.i("EyeceBoxService", "Sending packet");
try {
s = new DatagramSocket();
local = InetAddress.getByName("192.168.0.4");
int msg_length=messageStr.length();
byte[] message = messageStr.getBytes();
p = new DatagramPacket(message, msg_length,local,server_port);
s.send(p);
Log.i("EyeceBoxService", "Packet Sent!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Receive UDP Packet
byte[] message = new byte[1500];
try {
//progress.setMessage("Retrieving Discovery Information...");
p = new DatagramPacket(message, message.length);
s = new DatagramSocket(server_port);
Log.i("EyeceBoxService", "Waiting for packet");
s.receive(p);
String address = p.getAddress().toString();
Log.i("EyeceBoxService", "Server IP address" + address);
//progress.setMessage("Done...");
//MainActivity.buildNotification(context, address);
progress.dismiss();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void onPostExecute(Void unused) {
}
}
Try to isolate whether the issue is in the server hardware, client hardware, Android framework, network, router config or your code. Try using some debugging tools like wireshark, netcat, ipsend and see what packets are actually sent, received, if packet sending works through commandline, etc.
Related
I try to build up a connection between my android device and an arduino nano.
I tested the TCP connection between an raspberry pi zero and my arduino and it works and does what it is supposed to do.
Now i try to write the android app, but it throws the
android.io.NetworkOnMainThreadException
I found some hints to do it with AsynkTask but it still throws this exception. I found some solutions but neither did help in my case (eg: setting minAPI to 11).
public class MainActivity extends AppCompatActivity {
[...]
#Override
protected void onCreate(Bundle savedInstanceState) {
[...]
bt1.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
onBtnClick();
}
}
}
public void onBtnClick() {
new Client().execute("0101010101");
}
private class Client extends AsyncTask<String, Void, String> {
protected String doInBackground(String[] params) {
// do above Server call here
return "null";
}
protected void onPostExecute(String msg) {
String reply ="";
try {
reply=sendData();
} catch(IOException e) {
e.printStackTrace();
reply = "IOException: "+e;
}
txt1.setText(reply);
}
public String sendData() throws IOException{
try {
// send message to Arduino
InetAddress serverAddr = InetAddress.getByName(ipAddress);
DatagramSocket clientSocket = new DatagramSocket();
send_data = str.getBytes();
DatagramPacket sendPacket = new DatagramPacket(send_data, send_data.length, serverAddr, portNumber);
clientSocket.send(sendPacket);
// get reply
byte[] receiveData1 = new byte[512];
DatagramPacket receivePacket = new DatagramPacket(receiveData1, receiveData1.length);
clientSocket.receive(receivePacket);
String reply = new String(receiveData1);
clientSocket.close();
return reply;
} catch (Exception e) {
e.printStackTrace();
return("Exception: "+ e);
}
}
}
}
What am i doing wrong? Thank you for your help.
The methods onPreExecute and onPostExecute runs on main thread, so, the method sendData should be executed on doInBackground
private class Client extends AsyncTask<String, Void, String> {
protected String doInBackground(String[] params) {
String reply ="";
try {
reply=sendData();
} catch(IOException e) {
e.printStackTrace();
reply = "IOException: "+e;
}
}
protected void onPostExecute(String msg) {
txt1.setText(reply);
}
public String sendData() throws IOException{
try {
// send message to Arduino
InetAddress serverAddr = InetAddress.getByName(ipAddress);
DatagramSocket clientSocket = new DatagramSocket();
send_data = str.getBytes();
DatagramPacket sendPacket = new DatagramPacket(send_data, send_data.length, serverAddr, portNumber);
clientSocket.send(sendPacket);
// get reply
byte[] receiveData1 = new byte[512];
DatagramPacket receivePacket = new DatagramPacket(receiveData1, receiveData1.length);
clientSocket.receive(receivePacket);
String reply = new String(receiveData1);
clientSocket.close();
return reply;
} catch (Exception e) {
e.printStackTrace();
return("Exception: "+ e);
}
}
}
I want to connect via socket to my android app.but in server side(android app) I get java.net.SocketTimeoutException error and in client side I get java.net.ConnectException: Connection refused: connecterror.
what is my mistake? thank you
server (android app)
public class ServerSocketTask extends AsyncTask<Void, Void, String> {
final StackTraceElement se = Thread.currentThread().getStackTrace()[2];
private String data = null;
#Override
protected String doInBackground(Void... params) {
Log.d(se.getClassName() + "." + se.getMethodName(), "start");
try {
ServerSocket serverSocket = new ServerSocket(8989);
serverSocket.setSoTimeout(50000);
Socket socket = serverSocket.accept();
socket.setKeepAlive(true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int readed = in.read();
Log.d("","readed bytes : "+readed);
String line;
while ((line = in.readLine()) != null){
Log.i("","line : "+ line);
}
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ServerSocketTask.this.data = result;
}
public String getData() {
return data;
}
}
client
public static void main(String[] args) {
int port;
try (Socket socket = new Socket("192.168.240.105", 8989)) {
String customerId = "123";
String requestId = Configuration.getProperty("requestId");
ClientService result = new ClientService();
String makeRequest = result.objectToJson(customerId, requestId);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.write(makeRequest);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
my client can't connect to server and my server wait for connection.
When you construct ServerSocket(8989) you're binding to wildcard address of network interfaces available on android emulator/device.
However both Android emulator and real device has it's own network interface(s) and thus it's it's own IP addresses. Your client program (development machine) IP address is not the same as IP address of android emulator/device. In other words you cannot connect to the socket created in Android app because you're using wrong address.
This answer should guide you on how to find out the address.
I am beginner in android xamarin. I want to use chat room realtime using SignalR. But i dont know what is "http://10.0.2.2:8081/echo" mean in this example. Is it a server???There are something in that server - like php file, database or something else???
hope your answer, thanks :D or anybody show me how to build a group chat application, please(use socket like :http://www.androidhive.info/2014/10/android-building-group-chat-app-using-sockets-part-1/ or SignalR in xamarin )
using System.Collections.Generic;
using Android.App;
using Android.OS;
using Android.Widget;
namespace SignalR.Client.MonoDroid.Sample
{
[Activity(Label = "SignalR.Client.MonoDroid.Sample", MainLauncher = true, Icon = "#drawable/icon")]
public class DemoActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var messageListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, new List<string>());
var messageList = FindViewById<ListView>(Resource.Id.Messages);
messageList.Adapter = messageListAdapter;
var connection = new Connection("http://10.0.2.2:8081/echo");
connection.Received += data =>
RunOnUiThread(() => messageListAdapter.Add(data));
var sendMessage = FindViewById<Button>(Resource.Id.SendMessage);
var message = FindViewById<TextView>(Resource.Id.Message);
sendMessage.Click += delegate
{
if (!string.IsNullOrWhiteSpace(message.Text) && connection.State == ConnectionState.Connected)
{
connection.Send("Android: " + message.Text);
RunOnUiThread(() => message.Text = "");
}
};
connection.Start().ContinueWith(task => connection.Send("Android: connected"));
}
}
}
10.0.x.x is a private subnet (http://en.wikipedia.org/wiki/Private_network). In this example then it is talking about you running some kind of server system on your computer on port 8081.
http://10.0.2.2:8081/echo
10.0.2.2 is the ip of your server
8081 is the port on which server listening your request and give response on same port
echo is the automated generate respone which is given to you on every request with same request(String)
public static class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
String s;
String red;
String loc;
public MyClientTask(String addr, int port,String msg){
dstAddress = addr;
dstPort = port;
loc=msg;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
ObjectInputStream inputStream=null;
try {
SocketAddress socketAddress = new InetSocketAddress(dstAddress,dstPort);
socket = new Socket();
socket.setTcpNoDelay(true);
socket.setSoTimeout(5000);
socket.connect(socketAddress, 50000);
// socket = new Socket(dstAddress, dstPort);
System.setProperty("http.keepAlive", "false");
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF(loc);
///inputStream = new ObjectInputStream(socket.getInputStream());
InputStream is = socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
out.println("");
//response = br.readLine();
try{
while((s=br.readLine())!=null){
red=red+s;
Log.i("server", ""+red);
}
Log.i("server", ""+red);
}catch(Exception ex){
ex.printStackTrace();
}
Log.i("Server response ", "hi"+s);
try {
System.out.println("Read back from server: " + response);
}
catch(Exception e) {
Log.i("Server response ", response+e);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}finally{
if(socket != null){
try {
dataOutputStream.flush();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
res=response;
Log.i("response:", "res"+res);
// Toast.makeText(getApplicationContext(), "hi"+res, Toast.LENGTH_LONG).show();
super.onPostExecute(result);
}
}
call this method to send request and get response on your desired place
public void sendtoserver(String msg){
if(isConnectingToInternet()){
servermsg="$loc"+","+ieminumber+","+formattedDate2+","+formattedDate1+","+formattedDate2+","+formattedDate1+","+1+","+lat1+","+"N"+","+lon1+"*";
//10.0.2.2:8081/echo
MyClientTask myClientTask = new MyClientTask(
"10.0.2.2",8081,msg);
myClientTask.execute();
}
}
If you run your app on an emulator and your server runs on the same pc as the emulator then the only way your client app can reach that server is using ip 10.0.2.2 as Google implemented it that way. Meanwhile your computer can have local ip like 192.168.1.12 but your app can not use that. Also the server on the pc is reachable as localhost or 127.0.0.1 by clients running on the same pc. Your app does not run on that pc. Your app runs on the emulator.
I have created a server and client with Android and Arduino but I have a problem. Android reads only one time. Why? this is my code:
Client Android:
new Thread(new ClientThread()).start();
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName("192.168.1.240");
socket = new Socket(serverAddr, 8888);
if(socket == null)System.out.println("SOCKET NULL");
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),true);
inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
msgFromServer = inFromServer.readLine();
System.out.println(msgFromServer);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket != null) {
System.out.println("STOP SOCKET");
// close socket
}
}
}
}
Arduino Server:
void loop() {
YunClient client = server.accept();
sensorValue = analogRead(sensorPin);
String myString = String(sensorValue);
if (client) {
String command = "none";
command = client.readString();
Serial.println(sensorValue);
client.print(myString+"\n");
}
}
LOGCAT:
07-24 11:44:24.468: D/OpenGLRenderer(19693): Enabling debug mode 0
07-24 11:44:25.363: I/System.out(19693): 121
121 is the value from Arduino. But this is showing only once.
It works only once. I want receive data from the Arduino every second.
Thank you guys!
You need to take the accept out of the loop. otherwise it send a string and wait for another connect from client.
YunClient client = server.accept();
void loop() {
sensorValue = analogRead(sensorPin);
String myString = String(sensorValue);
if (client) {
String command = "none";
command = client.readString();
Serial.println(sensorValue);
client.print(myString+"\n");
}
}
Also, I don't see where the client sends something to the server. Instead of System.out.println should't it be out.println?
I use the following code to receive the data from a particular port. It's not working in Android. But sending data to particular port is working fine.
public class UDPDemo extends Activity {
private TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView)findViewById(R.id.recv_message);
try {
DatagramSocket clientsocket=new DatagramSocket(9876);
byte[] receivedata = new byte[1024];
while(true)
{
DatagramPacket recv_packet = new DatagramPacket(receivedata, receivedata.length);
Log.d("UDP", "S: Receiving...");
clientsocket.receive(recv_packet);
String rec_str = new String(recv_packet.getData());
tv.setText(rec_str);
Log.d(" Received String ",rec_str);
InetAddress ipaddress = recv_packet.getAddress();
int port = recv_packet.getPort();
Log.d("IPAddress : ",ipaddress.toString());
Log.d(" Port : ",Integer.toString(port));
}
} catch (Exception e) {
Log.e("UDP", "S: Error", e);
}
}
}
If you are using the emulator you may need setup redirects, remember the emulator is behind a virtual router.
In other words, type these commands in;
telnet localhost 5554
redir add udp:9876:9876
and try again.
Used Port numbers
Create Datagram packet
try {
mDataGramSocket = new DatagramSocket(Config.PORT_NUMBER);
mDataGramSocket.setReuseAddress(true);
mDataGramSocket.setSoTimeout(1000);
} catch (SocketException e) {
e.printStackTrace();
}
Call below function through AsyncTask
Create Function to receive infinitely
public void receive() {
String text;
byte[] message = new byte[1500];
DatagramPacket p = new DatagramPacket(message, message.length);
try {
while (true) { // && counter < 100 TODO
// send to server omitted
try {
mDataGramSocket.receive(p);
text = new String(message, 0, p.getLength());
// If you're not using an infinite loop:
//mDataGramSocket.close();
} catch (SocketTimeoutException | NullPointerException e) {
// no response received after 1 second. continue sending
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
// return "error:" + e.getMessage();
mReceiveTask.publish("error:" + e.getMessage());
}
// return "out";
}