Im trying to send an image as a byte array over a socket to a client so it can view the image, and all goes well except when viewing the image its fragmented, i can view the top 10th of the image but the rest of it is grey and black pixels and i cant figure out why
heres a piece of my server code:
public synchronized void nextFrame(VideoFrame frame) {
// This method is called when a new frame is ready.
// Don't forget to recycle it when done dealing with the frame.
// draw the new frame onto the JLabel
go = true;
pic = frame.getBytes();
go = false;
label.getGraphics().drawImage(frame.getBufferedImage(), 0, 0, width, height, null);
frame.recycle();
}
}
class server extends Thread{
int port;
ServerSocket socket;
Socket temps = null;
boolean go = true;
server(int p){
port = p;
start();
}
public void run(){
while(go == true){
try {
socket = new ServerSocket(port, 10);
socket.setSoTimeout(10000);
temps = socket.accept();
new connect(temps);
port += 1;
} catch (IOException e) {
if(e.getMessage().toString().equalsIgnoreCase("Accept timed out")){
go = false;
}else{
e.printStackTrace();
}
break;
}
}
try {
socket.close();
System.out.println("Closing socket server(no more connections will be created)");
} catch (IOException e) {
e.printStackTrace();
}
}
}
class connect extends Thread{
Socket connection;
ObjectOutputStream out;
int port;
String host;
GetInput in;
connect(Socket s){
try {
connection = s;
out = new ObjectOutputStream(connection.getOutputStream());
host = connection.getInetAddress().getHostName();
port = connection.getPort();
System.out.println("Connected to " + host + ":" + port);
in = new GetInput(connection);
start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void run(){
try {
out.writeInt(Main.pic.length);
} catch (IOException e1) {
e1.printStackTrace();
}
while(in.isAlive()){
if(Main.go){
try {
out.write(Main.pic);
} catch (IOException e) {
e.getMessage().toString();
}
}
}
try {
out.close();
connection.close();
System.out.println("Closing " + host + ":" + port);
} catch (IOException e) {
e.printStackTrace();
}
}
}
class GetInput extends Thread{
ObjectInputStream in;
GetInput(Socket s){
try {
in = new ObjectInputStream(s.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
start();
}
public void run(){
try{
boolean go = in.readBoolean();
int a = (go?1:0);
System.out.println(a);
} catch (IOException e) {
e.getMessage().toString();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
i know the frame grabber is grabbing the image right because im also displaying the image on the server and it looks fine, so that means the byte arrays not getting sent over the sockets correctly, but why?
EDIT: heres my client code, its an android app
package org.smiley.doom;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
public class ClientActivity extends Activity implements View.OnClickListener{
Socket s;
InetAddress inet;
ObjectOutputStream out;
ObjectInputStream in;
TextView log;
ImageView im;
Button send;
EditText tip;
int rport;
String ip;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tip = (EditText) findViewById(R.id.etIP);
send = (Button) findViewById(R.id.bSEND);
im = (ImageView) findViewById(R.id.ivPIC);
log = (TextView) findViewById(R.id.tvLog);
s = null;
in = null;
out = null;
send.setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
switch(arg0.getId()){
case R.id.bSEND:
final int len;
try {
inet = InetAddress.getByName("192.168.0.2");
s = new Socket(inet, 4321);
in = new ObjectInputStream(s.getInputStream());
out = new ObjectOutputStream(s.getOutputStream());
log.setText("Client opened");
len = in.readInt();
new Thread(new Runnable(){
#Override
public void run() {
byte[] b = new byte[len];
try {
in.read(b);
log.setText(""+s.getReceiveBufferSize());
} catch (IOException e1) {
e1.printStackTrace();
}
final byte[] l = b;
im.post(new Runnable(){
#Override
public void run() {
Bitmap bmp = BitmapFactory.decodeByteArray(l, 0, l.length);
im.setImageBitmap(bmp);
}
});
try {
out.writeBoolean(true);
out.close();
in.close();
s.close();
//log.setText("Client closed");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
TCP only delivers as many bytes to the application as currently available. Since the underlying network layer (IP) is packet based, your stream is getting chunked into parts during transmission. Network stack on the receiving side gets these chunks (packets) off the network card and buffers them until an application reads from given socket, at which point you get min of your buffer size and what's piled up in the OS per-socket buffer.
Because TCP connection represents a stream, the OS doesn't know anything about your application messages, so it's your responsibility to reassemble everything back together.
You have to read from the socket in a loop until you know you have all your data. The easiest way to know that is to tell the client upfront how many bytes you are going to send.
Chances are your data segment (image) is much larger than your buffer.
Somehow, you have to find a way to buffer the output so you can flush it before you overflow your write buffer.
Nikolai Fetissov's answer helped me solve the issue. Here's how I got it to work:
Send a JSON (or any other format) containing the expected message
size and message type from sender to receiver. Make sure this is
short and sweet.
Immediately send your data. It could be an image/audio/video or anything.
Bonus: This will work for Android Bluetooth/Wifi Sockets too.
Code snippet to go with:
byte[] fileBuffer = null;
int bytes = 0, expectedFileSize = 0, messageType = Constants.TYPE_IMAGE;
boolean isProcessing = false;
while (isReading) {
try {
if (isProcessing) {
// Fragment arrived
byte[] buffer = new byte[1024];
int currentSize = mmInStream.read(buffer);
// Keep appending to the fileBuffer
System.arraycopy(buffer, 0, fileBuffer, bytes, currentSize);
bytes += currentSize;
if (bytes == expectedFileSize) {
// Your message is ready. Send it!
sendIt(fileBuffer, messageType);
isProcessing = false;
bytes = 0;
}
} else {
byte[] buffer = new byte[1024];
bytes = mmInStream.read(buffer);
try {
// Message is a JSON. Next set of messages will be audio or image.
JSONObject json = new JSONObject(new String(buffer, 0, bytes));
expectedFileSize = json.getInt(Constants.MESSAGE_SIZE);
messageType = json.getInt(Constants.MESSAGE_TYPE);
fileBuffer = new byte[expectedFileSize];
isProcessing = true;
bytes = 0;
} catch (JSONException e) {
// This is a normal message. Send it without processing.
sendIt(buffer, Constants.TYPE_TEXT);
isProcessing = false;
bytes = 0;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Edits to the code to optimize it further are welcome! Hope this helps.
Related
My application is a simple WiFi Direct chat. I can connect two devices, but I don't know how I should send and receive a String (not a File) in both sides (not just from client to server like the developer example)
In both sides: I just want an EditText and a Button that when clicked sends EditText.getText() to the other side
If anyone has full code, please send me a link. Thanks a lot
Android's WiFiDirectServiceDiscovery sample project does that:
package com.example.android.wifidirect.discovery;
import android.os.Handler;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* Handles reading and writing of messages with socket buffers. Uses a Handler
* to post messages to UI thread for UI updates.
*/
public class ChatManager implements Runnable {
private Socket socket = null;
private Handler handler;
public ChatManager(Socket socket, Handler handler) {
this.socket = socket;
this.handler = handler;
}
private InputStream iStream;
private OutputStream oStream;
private static final String TAG = "ChatHandler";
#Override
public void run() {
try {
iStream = socket.getInputStream();
oStream = socket.getOutputStream();
byte[] buffer = new byte[1024];
int bytes;
handler.obtainMessage(WiFiServiceDiscoveryActivity.MY_HANDLE, this)
.sendToTarget();
while (true) {
try {
// Read from the InputStream
bytes = iStream.read(buffer);
if (bytes == -1) {
break;
}
// Send the obtained bytes to the UI Activity
Log.d(TAG, "Rec:" + String.valueOf(buffer));
handler.obtainMessage(WiFiServiceDiscoveryActivity.MESSAGE_READ,
bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void write(byte[] buffer) {
try {
oStream.write(buffer);
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
}
Ive been trying to setup a server using ESP8266 wifi module on a particular port. I'm done with that.
I want to receive the message from it now.
Whenever I connect using socket.connect(), I am able to detect it in the esp8266. But I cant receive any message, the server sends through the same socket.
I am trying to obtain the message using DataInputStream inside a while loop continuously in a async task.Pls let me know if my approach or code is wrong! Thanks!
This is my code:
package test.espclient;
import java.io.DataInputStream;
//import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
TextView textResponse;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonClear,buttonDiscon , buttonSendMsg;
EditText welcomeMsg;
Socket socket;
boolean socketStatus = false;
MyClientTask myClientTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText) findViewById(R.id.address);
editTextPort = (EditText) findViewById(R.id.port);
buttonConnect = (Button) findViewById(R.id.connect);
buttonClear = (Button) findViewById(R.id.clear);
buttonDiscon = (Button) findViewById(R.id.closeSocket);
buttonSendMsg = (Button) findViewById(R.id.sendMsg);
textResponse = (TextView) findViewById(R.id.response);
welcomeMsg = (EditText)findViewById(R.id.welcomemsg);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonDiscon.setOnClickListener(buttonDisconnectOnCLickListener);
//buttonSendMsg.setOnClickListener(sendMessage);
buttonClear.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
textResponse.setText("");
}
});
}
OnClickListener buttonConnectOnClickListener = new OnClickListener() {
#Override
public void onClick(View arg0) {
if(socketStatus)
Toast.makeText(MainActivity.this,"Already talking to a Socket!! Disconnect and try again!", Toast.LENGTH_LONG).show();
else {
socket = null;
String address = editTextAddress.getText().toString();
int port = Integer.parseInt(editTextPort.getText().toString());
String tMsg = welcomeMsg.getText().toString();
if (address == null || port == 0)
Toast.makeText(MainActivity.this, "Please enter valid address/port", Toast.LENGTH_LONG).show();
else {
myClientTask = new MyClientTask(address,port,tMsg);
myClientTask.execute();
} //else when no active socket conn. and credentials are validated.
} //else when already active socket conn.
}
};
OnClickListener buttonDisconnectOnCLickListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (!socketStatus)
Toast.makeText(MainActivity.this, "SOCKET Already Closed!!", Toast.LENGTH_SHORT).show();
else {
try {
onDisconnect();
if(myClientTask.isCancelled()) {
socket.close();
Toast.makeText(MainActivity.this, "Socket Closed!", Toast.LENGTH_SHORT).show();
socketStatus = false;
}
else
{
Toast.makeText(MainActivity.this, "Couldn't Disconnect! Pls try again!", Toast.LENGTH_SHORT).show();
socketStatus = true;
}
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this,e.toString(), Toast.LENGTH_SHORT).show();
}
}
}
};
// OnClickListener sendMessage = new OnClickListener() {
// #Override
// public void onClick(View v) {
// String msg = welcomeMsg.toString();
// if(msg.equals(""))
// {
// Toast.makeText(MainActivity.this, "Message is empty!!!", Toast.LENGTH_SHORT).show();
// }
// else if(!socketStatus)
// {
// Toast.makeText(MainActivity.this, "Please Establish Socket Connection first!", Toast.LENGTH_SHORT).show();
// }
// else
// {
// MyClientTask myClientTask = new MyClientTask(editTextAddress
// .getText().toString(), Integer.parseInt(editTextPort
// .getText().toString()),
// msg);
// myClientTask.execute();
//
// }
//
// }
// };
public void onDisconnect()
{
myClientTask.cancel(true);
}
public class MyClientTask extends AsyncTask<Void, String, Void> {
String dstAddress;
int dstPort;
String response ="";
String msgToServer;
MyClientTask(String addr, int port, String msgTo) {
dstAddress = addr;
dstPort = port;
msgToServer = msgTo;
Log.w("MSG","Entering async task");
}
#Override
protected Void doInBackground(Void... arg0) {
// DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket(dstAddress, dstPort);
socketStatus = true;
// dataOutputStream = new DataOutputStream(socket.getOutputStream());
// if(msgToServer != null){
// dataOutputStream.writeUTF(msgToServer);
// }
}
catch (UnknownHostException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
socketStatus = false;
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}
Log.w("MSG","Inside while loop for retrieving data");
while(!isCancelled()){
try {
dataInputStream = new DataInputStream(socket.getInputStream());
response = dataInputStream.readUTF();
if(!response.isEmpty())
{
publishProgress(response);
Log.w("Data:",response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// if (dataOutputStream != null) {
// try {
// dataOutputStream.close();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Log.w("MSG","Stopping async task");
socket.close();
socketStatus = false;
} catch (IOException e) {
e.printStackTrace();
socketStatus = true;
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
textResponse.setText(values[0]);
Toast.makeText(MainActivity.this,"Server:"+values[0],Toast.LENGTH_LONG).show();
Log.w("MSG","Updating with msg");
}
#Override
protected void onPostExecute(Void result) {
Log.w("MSG","On postExecute method..");
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
UPDATE(16-12-15) I made the following changes under the doInBackground().
originally, I used DataInputStream, now I replaced it with BufferedReader.
The change was made under the while loop part for constantly checking the socket input stream. Also added the ESP8266 code for reference.
Now I able to Receive the text sent from ESP8266, but it reaches only after I send 3 or 4 messages via CIPSEND cmd. for e.g. if i send "hi", "hello" "yo", after sending the third word, I receive all the words together as "hihelloyo"
Instead of recieving each message as soon as it is sent, I receive it very late.
I am not sure what exactly is causing this problem. May be the buffer size?
How to solve this ?
MODIFIED CODE:
protected Void doInBackground(Void... arg0) {
// DataOutputStream dataOutputStream = null;
// DataInputStream dataInputStream = null;
try {
socket = new Socket(dstAddress, dstPort);
socketStatus = true;
// dataOutputStream = new DataOutputStream(socket.getOutputStream());
// if(msgToServer != null){
// dataOutputStream.writeUTF(msgToServer);
// }
}
catch (UnknownHostException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
socketStatus = false;
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}
Log.w("MSG","Inside while loop for retrieving data");
while(!isCancelled() && socketStatus) {
try {
// dataInputStream = new DataInputStream(socket.getInputStream());
// response = dataInputStream.readUTF();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
response = br.readLine();
if (!response.isEmpty()) {
publishProgress(response);
Log.w("Data:", response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
ESP266 code
#include <AltSoftSerial.h>
AltSoftSerial ESP8266 ;//(8,9)|Rx,Tx
int LED = 13;
boolean FAIL_8266 = false;
#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];
String ssid="\"SSID\"";
String pass="\"PASSWORD\"";
void clearESP8266SerialBuffer()
{
Serial.println("= clearESP8266SerialBuffer() =");
while (ESP8266.available() > 0) {
char a = ESP8266.read();
Serial.write(a);
}
Serial.println("==============================");
}
void sendHTTPResponse(int id, String content)
{
String response;
response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: text/html; charset=UTF-8\r\n";
response += "Content-Length: ";
response += content.length();
response += "\r\n";
response +="Connection: close\r\n\r\n";
response += content;
String cmd = "AT+CIPSEND=";
cmd += id;
cmd += ",";
cmd += response.length();
Serial.println("--- AT+CIPSEND ---");
sendESP8266Cmdln(cmd, 1000);
Serial.println("--- data ---");
sendESP8266Data(response, 1000);
}
boolean waitOKfromESP8266(int timeout)
{
do{
Serial.println("wait OK...");
delay(1000);
if(ESP8266.find("OK"))
{
return true;
}
}while((timeout--)>0);
return false;
}
//Send command to ESP8266, assume OK, no error check
//wait some time and display respond
void sendESP8266Cmdln(String cmd, int waitTime)
{
ESP8266.println(cmd);
delay(waitTime);
clearESP8266SerialBuffer();
}
//Basically same as sendESP8266Cmdln()
//But call ESP8266.print() instead of call ESP8266.println()
void sendESP8266Data(String data, int waitTime)
{
ESP8266.print(data);
delay(waitTime);
clearESP8266SerialBuffer();
}
void adc()
{
int ldr;
for(int i=0;i<=3;i++)
{
ldr = analogRead(A0);
sendESP8266Cmdln("AT+CIPSEND=0,5",1000);
sendESP8266Cmdln(String(ldr),1000);
delay(1000);
}
}
void setup()
{
Serial.begin(9600);
ESP8266.begin(9600);
pinMode(LED,OUTPUT);
do{
ESP8266.println("AT+RST");
delay(1000);
if(ESP8266.find("Ready"))
{
Serial.println("Module is ready");
delay(1000);
clearESP8266SerialBuffer();
sendESP8266Cmdln("AT+CWMODE=1",1000);
//Join Wifi network
sendESP8266Cmdln("AT+CWJAP="+ssid+","+pass,6500);
//Get and display my IP
sendESP8266Cmdln("AT+CIFSR", 1000);
//Set multi connections
sendESP8266Cmdln("AT+CIPMUX=1", 1000);
//Setup web server on port 80
sendESP8266Cmdln("AT+CIPSERVER=1,3333",1000);
Serial.println("Server setup finish");
FAIL_8266 = false;
}else{
Serial.println("Module have no response.");
delay(500);
FAIL_8266 = true;
}
}while(FAIL_8266);
digitalWrite(LED, HIGH);
ESP8266.setTimeout(1000);
}
void loop() {
// listen for communication from the ESP8266 and then write it to the serial monitor
if(ESP8266.available()) // check if the esp is sending a message
{
String msg = ESP8266.readString();
if(msg.substring(0,4)=="Link")
Serial.println("Client connected!");
else if(msg.substring(0,6)=="Unlink")
Serial.println("Client Disconncected!!");
else if(msg.substring(1,5)=="+IP")
{
Serial.println("Client says: "+msg.substring(9,14));
}
else
{
// Serial.println("Calling ADC.!");
//adc();
// Serial.println("Msg:"+msg.charAt(0)+msg.charAt(1)+msg.charAt(2)+msg.charAt(3));
// Serial.println("Something recieved!: "+msg.substring(1,2));
Serial.println("MSG:"+msg);
}
}
// listen for user input and send it to the ESP8266
if ( Serial.available() ) { ESP8266.write( Serial.read() ); }
}
//Clear and display Serial Buffer for ESP8266
UPDATE(17-12-15):Added pics for reference
My arduino serial window showing the AT+CIPSEND commands.
pic of the app running on phone.
As to this comment:
... it worked! I can get the messages immediately irrespective of their lengths, after i close the connection on esp side using cipclose=0. But is this is the only way? Is it possible to make the device and the app talk? How come it is possible in the telnet application, where i can continuously send data till i close connection on one side.?
On the upper application layers data from TCPIP connection is presented as a Stream. Using this stream with well-defined application protocols like HTTP or telnet, message exchange is defined. In your case basically Android side does not know what amount of data to receive. After using buffered reader you get buffered answer, not the whole.
In telnet protocol for example there are control commands. Thus the system goes on working.
To solve your case:
Close connection after every message. (this slows down things)
Implement a basic application protocol. For example: Implement a Message frame:
FRAME
1st byte : length ( this byte gives the length of the payload )
2nd...255th byte : payload ( this is the actual message )
LOGIC
-Sender packs the frame giving length and payload.
-Sender sends the data
...
-Receiver queries for the available bytes.
-When available bytes are >1 receive only 1 byte say it is 'n'
-'n' is the length of the total frame
-Read 'n' bytes from the stream. if EOF then return what is received.
In addition to this you can implement control commands.
For example you may want the receiver to close the connection so your frame can be:
Byte 1 : length
Byte 2 : command (0=nothing, 1=close conn)
Byte 3..n : payload
LOGIC
-When receiver finished receiving and command is 1 then closes the connection.
The app I have found online works flawlessly except when clicking onto the Send Button, after typing something into the textbox, the printer runs, and stops in the middle of the process of printing, program doesn't crash however. I'm just curious if I'm using the wrong UUID, in fact I don't even know what it is. I have this following class, which is the only class needed to run the app, the rest are XML, with all three bluetooth permissions;
package com.example.bluetoothprinter;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Button;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
public class MainActivity extends Activity {
// will show the statuses
TextView myLabel;
// will enable user to enter any text to be printed
EditText myTextbox;
// android built in classes for bluetooth operations
BluetoothAdapter mBluetoothAdapter;
BluetoothSocket mmSocket;
BluetoothDevice mmDevice;
OutputStream mmOutputStream;
InputStream mmInputStream;
Thread workerThread;
byte[] readBuffer;
int readBufferPosition;
int counter;
volatile boolean stopWorker;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
// we are goin to have three buttons for specific functions
Button openButton = (Button) findViewById(R.id.open);
Button sendButton = (Button) findViewById(R.id.send);
Button closeButton = (Button) findViewById(R.id.close);
myLabel = (TextView) findViewById(R.id.label);
myTextbox = (EditText) findViewById(R.id.entry);
// open bluetooth connection
openButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
findBT();
openBT();
} catch (IOException ex) {
}
}
});
// send data typed by the user to be printed
sendButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
sendData();
} catch (IOException ex) {
}
}
});
// close bluetooth connection
closeButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
closeBT();
} catch (IOException ex) {
}
}
});
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* This will find a bluetooth printer device
*/
void findBT() {
try {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
myLabel.setText("No bluetooth adapter available");
}
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 0);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter
.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// OJL411MY29I911JH is the name of the bluetooth printer device shown after scan
if (device.getName().equals("OJL411MY29I911JH")) {
mmDevice = device;
break;
}
}
}
myLabel.setText("Bluetooth Device Found");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* Tries to open a connection to the bluetooth printer device
*/
void openBT() throws IOException {
try {
// Standard SerialPortService ID
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
mmSocket.connect();
mmOutputStream = mmSocket.getOutputStream();
mmInputStream = mmSocket.getInputStream();
beginListenForData();
myLabel.setText("Bluetooth Opened");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* After opening a connection to bluetooth printer device,
* we have to listen and check if a data were sent to be printed.
*/
void beginListenForData() {
try {
final Handler handler = new Handler();
// This is the ASCII code for a newline character
final byte delimiter = 10;
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()
&& !stopWorker) {
try {
int bytesAvailable = mmInputStream.available();
if (bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
for (int i = 0; i < bytesAvailable; i++) {
byte b = packetBytes[i];
if (b == delimiter) {
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0,
encodedBytes, 0,
encodedBytes.length);
final String data = new String(
encodedBytes, "US-ASCII");
readBufferPosition = 0;
handler.post(new Runnable() {
public void run() {
myLabel.setText(data);
}
});
} else {
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException ex) {
stopWorker = true;
}
}
}
});
workerThread.start();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* This will send data to be printed by the bluetooth printer
*/
void sendData() throws IOException {
try {
// the text typed by the user
String msg = myTextbox.getText().toString();
msg += "\n";
mmOutputStream.write(msg.getBytes());
// tell the user data were sent
myLabel.setText("Data Sent");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* Close the connection to bluetooth printer.
*/
void closeBT() throws IOException {
try {
stopWorker = true;
mmOutputStream.close();
mmInputStream.close();
mmSocket.close();
myLabel.setText("Bluetooth Closed");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I added code to run closeBT function at the end of the sendData function. if you don't close the connection, I think it is hanging in the process of sending.
void sendData() throws IOException {
try {
// the text typed by the user
String msg = myTextbox.getText().toString();
msg += "\n";
mmOutputStream.write(msg.getBytes());
// tell the user data were sent
myLabel.setText("Data Sent");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
I want to created simple Android bluetooth Client-Server program
Server Code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1=(TextView)findViewById(R.id.textView1);
tv2=(TextView)findViewById(R.id.textView2);
mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
try {
mBluetoothServerSocket=mBluetoothAdapter.listenUsingRfcommWithServiceRecord(name,uUID);
mBluetoothAdapter.cancelDiscovery();
mBluetoothSocket=mBluetoothServerSocket.accept();
mInputStream=mBluetoothSocket.getInputStream();
//if(mInputStream.available()>0){
mBufferedReader=new BufferedReader(new InputStreamReader(mInputStream));
data = mBufferedReader.readLine();
tv1.setText(data);
//}
if(mInputStream.available()>0){
data=mBufferedReader.readLine();
tv2.setText(data);
x++;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Client Code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lb=(Button)findViewById(R.id.button1);
btAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = btAdapter.getRemoteDevice(addressHTC);
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btAdapter.cancelDiscovery();
btSocket.connect();
String message = "Hello.............. from....... Android......\n";
outStream = btSocket.getOutputStream();
byte[] msgBuffer = message.getBytes();
outStream.write(msgBuffer);
}
catch(IOException e){
e.printStackTrace();
}
lb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String m1="msg 2";
byte[] msgBuffer = m1.getBytes();
try {
outStream.write(msgBuffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
This application work in one side mode, just Send message to server and show received buffer, But i need to Send back some messages from server to client continuously.
How to do it?
if you have any idea. please share it.
This is works for me for contineously reading. Try it.
try {
BufferedReader Reader = new BufferedReader(
new InputStreamReader(mmSocket.getInputStream()));
while(true)
{
String receivedMsg;
while((receivedMsg = Reader.readLine()) != null)
{
// what you do with your message
}
}
} catch (Exception ex) {
System.out.println(ex);
}
you should have a different thread for listening which will send the message to the activity, this thread can be also the thread sending messages.
that way your the UI wont get stuck and you could receive messages continuously.
an example of such thread:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.util.Log;
public class MessageManager extends Thread {
private static final String TAG = "MessageListener thread";
private BluetoothSocket btConnectedSocket;
private InputStream inStream;
private OutputStream outStream;
private Activity parent;
private boolean run = true;
public MessageManager(BluetoothSocket btConnectedSocket, Activity parent) throws IOException {
this.btConnectedSocket = btConnectedSocket;
this.parent = parent;
inStream = btConnectedSocket.getInputStream();
outStream = btConnectedSocket.getOutputStream();
}
/* this method will listen continuously to messages received through the BT socket until you call cancel
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while (run) {
try {
bytes = inStream.read(buffer);
}
catch(IOException ex) {
Log.e(TAG, "error while reading from bt socket");
}
parent.doStuffWithTheMessage(buffer); // pay attention: its in bytes. u need to convert it to a string
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) throws IOException{
outStream.write(bytes);
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
run = false;
try {
btConnectedSocket.close();
} catch (IOException e) { }
}
}
I am trying to implement code that can recognize different URL requests and perform different actions upon each request, for example, take picture by accessing http://192.168.0.120/pic , and send email by accessing via http://192.168.0.120/email
I already built the code for taking picture and sending email but not sure how to assign them to different URL requests?
I found one code that can run a web server to recognize only one IP address and i want to to modified it to recognize multiple IP addresses and perform different actions upon each request:
The Code:
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class Server extends Thread {
private ServerSocket listener = null;
private static Handler mHandler;
private boolean running = true;
public static LinkedList<Socket> clientList = new LinkedList<Socket>();
public Server(String ip, int port, Handler handler) throws IOException {
super();
mHandler = handler;
InetAddress ipadr = InetAddress.getByName(ip);
listener = new ServerSocket(port,0,ipadr);
}
private static void send(String s) {
Message msg = new Message();
Bundle b = new Bundle();
b.putString("msg", s);
msg.setData(b);
mHandler.sendMessage(msg);
}
#Override
public void run() {
while( running ) {
try {
Socket client = listener.accept();
new ServerHandler(client).start();
LockStatus.getInstance().setMyVar(true);
clientList.add(client);
} catch (IOException e) {
}
}
}
public void stopServer() {
running = false;
LockStatus.getInstance().setMyVar(false);
try {
listener.close();
} catch (IOException e) {
}
}
Thanks a lot
Here is the modification of the code, but still cannot recognize the IP address:
public void run() {
try {
serverSocket = new ServerSocket(SERVERPORT);
while (running) {
// LISTEN FOR INCOMING CLIENTS
Socket client = serverSocket.accept();
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
String line = null;
String IP = "192.168.0.111";
line = in.readLine();
if (line.equals(IP)) {
new ServerHandler(client).start();
LockStatus.getInstance().setMyVar(true);
Log.i(TAG, "IP Receive=" + line);
// Toast.makeText(getContext(), "Matches",
// Toast.LENGTH_SHORT).show();
} else {
Log.i(TAG, " IP not received :=" + line);
// Toast.makeText(getApplicationContext(), line +" != "+
// IP, Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}