I am trying to send a file over bluetooth in an android device. I have done discovery, connection and have made a bluetooth socket. Problem is when i am writing the byte array in the output stream of the bluetooth socket, the recieving side does not receive anything although it accept that something is being sent.
Here's what Iam doing (bad is the bluetooth adaptor)
Please advise.
try
{
BluetoothDevice dev = bad.getRemoteDevice(a);
bad.cancelDiscovery();
dev.createRfcommSocketToServiceRecord(new UUID(1111, 2222));
Method m = dev.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
bs = (BluetoothSocket) m.invoke(dev, Integer.valueOf(1));
bs.connect();
tmpOut = bs.getOutputStream();
}catch(Exception e)
{
}
File f = new File(filename);
byte b[] = new byte[(int) f.length()];
try
{
FileInputStream fileInputStream = new FileInputStream(f);
fileInputStream.read(b);
}catch(IOException e)
{
Log.d(TAG, "Error converting file");
Log.d(TAG, e.getMessage());
}
try {
tmpOut.write(b);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I am using the below code snipped to connect to the serial service in a remote Bluetooth device and it is working fine for me. Just make sure that the other device (can be mobile or PC) has a server socket for serial communication over Bluetooth (see the server side code below)
Client Side:
UUID serialUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothDevice btDevice = btAdapter.getRemoteDevice(BTAddress); // Get the BTAddress after scan
BluetoothSocket btSocket = btDevice.createRfcommSocketToServiceRecord(SERIAL_UUID);
btSocket.connect();
InputStream iStream = btSocket.getInputStream();
OutputStream oStream = btSocket.getOutputStream();
Server Side:
UUID serialUUID = new UUID("1101", true);
String serviceURL = "btspp://localhost:" + serialUUID
+ ";name=Android BT Server;authorize=false;authenticate=false";
StreamConnectionNotifier connectionNotifier = (StreamConnectionNotifier) Connector
.open(serviceURL);
// Blocking method will wait for client to connect
StreamConnection connection = connectionNotifier.acceptAndOpen();
RemoteDevice remoteDevice = RemoteDevice.getRemoteDevice(connection);
InputStream btInput = connection.openInputStream();
OutputStream btOutput = connection.openOutputStream();
Why not use the standard api call instead of calling through reflection, eg:
BluetoothSocket socket = destination
.createRfcommSocketToServiceRecord(new UUID(...)) ;
Also your catch block is empty. Are you sure the socket was connected without any exception? Connect will throw IOException if the connection failed for some reason. See this link
It might be because dev and bs go out of scope before tmpout is used because they are declared within your try/catch block.
Related
I am developing an Android multiplayer game using Wi-Fi direct.
Using Wi-Fi direct, I am able to establish connection between peer devices. Also the code is able to send the data from client device to server device. (According to Android documentation, the Wi-Fi direct uses client-server model)
Problem:
I am not able to share the data from server device to client device using Wi-Fi direct.
I have following questions:
Is there any other way to transfer data (bi-directional) between two
Android devices which are connected through Wi-Fi Direct?
During my online research I understood that to send data from server
device to client device, server needs to know the client’s IP
address. How to use this client’s IP address to send data from
server device to client device? (I am able to fetch the client’s IP
address)
I'd appreciate any suggestions on these queries. Thank you in advance.
Code:
Server Side
public class DataTransferAsyncTask extends AsyncTask<Void,Void,String>{
ServerSocket serverSocket;
Socket client;
InputStream inputstream;
Context context = mActivity.getApplicationContext();
String s;
InetAddress client_add;
#Override
protected String doInBackground(Void... voids) {
try{
serverSocket = new ServerSocket(9999);
Log.e("hello", "Server: Socket opened");
client = serverSocket.accept();
Log.e("hello", "Server: connection done");
inputstream = client.getInputStream();
// OutputStream outputStream = serverSocket.getO
//getting data from client
byte[] address = new byte[12];
if(client.isConnected())
inputstream.read(address);
s = new String(address);
String only_add = new String();
only_add = s.substring(0,12);
client_add = InetAddress.getByName(only_add);
Log.e("hello", "Server: clients ip 1 " + only_add);
Log.e("hello", "Server: converted address 1 " + client_add + " \n is connected"+
client.isConnected());
//send data to client
OutputStream stream = client.getOutputStream();
stream.write(s.getBytes());
Log.e("hello","context value "+context);
// cancel(true);
}catch (IOException e){
}
return null;
}
}
Client Side:
#override
protected void onHandleIntent(Intent intent) {
Log.e("hello","client socket");
Toast.makeText(this,"client socket",Toast.LENGTH_LONG).show();
Context context = getApplicationContext();
if(intent.getAction().equals(action_send_data)){
String host = intent.getStringExtra(group_owner_address);
Socket socket = new Socket();
int port = intent.getIntExtra(group_owner_port,9999);
//binding connection
try{
String x="hello";
Log.e("hello","opening client socket");
byte[] address = getLocalAddress();
String ipAdd = getDottedDecimalIP(address);
socket.bind(null);
socket.connect(new InetSocketAddress(host,port),socket_timeout);
Log.e("hello","device socket address "+ socket.getInetAddress() );
Log.e("hello","client socket is connected"+socket.isConnected());
Log.e("hello","device address :"+ipAdd + " byte "+ address);
//sending data to server
OutputStream stream = socket.getOutputStream();
stream.write(ipAdd.getBytes());
//getting data from the server(supposed to)
InputStream inputstream = socket.getInputStream();
byte[] address_to_sto_fr_ser = new byte[15] ;
inputstream.read(address_to_sto_fr_ser);
String s = new String(address_to_sto_fr_ser);
Log.e("msg from server","msg from server "+s);
// stream.close();
// is.close();
}catch (IOException e){
}
}
}
The communication between client and WiFi Direct Group Owner is based on Socket server running on the Group Owner and clients connected to that server.
Once WiFi Direct group is formed(you can know that by checking "onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo)"), check if the current device is the Group Owner and if so, start the sockets server (similar to your code):
mServerSocket = new ServerSocket(mPort);
Log.e(getClass().getSimpleName(), "Running on port: " + mServerSocket.getLocalPort());
Then next, add this line to accept connections and store a reference of the client socket:
Socket mSocket = mServerSocket.accept();
Now, you have a reference of the client socket, you can use it to send data / messages to it. Next, the other device (client) should initiate a connection to the socket server:
mSocket = new Socket();
mSocket.bind(null);
mSocket.connect(new InetSocketAddress(mAddress, mPort), 500);
To send message from server to client:
DataOutputStream mDataOutputStream = new DataOutputStream(mSocket.getOutputStream());
Send simple message:
mDataOutputStream.writeUTF(message);
mDataOutputStream.flush();
Hope this helps.
Can anyone suggest a good example for get an idea about creating TCP server and client with android WiFi direct to transfer data. (Actually transfering of strings not files)
Actually I did one, but I cannot get the IP of server from client side.
If server and client are connected to the same wifi network, then please try use the 192.168.1.40 IP in the client to send data to server.
For example in client:
Socket socket = new Socket("192.168.1.40", port);
Hope it helps.
package com.example.androidclient;
MyClientTask(String addr, int port){
dstAddress = addr;
dstPort = port;
}
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
}
I'm trying to send a simple string from an android device to a pc.
I managed to send the string via wifi (because is on a LAN network), but the code doesn't work over 3g.
The code i'm using is this:
class send extends AsyncTask
{
#Override
protected Object doInBackground(Object... params) {
try {
InetAddress serverAddr = InetAddress.getByName("IP here")
Socket socket = new Socket(serverAddr, 8564);
String message = "sample_message";
try {
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(message);
} catch(Exception e) {}
finally {
socket.close();
}
} catch (Exception e) {}
return null;
}
}
Where is your PC connected? Is it a LAN behind NAT? Are you using the LAN IP address as serverAddr? What is "IP here"?
If you are using a local network IP address behind the NAT you'll never be able to connect.
If you have a router/wifi AP, enable port forwarding to you PC and use the public IP address provided by the ISP as serverAddr.
Have you tried creating a DataOutputStream like
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
dos.writeBytes(message + '\n');
Instead of :
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(message);
I have searched in Google. In Android 2.2 and sdk 8 how can I use SSID in a List in Android ?
By using SSID should get specific wifi enabled device properties by programmatically. With that help, should transfer the data between two Wifi enabled devices in Android.
To send data in a meaningful manner between two Android devices you would use a TCP connection. To do that you need the ip address and the port on which the other device is listening.
Examples are taken from here.
For the server side (listening side) you need a server socket:
try {
Boolean end = false;
ServerSocket ss = new ServerSocket(12345);
while(!end){
//Server is waiting for client here, if needed
Socket s = ss.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter output = new PrintWriter(s.getOutputStream(),true); //Autoflush
String st = input.readLine();
Log.d("Tcp Example", "From client: "+st);
output.println("Good bye and thanks for all the fish :)");
s.close();
if ( STOPPING conditions){ end = true; }
}
ss.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
For the client side you need a socket that connects to the server socket. Please replace "localhost" with the remote Android devices ip-address or hostname:
try {
Socket s = new Socket("localhost",12345);
//outgoing stream redirect to socket
OutputStream out = s.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println("Hello Android!");
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
//read line(s)
String st = input.readLine();
//. . .
//Close connection
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
For data Transfer between 2 devices over the wifi can be done by using "TCP" protocol. Connection between Client and Server requires 3 things
Using NSD Manager, Client device should get server/host IP Address.
Send data to server using Socket.
Client should send its IP Address to server/host for bi-directional communication.
For faster transmission of data over wifi can be done by using "WifiDirect"
which is a "p2p" connection. so that this will transfer the data from one to other device without an Intermediate(Socket). For example, see this link in google developers wifip2p and P2P Connection with Wi-Fi.
Catch a sample in Github WifiDirectFileTransfer
public void sendToServer(String fileToSend, String ip, int sendPort)
{
int port = sendPort;
String url = ip;
File file = new File(fileToSend);
String fileName = file.getName();
Socket sock;
try {
sock = new Socket(url,port);
//Send the file name
OutputStream socketStream = sock.getOutputStream();
ObjectOutput objectOutput = new ObjectOutputStream(socketStream);
objectOutput.writeObject(fileName);
//Send File
byte [] mybytearray = new byte [(int)file.length()];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
os.write(mybytearray,0,mybytearray.length);
fileSentOkay();
os.flush();
sock.close();
} catch (UnknownHostException e) {
hostNotFound();
} catch (IOException e) {
hostNotFound();
}
}
When I try to send something to the server when the server isn't listening for the connection, the phone keeps attempting to send the file. As a result of this, my Android program will eventually force close.
How could I set a time out for this to happen? Would I have to use something like setSoTimeout() on the socket that is sending the data?
First: Just in case: Don't do network stuff on the UI Thread. Bad Things will happen (tm)
Second: setSoTimeout() should give you a timeout in case the server accepts the connection, but does not reply (or in case there is no reply from the network at all). In case the connection is rejected the socket should fail significantly faster.
Edit: In case the constructor of the Socket class is already taking that long, try using the connect(SocketAddress, int) method. Use InetSocketAddress as parameter:
Socket s = new Socket();
s.connect(..., 1000);