Socket & SDK minVersion - android

I coded an app before that uses the socket class to create a TCP/IP Client like this:
Socket soc;
DataOutputStream out;
DataInputStream in;
//in try-catch loop
soc = new ("192.168.1.101", 100);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
.....//code on I/O through socket
And it works fine on my previous ap, running sdk 9
Now I am trying to use the same function in my new app, which make uses of fragment and needed sdk 11. But the app crashes whenever it runs the socket code.
Once I change the android:minSdkVersion to 9 in manifest.xml, it works again. But I needed minSDK 11 for fragment.
What should I do? I have only code Android for few months, forgive me if I asked stupid question.Thanks a lot!
Edited: This is the OnClick function that triggered the Socket funcitons:
private Button.OnClickListener m_BtnConnectDisconnectOnClick = new Button.OnClickListener()
{
public void onClick(View v)
{
try
{
//Obtaining IP Address & Port number
String str_ip = m_EditPumpIP.getText().toString();
int int_port = Integer.parseInt(m_EditPumpPort.getText().toString());
//Establish Pump Connection
socket = new Socket(str_ip, int_port);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
//Update Status
m_TextSystemStatus.setText("OK");
}
catch (IOException e)
{
//Update Status
m_TextSystemStatus.setText("Fail");
}
}
};

Put this in AsyncTask
//Establish Pump Connection
socket = new Socket(str_ip, int_port);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
Like This example

Related

How to use the ip and port returned from a STUN server

hope your having a nice day . im building a Video Call application using XMPP and Jingle and direct ByteStream from phone to phone . in order to do so i noticed i need a stun server to get public ip and port of android devices and send them to the other party , im getting the public ip like this
InetAddress address = Inet4Address.getByName("stun.l.google.com");
MessageHeader sendMH = new
MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
ChangeRequest changeRequest = new ChangeRequest();
sendMH.addMessageAttribute(changeRequest);
byte[] data = sendMH.getBytes();
DatagramSocket s = new DatagramSocket(null);
localPort = s.getLocalPort();
s.setReuseAddress(true);
// s.bind(address);
DatagramPacket p = new DatagramPacket(data,
data.length,address,19302);
s.send(p);
DatagramPacket rp;
rp = new DatagramPacket(new byte[32], 32);
s.receive(rp);
MessageHeader receiveMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingResponse);
// System.out.println(receiveMH.getTransactionID().toString() + "Size:"
// + receiveMH.getTransactionID().length);
receiveMH.parseAttributes(rp.getData());
MappedAddress ma = (MappedAddress) receiveMH
.getMessageAttribute(MessageAttribute.MessageAttributeType.MappedAddress);
ip = ma.getAddress().toString();
port = ma.getPort();
Log.i("XMPP-Stabler",ma.getAddress().toString()+" "+ma.getPort());
s.close();
}catch (Exception e){
e.printStackTrace();
}
then i send the result to the other party and open up a SocketServer on this client using given port , but still i can not connect to this ServerSocket over internet , or probably i am doing some thing wrong ? can you please help me how should i use STUN or TURN results ? thanks
and here is my connecting side of Jingle just in case
otherTransport = (JingleS5BTransport)
jingle.getContents().get(0).getTransport();
ArrayList<JingleContent> contents = new ArrayList<>();
contents.add(content);
session = (JingleS5BTransportSession) JingleS5BTransportManager.getInstanceFor(connection).transportSession(new JingleSession(connection.getUser(),responderFullId,role,sessionId,contents) {
#Override
public XMPPConnection getConnection() {
return connection;
}
#Override
public void onTransportMethodFailed(String namespace) {
Log.i("XMPP-Stabler","transport method failed "+namespace);
}
});
session.setTheirProposal(otherTransport);
session.initiateOutgoingSession(new JingleTransportInitiationCallback() {
#Override
public void onSessionInitiated(BytestreamSession bytestreamSession) {
Log.i("XMPP-Stabler","ON SESSION INITIATED 2!");
Socks5BytestreamSession session = (Socks5BytestreamSession) bytestreamSession;
}
#Override
public void onException(Exception e) {
e.printStackTrace();
}
});

serversocket to bluetooth serversocket

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

server socket multithreading confuses with the devices

I'm writing an Android app using sockets for communication. In a class called sever I accept clients (android devices) and open sockets for them.
Server side:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Socket socket = serverSocket.accept();
Client clientThread = new Client(socket);
System.out.println("New client: " + clientThread.getName());
new Thread(clientThread).start();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
After a succesful connection the user may create a group, which is like a room for number of clients to connect and play together.
The group creation is done here:
Server side:
Client:
private void client_create() {
this.mGroup = new Group();
mGroup.joinPlayer(this);
System.out.println("New group for: " + name);
}
Group:
public Group(int nClients){
// Clients in this group
this.clients = new ArrayList<Client>();
}
public void joinPlayer(Client player){
clients.add(player);
}
Client Side:
Connection handling:
try {
socket = new Socket(hostName, portNumber);
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
Listener listener = new Listener();
new Thread(listener).start();
} catch (IOException e) {
e.printStackTrace();
}
I ran this programm on 2 android devices and on my localhost as the server. After the connection was made, I tried creating 2 independent different groups. While debugging it all seems legit until I reached to a point where I lost it due to the 2 different running threads.
The odd thing that happened is that after the first group was created with the first client (clients contains the first device client object), and then the second group with the second player (clients contains the second device client object), the first group clients array contains the second client object (from the second device).
Have you got any thoughts on that? Did I do something wrong?
Figured it out.
Clients was mistakly defined as static, so I guess when accessing to the clients array of the static object it received the last one who was created.

Send keystrokes from android device to PC without "stutter"

I'm working on an android app that when a button in the app is pressed, sends a key stroke to a server listing on the PC. Everything is working fine expect for a problem of the output "stuttering" when the button is pressed rapidly. If on the client is press rapidly, the server will "stutter" and sometimes simply become unresponsive. The cod I'm using is extremely simple. To simple?
Server side:
ServerSocket welcomeSocket = new ServerSocket(6789);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
keyin = inFromClient.readLine();
robby.translateAndForward(keyin);
}
}
catch (Exception ex)
....
On the client
public class ImageBoundListener implements OnTouchListener {
private ImageView view;
private static PadClient client;
The On Touch Event handler
#Override
public boolean onTouch(View view, MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;;
if (client==null)
{
client=new PadClient();
}
if (action==MotionEvent.ACTION_DOWN)
{
client.sender("A");
}
Integer actionCode = action & MotionEvent.ACTION_MASK;
Log.d(actionCode.toString()," Event occured on: "+view.getTag());
return true;
}
}
The Actual send implementation
try{
Socket clientSocket = new Socket("192.168.1.104", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Writing bytes to the server..");
outToServer.writeBytes(send);
clientSocket.close();
}
Not sure where to go from here...
There are several issues with your code:
Your code is opening connection every time button is pressed. If it is pressed rapidly - a lot of connections will be opened simultaneously between client and server.
It would be better to make one persistent connection and send all the data through it.
Also you can add some sort of buffering on the client side. I mean that data from several button presses will be combined into one data packet and sent to the server.
When dealing with communication problems between client and server - network I/O logging (what was sent and what was received on either side) is very important.
You server side can look like this:
try {
ServerSocket welcomeSocket = new ServerSocket(6789);
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
while(true) {
keyin = inFromClient.readLine();
Log.d("SERVER"," received: '" + keyin + "'");
robby.translateAndForward(keyin);
}
}
catch (Exception ex) {}

RFCOMM connection between two Android devices?

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.

Categories

Resources