I am trying to test this bluetooth communication example between a PC and an Android phone. My SPP client is exactly the one from there and it works fine. I am new to Android and I didn't want to make it run in a separate thread because I don't know how, so I just did everything in the onCreate() method. If this is not the best way, feel free to point me to a better way, but this is not my main problem.
The problem is I wanted to display the text received via bluetooth on a textView and I don't know how to read from InputStream. When the code is left like that, it displays something like java.io.DataInputStream#41b0cb68
I tried it like here it didn't display anything, also I don't know what encoding is being used.
here's my android app's code:
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.*;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
//based on java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");
// The local server socket
private BluetoothServerSocket mmServerSocket;
// based on android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.textView_Text);
BluetoothSocket socket = null;
mAdapter = BluetoothAdapter.getDefaultAdapter();
// Listen to the server socket if we're not connected
// while (true) {
try {
// Create a new listening server socket
Log.d((String) this.getTitle(), ".....Initializing RFCOMM SERVER....");
// MY_UUID is the UUID you want to use for communication
mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService", MY_UUID);
//mmServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try using In Secure connection...
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (Exception e) {
}
try {
Log.d((String) this.getTitle(), "Closing Server Socket.....");
mmServerSocket.close();
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
DataInputStream mmInStream = new DataInputStream(tmpIn);
DataOutputStream mmOutStream = new DataOutputStream(tmpOut);
// here you can use the Input Stream to take the string from the client whoever is connecting
//similarly use the output stream to send the data to the client
text.setText(mmInStream.toString());
} catch (Exception e) {
//catch your exception here
}
// }
}
}
I commented out the while(true) loop because I think it was making my app crash when onPause() was being called. I know this is not the best implementation but I really want to read from the bluetooth I feel like I am very close :), other aspects will be dealt with afterwards (like working with threads and so on).
I finally managed to correctly display in a TextView the string sent from the PC ("Test String from SPP Client\r\n").
I used this question, namely this piece of code, just below DataOutputStream mmOutStream = new DataOutputStream(tmpOut);:
// Read from the InputStream
bytes = mmInStream.read(buffer);
String readMessage = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity
This is a very rudimentary example, designed only to show how to display strings received via bluetooth on the screen of the device. It is not done in a separate thread, and after it receives the string you have to close the app and restart it again, but the main purpose of the app was achieved (as I stated when I asked this question). What I really, really wanted was to receive a string from PC and display it on screen.
Here's my complete MainActivity, if somebody wants me to post a more complete approach (like using a separate thread) I will post it here once I complete it.
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.*;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
//based on java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");
// The local server socket
private BluetoothServerSocket mmServerSocket;
// based on android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.textView_Text);
BluetoothSocket socket = null;
mAdapter = BluetoothAdapter.getDefaultAdapter();
// Listen to the server socket if we're not connected
// while (true) {
try {
// Create a new listening server socket
Log.d((String) this.getTitle(), ".....Initializing RFCOMM SERVER....");
// MY_UUID is the UUID you want to use for communication
mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService", MY_UUID);
//mmServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try using In Secure connection...
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (Exception e) {
}
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
try {
Log.d((String) this.getTitle(), "Closing Server Socket.....");
mmServerSocket.close();
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
DataInputStream mmInStream = new DataInputStream(tmpIn);
DataOutputStream mmOutStream = new DataOutputStream(tmpOut);
// here you can use the Input Stream to take the string from the client whoever is connecting
//similarly use the output stream to send the data to the client
// Read from the InputStream
bytes = mmInStream.read(buffer);
String readMessage = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity
text.setText(readMessage);
} catch (Exception e) {
//catch your exception here
}
// }
}
}
Any questions? :)
Basically, you'll need to match the way data is sent from one device to the way data is received by the other one.
SPP is stream based and transfers bytes of data. So, whatever bytes the sending device transmits must be interpreted correctly by the receiver.
An InputStream gives you access to the raw bytes transmitted, and you'll have to do something with them; i.e. decode them in some way as needed. For instance, if the sender uses an ObjectOutputStream to do the encoding prior to transmission, the receiver will have to use an ObjectInputStream to decode the input.
You may want to read up on InputStream (read()), ObjectInputStream, and toString().
Besides, reading from a blocking stream should almost always be done in a separate thread; and especially so when reading from some remote device/host/network/... with possible unknown delays or transmission speed.
Related
I am trying to send a message named "ringdoor" from the python client to the android TCP server. However, the readline method in the Server code is not reading the message.
please note:
1) that I am using "sendall" to send the message from the python client
2)I am using the bufferedReader class and readline method to read messages from the client.
3) The codes for the client and the server are below.
Server code in Java
package com.example.mmz_10.test7;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// startService(new Intent(getBaseContext(), Server.class));
Thread ServerThread= new Thread(new MyServerThread());
// starting the thread to do work in the background
ServerThread.start();
// Log.d("Server.java", "Starting server...");
}
// https://developer.android.com/reference/java/lang/Thread.html
public class MyServerThread implements Runnable {
Socket socket;
ServerSocket serverSocket;
InputStreamReader isr;
BufferedReader br;
String message;
#Override
public void run (){
try
{
int port = 8080;
serverSocket = new ServerSocket(port);
// Now the server just started and is listening to port 4457
System.out.println ("the server just started and is listening to port 4457");
//To make Server run forever, we use "while(true)" loop as shown below
while(true)
{
//Reading the message from the client (raspberry pi 3)
// Log.d("Server.java", "Listening on port " + port);
socket = serverSocket.accept();
System.out.println ("the server just accepted the connection from the client");
System.out.println ("preparing to read the message" );
isr = new InputStreamReader(socket.getInputStream()); // side note :InputStreamReader is equivalent to DataInputStream
br = new BufferedReader(isr);
message = br.readLine(); // message received from the client
System.out.println ("preparing to print the message" );
if (message!=null){
System.out.println ("the messagee is not null");
}else {
System.out.println ("the message is null");
}
// System.out.println(br);
if (message.equals("ring")){
// starting an activity from the service
Intent intent = new Intent(MainActivity.this, RingCall.class); // The " Server.this" or in general "ClassName.this" is used for nested classes when an inner class need to use the outer class
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} // end of if
} // end of the "while(true)" loop
} // end of the "try block"
catch (IOException e)
{
e.printStackTrace();
}
//finally
//{
// try
//{
// socket.close();
//}
//catch(Exception e){}
//}
}// end of the "run" method
} // end of "MyServerThread" class
}
**Client in python**
Import socket
import sys
try:
s=socket.scoket(socket.AF_INET,socket.SOCK_STREAM)
except socket.error:
print ('Failed to create socket')
sysc.exit();
print ('Socket Created')
port=8080
remote_ip="192.168.0.100"
s.connect((remote_ip,port))
message="ring"
try:
s.sendall(b'ringdoor')
except socket.error
print ('send failed)
sys.exit()
print ('message sent successfully to the server')
I get bit problem, The problem is as follows:
At server socket, server receive data type as byte array:
this.receiveStream = new DataInputStream(this.clientSocket.getInputStream());
byte[] receiveBuffer = new byte[bufferSize];
while (this.receiveStream.read(receiveBuffer, 0, receiveBuffer.length) > -1) {
String dataReceive = new String(receiveBuffer, StandardCharsets.UTF_8).trim();
}
If client send text message in one thread then server run well, but if client run >=2 thread concurrent to send text message then at server, the message were mixed, it mean clientThead1 send "ABC", clientThead2 send "XYZ" => server receive "AXBC" OR "AXYZ",... => It is not expected message.
How to solve this problem???
P/S: I have tested with server receive message as text, it work well:
while (true) {
String dataReceive = this.receiveStream.readUTF().trim();
}
But i can not use it, because server serve muti platform client, so i want to server use byte array to receive data
Thanks all,
UPDATE:
I can not post full code because it is very long character
This is link all code Client + Server:https://www.mediafire.com/folder/j4d041uqfowt6/SocketApp
Do you use TCP or UDP? It is important, the sockets do not hide the difference.
For TCP,
the client threads must not reuse the same connection.
Each client thread must open its own connection, as if it were applications on different devices.
The server must start a new thread each time it listening socket receives a job. That thread will use its own connection; threads servicing different clients are independent as if it were applications on different devices.
I think you see the logic: one client thread <--> one service thread.
(I think you know that a listening socket does not receive data, it creates a data socket).
For UDP, on the server side you have to distinguish the clients yourself.
It would not be possible if you were sending single bytes, but packets are not single bytes, UDP packets include auxiliary information. You have the sender's IP and port, so you can distinguish the clients if they are not two threads using the same port on the same IP.
Use a child thread to read data from socket and main thread to accept request and hand over to child..
Server
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server extends Thread {
public Server(String ip, int port) {
try {
ServerSocket ser = new ServerSocket(port);
System.out.println("Listening....");
while (true) {
Socket soc = ser.accept();
new Child(soc).start();
System.out.println("Child Started...");
}
} catch (IOException e) {
}
}
private class Child extends Thread {
Socket cSoc;
public Child(Socket soc) {
this.cSoc = soc;
}
#Override
public void run() {
try {
String data = "";
InputStream in = cSoc.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int ch = 0, cnt = 0;
byte[] buffer = new byte[1024];
int length = Integer.parseInt(br.readLine());
System.out.println("Message Length = " + length);
while ((ch = in.read(buffer)) != -1) {
data += new String(buffer);
cnt += ch;
if (cnt >= length) {
break;
}
}
System.out.println("Message = " + data);
} catch (IOException ex) {
}
}
}
public static void main(String[] args) {
new Server("localhost", 1234).start();
}
}
Client
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
Socket s = new Socket("localhost", 1234);
OutputStream o = s.getOutputStream();
PrintStream ps = new PrintStream(o);
String data = "your data";
ps.println(data.length());
Thread.sleep(100);
o.write(data.getBytes());
ps.close();
o.close();
} catch (Exception e) {
}
}
}
It's just a sample implementation you can wrap the concept.
I'll try to be as descriptive as possible
I'm new to android and i'm making an android application
In that application i'd like to be able to see the address of the HTTP requests going OUT from the mobile (On what website they are heading).
So i've looked around and i found out that to do that , I need to use a VPN and android 4.0+ has a VPNService supplied from google implemented using ToyVPNService
So i got this service and started changing in it so i can use it without the need of using a server
I'd like to work the VPN as follows:
1-Capture the HTTP requests
2-Read their destination
3-Resend them back to their way
So i took the VPNService and i started modifying it so that i don't need an actual server
Here's the code i'm using
package com.example.testingservice;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.VpnService;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Enumeration;
public class SO1 extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "ToyVpnService";
private Handler mHandler;
private Thread mThread;
private ParcelFileDescriptor mInterface;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
}
#Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public synchronized void run() {
Log.i(TAG,"running vpnService");
try {
runVpnConnection();
} catch (Exception e) {
e.printStackTrace();
//Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}
private boolean runVpnConnection() throws Exception {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG,"************new packet");
System.exit(-1);
while (packet.hasRemaining()) {
Log.i(TAG,""+packet.get());
//System.out.print((char) packet.get());
}
packet.limit(length);
// tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
}
Thread.sleep(50);
}
}
public String getLocalIpAddress()
{
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
Log.i(TAG,"****** INET ADDRESS ******");
Log.i(TAG,"address: "+inetAddress.getHostAddress());
Log.i(TAG,"hostname: "+inetAddress.getHostName());
Log.i(TAG,"address.toString(): "+inetAddress.getHostAddress().toString());
if (!inetAddress.isLoopbackAddress()) {
//IPAddresses.setText(inetAddress.getHostAddress().toString());
Log.i(TAG,"IS NOT LOOPBACK ADDRESS: "+inetAddress.getHostAddress().toString());
return inetAddress.getHostAddress().toString();
} else{
Log.i(TAG,"It is a loopback address");
}
}
}
} catch (SocketException ex) {
String LOG_TAG = null;
Log.e(LOG_TAG, ex.toString());
}
return null;
}
private void configure() throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
String SS=getLocalIpAddress();
builder.setMtu(1500);
// builder.addAddress("10.0.0.2", 24);
builder.addAddress(SS, 24);
// builder.addAddress(SS,24);
builder.addRoute("0.0.0.0",0);
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}}
The problem is this line
mInterface = builder.setSession("GITVPN").setConfigureIntent(mConfigureIntent).establish();
the Establish returns NULL and i can't seem to get it working
I'm thinking there is a problem with the addresses
I'd like to work it that there's no server , and there would be a tunnel that reads the packets
I've seen some other post that said i should make the addresses to 10.0.0.2 instead of external ips ( 192.168.x.x) and i should add route (0.0.0.0,0)
However the descriptor file keeps returning null and i can't seem to fix it
Any help will be appreciated , and sorry if this sounded that it was repeated but i'm super stuck and you guys are my only hope
You can't run the VpnService and establish a VPN connection without having a server that you communicate with and forwards the traffic to the internet.
Check the IP address you assigned to the interface, it should not be the same as other adapters.
What the builder operated on is a TUN device, which is created for VPN service.
So, IP address of the TUN should be proper set.
Make the address conflict with others is not a good idea.
Also, Step 3 you mentioned is not quite easy as Android not support raw socket.
just to revive an old thread...
VpnService requires a users interaction to start and won't work without it
the ToyVpnClient puts a button on the screen that the user has to click and once that's done, the Builder method will return the interface
so, steps to make it work are;
1. build a button on your app
2. onclick of that button, call VpnService.prepare(this); (this = your app context)
3. Builder.establish() will now return a VPN interface
I have two Android devices which I want to connect, using Bluetooth, and transfer data over an RFCOMM channel. I only one one device to receive data, while the other device sends it...
Using this code, I am able to connect to the other device and begin listening to an RFCOMM channel:
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket) m.invoke(device, 2);
socket.connect();
class BasicThread implements Runnable{
public void run() {
try {
InputStream stream = socket.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(stream));
while (true){
Log.d("myapp", "now listening...");
latestLine = r.readLine();
Log.d("myapp", latestLine);
}
} catch (IOException e) {
}
}
}
new Thread(new BasicThread()).run();
Using the other device, I have implemented a listening socket like this:
Method m = blue.getClass().getMethod("listenUsingRfcommOn", new Class[] { int.class });
BluetoothServerSocket socket = (BluetoothServerSocket) m.invoke(blue, 2);
BluetoothSocket sock = socket.accept();
Log.d("myapp", "Connected...\n\n\n\n\n\n\n\n");
OutputStream s = sock.getOutputStream();
final PrintWriter out = new PrintWriter(s);
They both connect on RFCOMM channel 2, and both SEE eachother, however, the second device always remains blocked at the BluetoothSocket sock = socket.accept();
Any help?
OK, I am newbie, but I can try to help. So here is my experience, I managed to connect two devices using reflection. My Android phone is receiving data using method listenUsingInsecureRfcommOn, while other devices are masters in communication and send the data over BT SPP. I had a problem with this method since it makes no visible SDP record, so I could not detect it with other devices. Because of that, I made small sniffer using Bluecove and Java SE that tries to connect to every port in given range. Here's the code:
package application.test;
import static java.lang.System.out;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
public class RfCommClient {
public static void main(String args[]) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
String add = "btspp://8C71F894A36D:";
String par = ";authenticate=false;encrypt=false;master=true";
String url = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd;HH-mm-ss-SSS");
for (int i = 1; i < 15; ++i) {
try {
url = add + i + par;
out.format("Time: %s, port = %d\n", sdf.format(System.currentTimeMillis()), i);
StreamConnection conn = (StreamConnection) Connector.open(url);
PrintStream ops = new PrintStream(conn.openOutputStream());
ops.println("Hi there...");
// response
Thread.sleep(1000);
InputStream is = conn.openInputStream();
byte[] resp = new byte[5];
int r = is.read(resp);
out.println("r = " + r + ", response = " + new String(resp, "US-ASCII"));
Thread.sleep(10 * 1000);
conn.close();
} catch (Exception e) {
out.println("Exception occured, time = " + sdf.format(System.currentTimeMillis()) + ", i = " + i);
//e.printStackTrace();
}
}
}
}
What I've learned it that some ports are taken, and that some ports can not be uses (as documentation says, e.g. port 0). For example, port 2 I believe was taken, because when I send some data to it I receive 5 chars back beginning with ERR :).
While, on the other hand, my thread is still waiting?! :)
That leads us to another thing I noticed, ports (or channels) are not always mapped to desired number. For example, to me often happened that I want to send something on port 15, but on Android, thread waiting on port 9 received the data :)
So I suggest, check which port is really allocated!
You can achieve that using the code I posted.
And another thing, here is a link to channelPicker function, which selects channel when ordinary API is used, if I am not mistaken, inside some constants should represent reserved channels.
I just noticed something, my code for registering port is slightly different, here is how I do it:
Method m = cba.getDeclaredMethod("listenUsingInsecureRfcommOn", int.class);
ss = (BluetoothServerSocket) m.invoke(BluetoothAdapter.getDefaultAdapter(), port);
Anyway, I know that this is probably too late, but, maybe someone in future has similar question.
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).