I am beginner in android programming. Am trying to broadcast messages on WiFiDirect using the following code:
public class FileTransferService extends IntentService {
public static final String host= "255.255.255.255";
InetAddress broadcastAddress = InetAddress.getByName(host);// Exception: Unknown host exception
int port = 8888;
protected void onHandleIntent(Intent intent) {
Log.d(WiFiDirectActivity.TAG,"m in 1");
Context context = getApplicationContext();
DatagramSocket socket;
try {
socket = new DatagramSocket(port);
socket.setBroadcast(true);
socket.connect(broadcastAddress, port);
String message = "Hello";
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(
buffer, buffer.length, broadcastAddress, port);
socket.send(packet); // <----- Causes a SocketException
} catch (IOException e) {
Log.d(WiFiDirectActivity.TAG, e.getMessage(), e);
}
}
}
It shows me unknown host exception on getByName() method. Is there anyway to replace the method? Am I going on a right path? Do I need to add anything along with this to send messages.
Thanks in advance
Try calling public UnknownHostException (String detailMessage) to get the detailed exception message.
Another way to call getByName() can be get from here
Below link has a step by step illustration of setting up a Wi-Fi Direct broadcaster
Connecting with Wi-Fi Direct
Related
I am trying to write a simple android chat app. I have created a service class which handles all the networking communication. The DatagramSocket binding is in a separate thread. Once in while I am getting this error and the app crashes:
java.net.BindException: bind failed: EADDRINUSE (Address already in use)
at libcore.io.IoBridge.bind(IoBridge.java:89)
at java.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.java:68)
at java.net.DatagramSocket.createSocket(DatagramSocket.java:133)
at java.net.DatagramSocket.<init>(DatagramSocket.java:78)
and this is the code which prodruces it. The error occur on the line with new DatagramSocket How can I avoid this error? Thank you.
private class ComThread extends Thread {
private static final int BCAST_PORT = 8779;
DatagramSocket mSocket;
InetAddress myBcastIP, myLocalIP;
public ComThread() {
try {
myBcastIP = getBroadcastAddress();
if (D)
Log.d(TAG, "my bcast ip : " + myBcastIP);
myLocalIP = getLocalAddress();
if (D)
Log.d(TAG, "my local ip : " + myLocalIP);
if (mSocket == null) {
mSocket = new DatagramSocket(BCAST_PORT);
mSocket.setReuseAddress(true);
mSocket.setBroadcast(true);
}
} catch (IOException e) {
Log.e(TAG, "Could not make socket", e);
}
}
Since Sean asked for the code, I have translated Nikola's answer to the following code, which is similar to what I am using in my app, in case it is useful:
if (mSocket == null) {
mSocket = new DatagramSocket(null);
mSocket.setReuseAddress(true);
mSocket.setBroadcast(true);
mSocket.bind(new InetSocketAddress(BCAST_PORT));
}
You need to set SO_REUSEADDR before binding. Don't specify port in the constructor - create unbound socket instead with DatagramSocket(null), then set options, then bind() explicitly.
Another reason that I faced,
In case you access a method that using your socket from an external thread, you have to make sure that the thread won't access the method more than once in the same time(or in another words won't create the socket more than one time), and despite the send and receive methods of the DatagramSocket are threadsafe, the construction of the DatagramSocket object is not, so you have to just synchronize the method that is capable of creating the DatagramSocket socket:
synchronized public void my_datagram_socket() throws Exception{
// create the socket
// operations through the socket
// whatever you want
}
For the past couple of days, I have been working on establishing a client-server socket over Bluetooth with an android server and a windows PC socket so I can send information over from the computer that can be used on an app for Oculus Gear VR (app would be on the android). I am having a big issue with the Bluetooth server socket on the android side. It doesn't help that my experience with android studio is encompassed within like 4 days. I figured out how to create a regular server socket on an android app that waits for a connection from the client
`public class MyServer {
BluetoothDevice device;
Thread m_objThread;
ServerSocket m_server;
String m_strMessage;
DataDisplay m_dataDisplay;
Object m_connected;
public MyServer()
{
}
public void setEventListener(DataDisplay dataDisplay)
{
m_dataDisplay = dataDisplay;
}
public void startListening()
{
m_objThread = new Thread(new Runnable() {
public void run() {
try {
m_server = new ServerSocket(2001);
Socket connectedSocket = m_server.accept();
Message clientmessage = Message.obtain();
ObjectInputStream ois = new ObjectInputStream(connectedSocket.getInputStream());
String strMessage = (String) ois.readObject();
clientmessage.obj = strMessage;
mHandler.sendMessage(clientmessage);
ObjectOutputStream oos = new ObjectOutputStream(connectedSocket.getOutputStream());
oos.writeObject("Hi..");
ois.close();
oos.close();
m_server.close();
} catch (Exception e) {
Message msg3 = Message.obtain();
msg3.obj = e.getMessage();
mHandler.sendMessage(msg3);
}
}
});
m_objThread.start();
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message status)
{
m_dataDisplay.Display(status.obj.toString());
}
};
`
But I am not completely sure how to change this to a Bluetooth server socket in order to create a Bluetooth socket. Any help is appreciated, I am relatively new to coding and have only used c++ on visual studio so I am having a lot of trouble with android studio. Thanks!
You should create one thread for accepting a connection and another- for sending and receiving the data. When device is connected, you stop 'connect thread' and start 'transfer' thread. There is a gread example from google- https://github.com/googlesamples/android-BluetoothChat
I want to implement service discovery by using the network's broadcast address. I am sniffing packets with WireShark to confirm that my UDP packets are not being sent. The network code is not being run on the UI thread. The DatagramSocket.send call returns with no exception thrown, but nothing is seen by other programs including WireShark. I have verified that the address returned by getWifiBroadcastAddress actually is the broadcast address of my network.
I have verified that the network supports broadcast by writing a C# program, run on another machine, and WireShark is detecting broadcast packets from this program.
Here is my Android Java code:
try {
DatagramSocket socket = new DatagramSocket(Protocol.INQUIRY_PORT);
socket.setBroadcast(true);
InetAddress broadcastAddr = getWifiBroadcastAddress();
byte[] data = new byte[10];
for(int i = 0; i < data.length; i++) {
data[i] = (byte) i;
}
DatagramPacket packet = new DatagramPacket(data, data.length,
broadcastAddr, Protocol.INQUIRY_PORT);
while(true) {
// Loops indefinitely, no errors/exceptions
socket.send(packet);
try {
Thread.sleep(5000);
} catch(InterruptedException ie) {
break;
}
}
} catch(IOException ioe) {
// Not logged
Log.d("Broadcast", "Error sending inquiry.");
}
The getWifiBroadcastAddress() method is as seen here: https://lab.dyne.org/AndroidUDPBroadcast
Does anyone know why this would fail silently? Like I said my C# program running on another box is working just fine, doing the same thing, sending the same data every 5s, and WireShark sees those packets, but nothing from the Android phone.
The following works for me, where I can broadcast a particular string value to a specified port (in your case Protocol.INQUIRY_PORT) on the other end(s), and all of the devices on the local subnet that are monitoring UDP on that port can recognize that string value, and accordingly can respond. I am broadcasting from the main thread, but listening for responses in an async task.
public void sendBroadcast(String messageStr) {
// Hack Prevent crash (sending should be done using an async task)
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
byte[] sendData = messageStr.getBytes();
try {
sendSocket = new DatagramSocket(null);
sendSocket.setReuseAddress(true);
//sendSocket.bind(new InetSocketAddress(Protocol.INQUIRY_PORT));
sendSocket.setBroadcast(true);
//Broadcast to all IP addresses on subnet
try {
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("255.255.255.255"), Protocol.INQUIRY_PORT);
sendSocket.send(sendPacket);
System.out.println(getClass().getName() + ">>> Request packet sent to: 255.255.255.255 (DEFAULT)");
} catch (Exception e) {
}
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
}
}
Following is the corresponding UDP response listener code inside an async task class:
protected String doInBackground(String... params) {
serverIP = "";
try {
//Keep a socket open to listen to all the UDP trafic that is destined for this port
InetAddress myHostAddr = InetAddress.getByName("0.0.0.0");
rcvSocket = new DatagramSocket(null);
rcvSocket.setReuseAddress(true);
rcvSocket.bind(new InetSocketAddress("0.0.0.0",Protocol.INQUIRY_PORT));
rcvSocket.setBroadcast(true);
while (true) {
Log.i("VIS","Ready to receive broadcast packets!");
//Receive a packet
byte[] recvBuf = new byte[15000];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
rcvSocket.receive(packet);
//Packet received
serverIP = packet.getAddress().getHostAddress();
Log.i("VIS", "Packet received from: " + serverIP);
String data = new String(packet.getData()).trim();
Log.i("VIS", "Packet received; data: " + data);
if (!data.equals("") && !data.equals(myInquiryString)) {
//break while loop and return IP address of server
break;
}
}
} catch (IOException ex) {
Log.i("VIS", "ServerDiscovery" + ex.getMessage());
}
return serverIP;
}
I have an UDP server wrote in C langage which broadcasts paquets over my LAN every 5seconds, on port 3001.
i'm creating an android application as UDP client, which is listening on port 3001 (in the AsyncTask thread) and it's running until the receive() method, no data seems to be detected on this port.
Here is my code :
private class ConnectionTask extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... arg0) {
String receivedString = "";
byte[] receiveData = new byte[1024];
DatagramSocket clientSocket;
try {
while(true){
clientSocket = new DatagramSocket(5000);
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
clientSocket.receive(receivePacket);
receivedString = new String(receivePacket.getData());
}
} catch (SocketException e) {
Log.v("SocketExceptionOccured", e.toString());
e.printStackTrace();
//clientSocket.close();
} catch (IOException e) {
Log.v("IOExceptionOccured", e.toString());
e.printStackTrace();
//clientSocket.close();
}
Toast.makeText(getBaseContext(), receivedString, Toast.LENGTH_LONG)
.show();
return null;
}
}
I test my code with my own device for debug, with USB cable.
I've tested my server with a simple UDP client (in C) running on my computer, and the communication is ok.
I don't know why this code doesn't work. Has someone an idea ?
Thanks,
You're never leaving the while loop. You're message is probably received, and after it, the loop causes the datagramsocket to listen again.
Don't create and close the socket every time around the loop. Create it first and close it afterwards. At present there are windows of time during which the socket doesn't exist, so datagrams to it are dropped: also, all queued datagrams are dropped every time you close it.
I had this same problem. You need to add permissions in the android manifest
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
Also enable broadcasts in the socket.
clientSocket.setBroadcast(true);
Like everyone else before me mentioned, your code also never leaves the while loop, so it never goes to the the line where the toast is displayed.Remember that you CANNOT show Toast messages from doInBackground as this is accessing the UI Thread, you can only do so from the postExecute and preExecute functions. This will cause your application to crash. To check the data you receive you can either debug it or log it.
Your final doInBackground should be something like this
#Override
protected Void doInBackground(Void... arg0) {
String receivedString = "";
byte[] receiveData = new byte[1024];
DatagramSocket clientSocket;
try {
while(true){
clientSocket = new DatagramSocket(5000);
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
clientSocket.setBroadcast(true);
clientSocket.receive(receivePacket);
receivedString = new String(receivePacket.getData());
Log.i("Received String= "+receivedString);
}
} catch (SocketException e) {
Log.v("SocketExceptionOccured", e.toString());
e.printStackTrace();
//clientSocket.close();
} catch (IOException e) {
Log.v("IOExceptionOccured", e.toString());
e.printStackTrace();
//clientSocket.close();
} finally{
if(clientSocket!=null){
clientSocket.close();
}
}
return null;
}
Now when you check your logs, you should be able to see the value of the string received.
I want to transfer messages from the android device to desktop application. My question is that can i connect the android WiFi device with the desktop WiFi device without any use of internet connection. I want to use it just like the Bluetooth. is this possible or not? if it is possible then how can i implement it?
Thanks and Regards
Amit Thaper
Here is an implementation of mreichelt's suggestion. i looked this up when i had the same problem and figured i'd just post my implementation of the solution. it's really simple. i also built a java server that listens for incoming requests from the android device (for debugging purposes mostly). here's the code to send stuff over the wireless:
import java.net.*;
import java.io.*;
import java.util.*;
import android.app.Activity;
import android.content.Context;
import android.content.ContentValues;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;
public class SMSConnection {
/* The socket to the server */
private Socket connection;
/* Streams for reading and writing the socket */
private BufferedReader fromServer;
private DataOutputStream toServer;
/* application context */
Context mCtx;
private static final String CRLF = "\r\n";
/* Create an SMSConnection object. Create the socket and the
associated streams. Initialize SMS connection. */
public SMSConnection(Context ctx) throws IOException {
mCtx=ctx;
this.open();
/* may anticipate problems with readers being initialized before connection is opened? */
fromServer = new BufferedReader(new InputStreamReader(connection.getInputStream()));
toServer = new DataOutputStream(connection.getOutputStream());
}
public boolean open(String host, int port) {
try {
connection = new Socket(host, port);
return true;
} catch(IOException e) {
Log.v("smswifi", "cannot open connection: " + e.toString());
}
return false;
}
/* Close the connection. */
public void close() {
try {
connection.close();
} catch (IOException e) {
Log.v("smswifi","Unable to close connection: " + e.toString());
}
}
/* Send an SMS command to the server. Check that the reply code
is what is is supposed to be according to RFC 821. */
public void sendCommand(String command) throws IOException {
/* Write command to server. */
this.toServer.writeBytes(command+this.CRLF);
/* read reply */
String reply = this.fromServer.readLine();
}
}
that's a basic skeleton for a connection class. you simply instantiate the class, and call open on the instance you create with the host and port (don't forget to close the connection when you're done) and you can change the body of sendCommand to your liking. i've included a read/write operation in the function body as an example.
here is the code to run a server on a remote machine that listens for connections and spawns a thread to handle each request. it can easily interact with the above code for debugging (or any use).
import java.io.*;
import java.net.*;
import java.util.*;
public final class smsd {
///////MEMBER VARIABLES
ServerSocket server=null;
Socket client=null;
///////MEMBER FUNCTIONS
public boolean createSocket(int port) {
try{
server = new ServerSocket(port);
} catch (IOException e) {
System.out.println("Could not listen on port "+port);
System.exit(-1);
}
return true;
}
public boolean listenSocket(){
try{
client = server.accept();
} catch (IOException e) {
System.out.println("Accept failed: ");
System.exit(-1);
}
return true;
}
public static void main(String argv[]) throws Exception {
//
smsd mySock=new smsd();
//establish the listen socket
mySock.createSocket(3005);
while(true) {
if(mySock.listenSocket()) {
//make new thread
// Construct an object to process the SMS request message.
SMSRequest request = new SMSRequest(mySock.client);
// Create a new thread to process the request.
Thread thread = new Thread(request);
// Start the thread.
thread.start();
}
}
//process SMS service requests in an infinite loop
}
///////////end class smsd/////////
}
final class SMSRequest implements Runnable {
//
final static String CRLF = "\r\n";
Socket socket;
// Constructor
public SMSRequest(Socket socket) throws Exception
{
this.socket = socket;
}
// Implement the run() method of the Runnable interface.
public void run()
{
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception
{
// Construct a 1K buffer to hold bytes on their way to the socket.
byte[] buffer = new byte[1024];
int bytes = 0;
// Copy requested file into the socket's output stream.
while((bytes = fis.read(buffer)) != -1 ) {
os.write(buffer, 0, bytes);
}
}
private void processRequest() throws Exception
{
// Get a reference to the socket's input and output streams.
InputStream is = this.socket.getInputStream();
DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());
// Set up input stream filters.
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
// Get the request line of the SMS request message.
String requestLine = br.readLine();
//print message to screen
System.out.println(requestLine);
//send a reply
os.writeBytes("200");
// Close streams and socket.
os.close();
br.close();
socket.close();
}
}
nb4namingconventions.
almost forgot. you will need to set these permissions inside the tags in your AndroidManifest.xml in order to use wireless.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
This is easily possible if both devices are using the same wifi network and can ping each other. You may just create a Java application on your desktop which creates a ServerSocket. Then you can open a Socket in your Android app using the desktop's IP address and send data through the OutputStream.
I believe that Amit is referring to having the machines connect directly to each other using wireless.
There is the development currently of the Wifi-direct specification to allow for Plug-in-Play setup of Access Points. The issue currently is ensuring one of the machines is an AP that other machine(s) can establish connection to.
I'm interested in how this relates to Ad-Hoc networks. I don't have a solution, however I am quite interested in this question too ! (Assuming this is your question Amit).