At the moment I'm trying to create a little socket application for my Android device.
I would like to send large files (~500MB) via a socket connection to my Laptop/PC or whatever. I'm using a socket client on my Android device to connect to my socket server on my PC but, when I try to send a test field (~460MB) my app crashes and it says:
"Throwing OutOfMemoryError "Failed to allocate a 441616290 byte
allocationwith 4194304 free bytes and 90MB until OOM""
I guess my client cannot handle this file-size. So my question: is there a way to handle such big files with a TCP socket connection?. My Code works fine with little files (e.g 5MB) but it fails with bigger files.
This is what I have so far:
Client side running on my android device:
private class Connecting extends AsyncTask<String, Integer, String>
{
#Override
protected String doInBackground(String... serverAdd)
{
String filePath = "Path to file";
File sdFile = new File(filePath);
try {
client = new Socket("ip", "port");
outputStream = client.getOutputStream();
byte[] buffer = new byte[1024];
FileInputStream in = new FileInputStream(sdFile);
int rBytes;
while((rBytes = in.read(buffer, 0, 1024)) != -1)
{
outputStream.write(buffer, 0, rBytes);
}
outputStream.flush();
outputStream.close();
client.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Server side:
public class Main {
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStream inputStream;
private static FileOutputStream fileOutputStream;
private static BufferedOutputStream bufferedOutputStream;
private static int filesize = 10000000;
private static int bytesRead;
private static int current = 0;
public static void main(String[] args) throws IOException {
serverSocket = new ServerSocket(10898);
System.out.println("Server started. Listening to the port 10898");
clientSocket = serverSocket.accept();
byte[] mybytearray = new byte[filesize];
inputStream = clientSocket.getInputStream();
fileOutputStream = new FileOutputStream("E:\\output.zip");
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
System.out.println("Receiving...");
bytesRead = inputStream.read(mybytearray, 0, mybytearray.length);
current = bytesRead;
do {
bytesRead = inputStream.read(mybytearray, current, (mybytearray.length - current));
if (bytesRead >= 0) {
current += bytesRead;
}
} while (bytesRead > -1);
bufferedOutputStream.write(mybytearray, 0, current);
bufferedOutputStream.flush();
bufferedOutputStream.close();
inputStream.close();
clientSocket.close();
serverSocket.close();
System.out.println("Sever recieved the file");
}
}
Greetz
[EDIT]: Client code.
Here is sample code for Java on how to chunk a file up. You can adopt this to your TCP/IP client-server application. More on chunking is available here (Java - Read file by chunks?), where I took the sample from.
char[] myBuffer = new char[1024];
int bytesRead = 0;
BufferedReader in = new BufferedReader(new FileReader("foo.txt"));
while ((bytesRead = in.read(myBuffer, 0, 1024)) != -1)
{
...
}
Related
I'm trying to send multiple files from client to server using socket but when I click upload button it adds only one file second
Your copyFile() is not suitable for network transmissions.
You need to get rid of the two close() calls inside of copyFile(). On the client side, out.close() is closing the socket after the 1st file has been sent. On the server side, InputStream.close() is closing the socket after the 1st file has been received. It is the caller's responsibility to close the streams it passes to copyFile(), it is not copyFile()'s responsibility.
More importantly, for each file the client wants to send, copyFile() is not sending the file's byte count before sending the file's actual bytes, to indicate where each file ends and the next begins. So, on the server side, copyFile() does not know when to stop reading from the inputStream and will just keep reading endlessly until the connection is closed/broken.
As-is, copyFile() may work for copying files from one folder to another on the local system, but it is not suitable for copying files over a TCP network.
Try this instead:
Client side:
try {
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Log.d(TAG, "Client socket - " + socket.isConnected());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(fileUri.size());
for(String file : fileUri)
{
//long length = file.length();
//dos.writeLong(length);
String name = file;
dos.writeUTF(name);
File f = new File(file);
sendFile(f, dos);
}
dos.close();
Log.d(TAG, "Client: Data written");
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
}
finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
}
catch (IOException e) {
// Give up
e.printStackTrace();
}
}
}
}
void sendFile(File in, DataOutputStream out) throws IOException {
long fileLength = in.length();
out.writeLong(fileLength);
FileInputStream fis = new FileInputStream(in);
BufferedInputStream bis = new BufferedInputStream(fis);
byte buf[] = new byte[1024];
int len;
while (fileLength > 0) {
len = bis.read(buf);
if (len == -1) throw new IOException();
out.write(buf, 0, len);
fileLength -= len;
}
}
Server side:
try {
ServerSocket serverSocket = new ServerSocket(8988);
Socket client = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for(int i = 0; i < filesCount; i++)
{
Log.d(TAG, "doInBackground: " + filesCount);
//long fileLength = dis.readLong();
String fileName = dis.readUTF();
files[i] = new File(context.getExternalFilesDir("received"), Long.toString(System.currentTimeMillis()) + ".mp4" );
Log.d(TAG, "doInBackground: 1" );
File dirs = new File(context.getPackageName() + files[i].getParent());
Log.d(TAG, "doInBackground: 2" );
if (!dirs.exists()) dirs.mkdirs();
files[i].createNewFile();
Log.d(TAG, "server: copying files " + files[i].toString());
receiveFile(dis, files[i]);
}
serverSocket.close();
return "done";
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
return null;
}
void receiveFile(DataInputStream in, File out) throws IOException {
long fileLength = in.readLong();
FileOutputStream fos = new FileOutputStream(out);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte buf[] = new byte[1024];
int len;
while (fileLength > 0) {
len = (fileLength >= 1024) ? 1024 : (int) fileLength;
len = in.read(buf, 0, len);
if (len == -1) throw new IOException();
bos.write(buf, 0, len);
fileLength -= len;
}
}
I'm new at android development and I'm creating simple bluetooth app that can receive xml file and save xml file values to database. But how can I receive xml file from bytes array? Is it possible? After searchinf I found this question and based ont that question I try to save byte array to file. But how I need to test it? I can't find my file in my phone.
case Constants.MESSAGE_READ:
byte[] readBuffer = (byte[]) msg.obj;
try {
String path = activity.getFilesDir() + "/myFile.xml";
Log.d("MuTestClass", path);
FileOutputStream stream = new FileOutputStream(path);
stream.write(readBuffer);
stream.close();
} catch (Exception e1) {
e1.printStackTrace();
}
break;
You can use:
class Utils{
public static InputStream openFile(String filename) throws IOException{
AssetManager assManager = getApplicationContext().getAssets();
InputStream is = null;
is = assManager.open(filename);
return new BufferedInputStream(is);
}
public static byte[] readBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
}
like this:
try {
Utils.readBytes(Utils.openFile("something.xml"));
} catch (IOException e) {
e.printStackTrace();
}
I'm a newbie in android development and encounter this problem my client wish to stream video files from his camera storage to his android phone using only LAN connection.. is this possible? for now the only thing that i can do is play a video from the storage of the phone and stream http or RTSP streams video but is it possible to stream a video file while sending it through LAN? thank you.
#Androider-I apologize for not commenting because i can't anyway this is my code for now and any kind of help will be appreciated thank you.
Edited:
Client Side
`
public class Client extends Activi
ty {
private Socket client;
private FileInputStream fileInputStream;
private BufferedInputStream bufferedInputStream;
private OutputStream outputStream;
private Button button;
private TextView text;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.button1);
text = (TextView) findViewById(R.id.textView1);
//Button press event listener
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
File file = new File("/storage/emulated/BaseAhri.jpg");
try {
client = new Socket("10.0.2.2", 4444);
byte[] mybytearray = new byte[(int) file.length()];
fileInputStream = new FileInputStream(file);
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedInputStream.read(mybytearray, 0, mybytearray.length);
outputStream = client.getOutputStream();
outputStream.write(mybytearray, 0, mybytearray.length);
outputStream.flush();
bufferedInputStream.close();
outputStream.close();
client.close();
text.setText("File Sent");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Server Side
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStream inputStream;
private static FileOutputStream fileOutputStream;
private static BufferedOutputStream bufferedOutputStream;
private static int filesize = 10000000;
private static int bytesRead;
private static int current = 0;
public static void main(String[] args) throws IOException {
serverSocket = new ServerSocket(4444);
System.out.println("Server started. Listening to the port 4444");
clientSocket = serverSocket.accept();
byte[] mybytearray = new byte[filesize];
inputStream = clientSocket.getInputStream();
fileOutputStream = new FileOutputStream("/sdcard/DCIM/Camera/BaseAhri.jpg");
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);});
System.out.println("Receiving...");
bytesRead = inputStream.read(mybytearray, 0, mybytearray.length);
current = bytesRead;
do {
bytesRead = inputStream.read(mybytearray, current, (mybytearray.length - current));
if (bytesRead >= 0) {
current += bytesRead;
}
} while (bytesRead > -1);
bufferedOutputStream.write(mybytearray, 0, current);
bufferedOutputStream.flush();
bufferedOutputStream.close();
inputStream.close();
clientSocket.close();
serverSocket.close();
System.out.println("Sever recieved the file");
}
Error Server Side
[2014-01-22 15:20:15 - AndroidSocketSERVER] ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.javacodegeeks.android.androidsocketserver/.Server }
[2014-01-22 15:20:15 - AndroidSocketSERVER] ActivityManager: Error type 3
[2014-01-22 15:20:15 - AndroidSocketSERVER] ActivityManager: Error: Activity class {com.javacodegeeks.android.androidsocketserver/com.javacodegeeks.android.androidsocketserver.Server} does not exist.
And in the client side it crashes after i send.not sure if this is an error since my server have a problem....
#Androider -Sorry for late update,Here is my resulting code where i am now able to pass the video file and control it by bits but the problem is my data are always corrupted because of a missing byte or something like that and now how do i stream it? i am not able to play the file because it is not complete? if that's the case then what is the purpose of byte controll? i hope you can help me again thx.
COde Client and Server:
serverTransmitButton = (Button) findViewById(R.id.button_TCP_server);
serverTransmitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i("Start Server Button Clicked", "yipee");
try {
// create socket
// TODO: the port should match the one in Client
ServerSocket servsock = new ServerSocket(5005);
while (true) {
Log.i("************", "Waiting...");
Socket sock = servsock.accept(); // blocks until connection opened
Log.i("************", "Accepted connection : " + sock);
// sendfile
// TODO: put the source of the file
int filesize=8192;
File myFile = new File ("/sdcard/DCIM/Camera/test.mp4");
byte [] mybytearray = new byte [filesize];
Log.i("####### file length = ", String.valueOf(myFile.length()) );
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
Log.i("************", "Sending...");
int read;
while((read = fis.read(mybytearray)) != -1){
os.write(mybytearray,0,read);
}
os.flush();
os.close();
fis.close();
bis.close();
}
} catch (IOException e) {
Log.i("Io execption ", "e: " + e);
}
Log.i("=============== the end of start ==============", "==");
}
});
clientReceiveButton = (Button) findViewById(R.id.button_TCP_client);
clientReceiveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i("Read Button Clicked", "yipee");
try {
int bufferSize;// filesize temporary hardcoded
long start = System.currentTimeMillis();
int bytesRead;
int current;
// localhost for testing
// TODO: server's IP address. Socket should match one above in server
Socket sock = new Socket("192.168.123.186",5005);
Log.i("************", "Connecting...");
// receive file
bufferSize=sock.getReceiveBufferSize();
byte [] mybytearray = new byte [bufferSize];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("/storage/emulated/0/testinggo.mp4");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
while((current = is.read(mybytearray)) >0){
bos.write(mybytearray, 0 , current);
}
bos.flush();
bos.close();
is.close();
sock.close
} catch ( UnknownHostException e ) {
Log.i("******* :( ", "UnknownHostException");
} catch (IOException e){
Log.i("Read has IOException", "e: " + e);
}
Log.i("=============== the end of read ===============", "==");
}
});
}
}
Actually it is. You will need to build your own socket server in app and play video from it. Then you will have control over byte input stream and save dowloaded part to file while same part will go to mediaplayer
hi i transferred an image from server socket to client socket between two android devices. i got the image but it is 0 bytes in size.here is my code
sender:
// LISTEN FOR INCOMING CLIENTS
Socket client = serverSocket.accept();
File myFile = new File("/sdcard/DCIM/d.png");
byte [] mybytearray = new byte[(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = client.getOutputStream();
serverStatus.setText("sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
client.close();
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Connected.");
}
});
receiver:
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connecting...");
Socket socket = new Socket(serverAddr, ServerActivity.SERVERPORT);
connected = true;
byte[] mybytearray = new byte[filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("/sdcard/j.png");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do{
bytesRead = is.read(mybytearray,current,(mybytearray.length-current));
if(bytesRead > 0){
current +=bytesRead;
}
}while(bytesRead > 0);
bos.write(mybytearray,0,current);
bos.flush();
long end = System.currentTimeMillis();
System.out.println(end-start);
bos.close();
socket.close();
while (connected) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true);
// WHERE YOU ISSUE THE COMMANDS
out.println("Hey Server!");
Log.d("ClientActivity", "C: Sent.");
} catch (Exception e) {
Log.e("ClientActivity", "S: Error", e);
}
is anything wrong in this code? thanks in advance..
is anything wrong in this code?
You bet.
byte [] mybytearray = new byte[(int)myFile.length()];
Here you are assuming (1) that the file's length fits into an int, and (2) that the file contents will fit into memory.
bis.read(mybytearray,0,mybytearray.length);
Here you are assuming the read fills the buffer.
byte[] mybytearray = new byte[filesize];
Here you are again assuming (3) that the file contents will fit into memory, and (4) that filesize is indeed the correct length of the file. You haven't shown how the receiver can possibly know that.
bytesRead = is.read(mybytearray, 0, mybytearray.length);
current = bytesRead;
do {
bytesRead = is.read(mybytearray, current, (mybytearray.length - current));
if (bytesRead > 0) {
current += bytesRead;
}
} while (bytesRead > 0);
bos.write(mybytearray, 0, current);
Here you (5) aren't checking the result of the first read and (6) pointlessly reading the entire input into a buffer. You don't need to do that. The canonical way to copy a stream in Java is as follows:
while ((count = in.read(buffer)) < 0){
out.write(buffer, 0, count);
}
It works at both ends, i.e. for sending and receiving, and with any buffer size greater than zero. Use this both for sending the file and receiving it.
I need to download a single image at time from the Internet and then save it on the SD card. How do I do it? I have made an attempt, but when I try to view that downloaded image, it shows the message, "No Preview Available". Please see my code below:
public class ImgDownloader {
private static final int IO_BUFFER_SIZE = 4 * 1024;
public static final byte[] downloadImage(String imgURL) {
byte[] data = null;
try {
Log.v("Down", "1");
InputStream in = null;
BufferedOutputStream out = null;
in = new BufferedInputStream(new URL(imgURL).openStream(), 8 * 1024);
Log.v("Down", "2");
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
Log.v("Down", "3");
data = dataStream.toByteArray();
// bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Log.v("Down", "4");
} catch (Exception ex) {
ex.printStackTrace();
// System.out.println("Exception in Image Downloader .."
// +ex.getMessage());
}
return data;
}
private static void copy(InputStream in, OutputStream out)
throws IOException {
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
}
}
Note:
i have download the image from the SSL connection.
Any ideas? Thanks in advance.
You can try something like
try{
URL url = new URL(downloadUrl); //you can write here any link
File file = new File(absolutePath); //Something like ("/sdcard/file.mp3")
//Create parent directory if it doesn't exists
if(!new File(file.getParent()).exists())
{
System.out.println("Path is created " + new File(file.getParent()).mkdirs());
}
file = new File(absolutePath); //Something like ("/sdcard/file.mp3")
file.createNewFile();
/* Open a connection to that URL. */
URLConnection ucon = url.openConnection();
/*
* Define InputStreams to read from the URLConnection.
*/
InputStream is = ucon.getInputStream();
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
FileOutputStream fos = new FileOutputStream(file);
int size = 1024*1024;
byte[] buf = new byte[size];
int byteRead;
while (((byteRead = is.read(buf)) != -1)) {
fos.write(buf, 0, byteRead);
bytesDownloaded += byteRead;
}
/* Convert the Bytes read to a String. */
fos.close();
}catch(IOException io)
{
networkException = true;
continueRestore = false;
}
catch(Exception e)
{
continueRestore = false;
e.printStackTrace();
}
Make the appropriate changes according to your requirement. I use the same code for downloading files from internet and saving it to SDCard.
Hope it helps !!