i'm stuck at creating UDP connection between android phone(2.3) and my PC over wifi.
I know how to create a UDP connection in local server. My problem is do android support adhock network because whenever i try searching for my PC's wifi directly , it doesn't show it , hence i have to first create a virtual hotspot over my PC and then connect my phone to it .
After this , i simply try sending data packets from my phone to server running on my PC.
public class WifitestActivity extends Activity {
WifiManager w;
TextView status;
InetAddress server_ip;
int server_port = 9876;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
status = (TextView) findViewById(R.id.status);
w = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
if (!w.isWifiEnabled()) {
status.setText("switching ON wifi ");
w.setWifiEnabled(true);
} else {
status.setText("Its already ON ");
}
int x;
WifiInfo info = w.getConnectionInfo();
status.append("\n\nWiFi Status: " + info.toString());
x = info.getIpAddress();
String str = info.getMacAddress();
status.append("\n\nmac address===" + str + " ,ip===" + x);
try {
server_ip = InetAddress.getByName("192.168.181.1"); // ip of my server.How to dynamically update it
} catch (UnknownHostException e) {
status.append("Error at fetching inetAddress");
}
DatagramSocket s = new DatagramSocket(server_port, server_ip);
// **ERROR AT PREVIOUS LINE, I HAD TO FORCE STOP MY APP EVERTIME I RUN
// MY CODE**
String str = "TEST MESSAGE !!!";
byte b1[];
b1 = new byte[100];
b1 = str.getBytes();
DatagramPacket p1 = new DatagramPacket(b1, b1.length, server_ip,
server_port);
}
}
Server code running on my PC :
import java.io.*;
import java.net.*;
class server2
{
static InetAddress clientip;
static int clientport;
static DatagramPacket p3;
public static void main(String args[])throws Exception
{
DatagramSocket s = new DatagramSocket(9876);
byte b1[],b2[];
b1=new byte[100];
b2=new byte[100];
DatagramPacket p1 = new DatagramPacket(b1,b1.length);
s.receive(p1);
b1=p1.getData();
String str = new String( b1);
clientport = p1.getPort(); //packet mein save hota hai
clientip=p1.getAddress();
System.out.println("RECIEVED FROM CLIENT IP ="+clientip+" port="+clientport+" data="+str);
}
}
There is an error at client code (WifiTestActivity) and my app crashes whenever i try running it on my phone . Plzz help me out !
You need the Internet Permission. Add this to your manifest:
<uses-permission android:name="android.permission.INTERNET"/>
Related
I want to read html code of arduino web server.
I can make web server simply with from example 4. code is below.
#include <SoftwareSerial.h>
#include "WiFly.h"
#define SSID "yum2"
#define KEY "yum000000"
// check your access point's security mode, mine was WPA20-PSK
// if yours is different you'll need to change the AUTH constant, see the file WiFly.h for avalable security codes
#define AUTH WIFLY_AUTH_WPA2_PSK
int flag = 0;
// Pins' connection
// Arduino WiFly
// 2 <----> TX
// 3 <----> RX
SoftwareSerial wiflyUart(2, 3); // create a WiFi shield serial object
WiFly wifly(&wiflyUart); // pass the wifi siheld serial object to the WiFly class
void setup()
{
wiflyUart.begin(9600); // start wifi shield uart port
Serial.begin(9600); // start the arduino serial port
Serial.println("--------- WIFLY Webserver --------");
// wait for initilization of wifly
delay(1000);
wifly.reset(); // reset the shield
delay(1000);
//set WiFly params
wifly.sendCommand("set ip local 80\r"); // set the local comm port to 80
delay(100);
wifly.sendCommand("set comm remote 0\r"); // do not send a default string when a connection opens
delay(100);
wifly.sendCommand("set comm open *OPEN*\r"); // set the string that the wifi shield will output when a connection is opened
delay(100);
Serial.println("Join " SSID );
if (wifly.join(SSID, KEY, AUTH)) {
Serial.println("OK");
} else {
Serial.println("Failed");
}
delay(5000);
wifly.sendCommand("get ip\r");
char c;
while (wifly.receive((uint8_t *)&c, 1, 300) > 0) { // print the response from the get ip command
Serial.print((char)c);
}
Serial.println("Web server ready");
}
void loop()
{
if(wifly.available())
{ // the wifi shield has data available
if(wiflyUart.find("*OPEN*")) // see if the data available is from an open connection by looking for the *OPEN* string
{
Serial.println("New Browser Request!");
delay(1000); // delay enough time for the browser to complete sending its HTTP request string
// send HTTP header
wiflyUart.println("HTTP/1.1 200 OK");
wiflyUart.println("Content-Type: text/html; charset=UTF-8");
wiflyUart.println("Content-Length: 244"); // length of HTML code
wiflyUart.println("Connection: close");
wiflyUart.println();
// send webpage's HTML code
wiflyUart.print("<html>");
wiflyUart.print("<head>");
wiflyUart.print("<title>My WiFI Shield Webpage</title>");
wiflyUart.print("</head>");
wiflyUart.print("<body>");
wiflyUart.print("<h1>Hello World!</h1>");
wiflyUart.print("<h3>10 20 30 40 50</h3>");
wiflyUart.print("Yahoo! Google");
wiflyUart.print("<br/><button>My Button</button>");
wiflyUart.print("</body>");
wiflyUart.print("</html>");
}
}
}
the web server work well.
I wrote simple android code to read html is below.
package com.example.http;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private TextView tv;
String urlAddress = "192.168.0.10"; // doesn't show
// String urlAddress = "http://www.kma.go.kr/weather/main.jsp#1159068000"; // work well
Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.textView1);
Button b = (Button)findViewById(R.id.button1);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadHtml();
}
});
}
void loadHtml() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
final StringBuffer sb = new StringBuffer();
try {
URL url = new URL(urlAddress);
HttpURLConnection conn =
(HttpURLConnection) url.openConnection();
if (conn != null) {
conn.setConnectTimeout(2000);
conn.setUseCaches(false);
if (conn.getResponseCode()
== HttpURLConnection.HTTP_OK) {
BufferedReader br
= new BufferedReader(new InputStreamReader
(conn.getInputStream()));
while (true) {
String line = br.readLine();
if (line == null) break;
sb.append(line + "\n");
}
br.close();
}
conn.disconnect();
}
Log.d("test", sb.toString());
handler.post(new Runnable() {
#Override
public void run() {
tv.setText(sb.toString());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
}
}
It work very well with String urlAddress = "http://www.kma.go.kr/weather/main.jsp#1159068000";
but it doesn't show when using
String urlAddress = "192.168.0.10"; instead of before one.
the 192.168.0.10 is allocated ip of arduino from DHCP that i can check on serial monitor.
there is any way to read html from arduino web server??
Your urlAddress isn't a URL, it's just an IP address. You should fully qualify the address with the protocol and the path you want to land on, for example:
String urlAddress = "http://192.168.0.10/";
I would expect you're getting a MalformedURLException.
I set up an Arduino Nano as a TCP server. Then I wrote an Android app that is opening a socket and sending data, but it is not able to receive the answer from the server. The TCP server is receiving the message from the Android app but is getting sometimes more empty messages:
Android log:
05-27 04:08:04.673 7571-7571/com.livingroom.stefan.livinglight D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
05-27 04:08:04.768 7571-7571/com.livingroom.stefan.livinglight D/LivingLight: onBtnClick(): gathering data from Buttons
05-27 04:08:04.768 7571-7571/com.livingroom.stefan.livinglight D/LivingLight: onBtnClick(): data gathered: 00000000
05-27 04:08:04.843 7571-9973/com.livingroom.stefan.livinglight D/LivingLight: startCom(): open socket(192.168.188.25,23598)
05-27 04:08:04.843 7571-9973/com.livingroom.stefan.livinglight D/LivingLight: startCom(): sending data to device
05-27 04:08:04.848 7571-9973/com.livingroom.stefan.livinglight D/LivingLight: startCom(): data sent to device (00000000)
05-27 04:08:04.848 7571-9973/com.livingroom.stefan.livinglight D/LivingLight: startCom(): socket closed
Log from Arduino:
ESP8266: init()
ESP8266: connected to wifi
ESP8266: TCP Server started
AT+CIFSR
+CIFSR:STAIP,"192.168.188.25"
+CIFSR:STAMAC,"18:fe:34:a5:22:bb"
OK
got message:,9:00000000
0,CLOSED
set outputs: 00000000
got message:
got message:
got message:
got message:
got message:
To check if this problem is in my server or my Android app, I tried sending data to my Arduino from two additional devices. The C code on my Raspberry Pi and a program called "SocketTest3" worked fine. Both were sending data properly and receiving the acknowledge from the TCP server. That's why I guess the problem is in my Android code.
The strange thing is there is only from the android device a 0,CLOSED behind the message.
I've found here some pieces of advice like flushing PrintWriter or waiting for BufferedReader.ready(). But neither of them led to a solution. The method PrintWriter.checkError() is false.
My Arduino code is:
void loop() {
int client = esp8266.getId();
if (client >= 0) {
String msg = esp8266.readString();
// receive data from serial buffer
esp8266.sendData(client, "#\r\n");
// acknowledge received data
debug("got message:");
debug(msg);
// eg.: ,9:01101001
debug("\n");
int start = msg.indexOf(':')+1;
// gets index of : char
if((msg.charAt(start)-48)>=0) {
// checks if buffer contains data
debug("set outputs: ");
for(int i=0; i<N_LED; i++) {
// for each LED (starts with PIN 2)
digitalWrite((i+2),(msg.charAt(start+i)-48));
debug(digitalRead(i+2));
EEPROM.write(i,digitalRead(i+2));
}
debug("\n");
}
esp8266.closeConnection(client);
}
} //end loop
String preparation txData:
public void onBtnClick() {
txData = "";
if(tbAllOff.isChecked()) {
Log.d(TAG, "onBtnClick, allOff");
txData = "00000000";
} else if(tbAllOn.isChecked()) {
Log.d(TAG, "onBtnclick, allOn");
txData = "11111111";
} else {
Log.d(TAG, "onBtnClick, gathering data from Buttons");
for (int i=0; i<tbList.length; i++) {
txData += (tbList[i].isChecked())?1:0;
}
Log.d(TAG, "onBtnClick, data gathered: " + txData);
}
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.HONEYCOMB)
new Client().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
new Client().execute();
txt1.setText(rxData);
}
The socket part from my Android app is:
private class Client extends AsyncTask<String, Void, Void> {
protected Void doInBackground(String[] params) {
try {
Log.d(TAG,"AsyncTask.doInBackground(): send data: "+ txData);
rxData = startCom();
} catch(IOException e) {
e.printStackTrace();
rxData = "IOException: " + e;
Log.e(TAG,rxData);
}
return null;
}
private String startCom() throws IOException {
ipAddress = "192.168.188.25";
portNumber = 23598;
Socket socket = new Socket(ipAddress, portNumber);
Log.d(TAG,"startCom(): open socket(" + ipAddress + "," + portNumber + ")");
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter(socket.getOutputStream(),true);
Log.d(TAG,"startCom(): sending data to device");
output.println(txData);
output.close();
Log.d(TAG,"startCom(): data sent to device (" + txData + ")");
String in = "#";
if(input.ready()) {
in = input.readLine();
Log.d(TAG, "startCom(): data received: " + in);
}
socket.close();
Log.d(TAG,"startCom(): socket closed");
return in;
}
}
In My Android application I get xmpp connection initially using server_nm and 5222 port on login and done single chat message send and receive,but at time of file transfer, How I configure connection with proxy_server and 7777 port which use for file transfer?
public class XmppManager {
private static final int packetReplyTimeout = 500; // millis
private String server=server_nm;
private int port=5222;
private ConnectionConfiguration config;
private XMPPConnection connection;
String group_name,userid;
private ChatManager chatManager;
private MessageListener messageListener;
private Handler mHandler;
PacketFilter filter;
Message message;
Context context;
public static boolean IBB_ONLY = (System.getProperty("ibb") != null);//true;
protected static final String STREAM_DATA_FIELD_NAME = "stream-method";
private StreamNegotiator byteStreamTransferManager;
private StreamNegotiator inbandTransferManager;
// constructor
public XmppManager(String server, int port) {
this.server = server;
this.port = port;
}
// to initialize connection
public void init(Context c) throws XMPPException {
System.out.println(String.format(
"Initializing connection to server %1$s port %2$d", server,
port));
SmackConfiguration.setPacketReplyTimeout(50000);
config = new ConnectionConfiguration(server, port);
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(SecurityMode.disabled);
// group chat invitation
ProviderManager.getInstance().addExtensionProvider("x",
"http://jabber.org/protocol/muc#user",
new GroupChatInvitation.Provider());
// offline msgtime
ProviderManager.getInstance().addExtensionProvider("x",
"jabber:x:delay", new DelayInformationProvider());
//file transfer method
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
ProviderManager.getInstance().addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());
ProviderManager.getInstance().addIQProvider("open","http://jabber.org/protocol/ibb", new OpenIQProvider());
ProviderManager.getInstance().addIQProvider("close","http://jabber.org/protocol/ibb", new CloseIQProvider());
ProviderManager.getInstance().addExtensionProvider("data","http://jabber.org/protocol/ibb", new DataPacketProvider());
// v-card integration
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider());
connection = new XMPPConnection(config);
connection.connect();
System.out.println("Connected: " + connection.isConnected());
chatManager = connection.getChatManager();
context = c;
Intent i = new Intent(context, MyService.class);
context.startService(i);
}
// login to xmpp server
public void performLogin(String username, String password,String resource)
throws XMPPException {
if (connection != null && connection.isConnected()) {
System.out.println("connection on presence send" + connection.isConnected() + " " + username + " " + password);
connection.login(username, password,resource);
setStatus(true, "Online");
Presence presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
}
}
//using this code I try to send file
public void sendfileafterresponse(String filenm,String filereceiverid )
{
FileTransferNegotiator.IBB_ONLY = true;
this.setServiceEnabled(connection, true);
FileTransferManager manager = new FileTransferManager(connection);
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(filereceiverid + "#chat.bobl.us/" + filereceiverid);
File file = new File(filenm);
try {
System.out.println("file send to" + filenm + filereceiverid);
transfer.sendFile(file, "test_file");
} catch (XMPPException e) {
e.printStackTrace();
}
while(!transfer.isDone()) {
if(transfer.getStatus().equals(Status.error)) {
System.out.println("ERROR!!! " + transfer.getError());
} else if (transfer.getStatus().equals(Status.cancelled)
|| transfer.getStatus().equals(Status.refused)) {
System.out.println("Cancelled!!! " + transfer.getError());
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
|| transfer.getStatus().equals(Status.cancelled)){
System.out.println("refused cancelled error " + transfer.getError());
} else {
System.out.println("Success");
}
}
}
}
If you still want to transfer files via smack directly, you basically have too options, as far as I understand the API.
1.
First you can use In Band transmission, that is enabled via
FileTransferNegotiator.IBB_ONLY = true;
This sends your file as base64 encoded message, the same way you are sending a normal message packet.
The second option is to use a streaming proxy. This one is way faster since it does not need to encode / decode the file to base64 but transmitts the data directly. Both devices connnect to the proxy server and share data on this.
To configure a streaming proxy you have to configure it on the server side and add the Providers to your client side connection (this should be done automatically on the latest asmack library).
I configured such a setup using the ejabberd service and mod_proxy65 Mod_proxy65
add to your /etc/ejabberd/ejabberd.yml, your ip adress and host should match the service you are using.
host: "proxy1.example.org"
name: "File Transfer Proxy"
ip: "200.150.100.1"
port: 7777
Then allow the firewall to communicate on this port, and you should be good to go.
However, I figured out, that the file transfer only is functional, if both clients are in the presence "available" if any of them is in another state, the sender receives "service- unavailabe" errors.
Don't rely on XMPP file transfer using aSmack/Smack as it is buly. Instead you can create a plugin which will upload files to the server and after successfully uploading the files send the absolute url of the file to the recipient so that he/she can download the file from there.
Hope this works !
I am using XBMC android source code and now try to extract some code to new xbmc android project. When i try to connect to a ip address and check whether it is reachable using isReachable(), it is throwing a NetworkOnMainThreadException but same source code(in XBMC source code that is i downloded from the git) it is working fine,
This is the source code i'm working on
Handler handler = new Handler(){
public void handleMessage(android.os.Message message){
if(message.getData().containsKey(MacAddressResolver.MESSAGE_MAC_ADDRESS)){
String mac = message.getData().getString(MacAddressResolver.MESSAGE_MAC_ADDRESS);
if(!mac.equals("")) {
mMacAddrView.setText(mac);
Toast toast = Toast.makeText(getContext(), "Updated MAC for host: " + mHostView.getText().toString() + "\nto: " + mac, Toast.LENGTH_SHORT);
toast.show();
}
}
}
};
public class MacAddressResolver implements Runnable{
private String mHost = null;
private String mMac = null;
private Handler mHandler;
public static final String MESSAGE_MAC_ADDRESS = "MAC_ADDRESS";
public MacAddressResolver(String ipString, Handler handler){
mHost = ipString;
mHandler = handler;
}
public void run(){
mMac = arpResolve(mHost);
Bundle bundle = new Bundle();
bundle.putString(MESSAGE_MAC_ADDRESS, mMac);
Message message = new Message();
message.setData(bundle);
mHandler.sendMessage(message);
}
private String arpResolve(String host){
System.out.println("ARPRESOLVE HOST: " + host);
try{
//Parse it as a proper InetAddress - it might be a hostname. We don't know yet.
InetAddress inet = InetAddress.getByName(host);
//initiate some sort of traffic to ensure we get an arp entry (if we're on same subnet, that is...)
inet.isReachable(500); //timeout of 500ms. just to trigger the arp resolution process
//Get the official string representation of the resolved ip address
String ipString = inet.getHostAddress();
BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));
String line = "";
while(true){
line = br.readLine();
if (line == null)
break;
if(line.startsWith(ipString)){
br.close();
System.out.println("ARPRESOLVE MAC:\n" + line);
return line.split("\\s+")[3]; // 4th word, separated by "whitespace"
}
}
br.close();
return "";
}catch(Exception e){
return "";
}
}
}
and i also put these two permission in my AndroidManifest.xml file
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="13" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
I don't know, what is the problem and how can i fix it?
NetworkOnMainThreadException exception means that you are doing some Networking Work on MainThread (which will overload that Thread and throw an Exception).
So, you have to move that Networking Code to the Background Thread(another thread other then Main Thread).
AsyncTask
is a good example to handle such things
I have an application android who send data to the server (PC) but I don't receive any data from the PC to the application. And, how can I do a listener for incoming UDP messages ?
because I need an app to be running all the time even if the app is closed. How would I ensure that my 'listener' service is always running?
I would like to receive a notification when a message arrive from the server to the smartphone.
Here is my code :
public class MainActivity extends Activity implements TextWatcher, OnClickListener {
Client client;
EnvoyerMess envoyermessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
client = new Client();
client.execute();
lancer.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
envoyermessage=new EnvoyerMess();
envoyermessage.execute();
}
});
}
class Client extends AsyncTask<Void,Void,String>{
DatagramSocket client;
String test ;
public String doInBackground(Void...params){
String result=null;
int port=4000;
DatagramSocket clientSocket = null;
byte[] receiveData = new byte[256];
DatagramPacket packet = new DatagramPacket(receiveData, receiveData.length);
try{
InetAddress adresse = InetAddress.getByName("10.0.2.2");
clientSocket = new DatagramSocket(port);
clientSocket.receive(packet);
result = new String(packet.getData());
Log.d("","Received :) ");
}catch (Exception e) {
e.printStackTrace();
} finally {
if (clientSocket != null) {
clientSocket.close();
}
}
return result;
}
public void onPostExecute(String result){
if (result != null) {
//createNotify();
TextView tv = (TextView) MainActivity.this.findViewById(R.id.textView1);
tv.setText(result);
}
}
thanks in advance..
I would start by ensuring that the PC is in fact sending the packets to the correct IP address. Do this by using wireshark, http://www.wireshark.org/ , or a similar tool.
To ensure that your task is running even though the application is is closed you need a service, http://developer.android.com/guide/components/services.html.
Edit:
I you are using an emulator you must first enable redirection in the avd router. This link provides instructions on how to accomplish this developer.android.com/tools/devices/emulator.html#redirection (I cant publish links so you'll have to copy-paste).
If you are developing in windows you would also need to enable telnet. This link describes the steps to accomplish that social.technet.microsoft.com/wiki/contents/articles/910.windows-7-enabling-telnet-client.aspx (again, copy-paste)