Monday, January 26, 2015

Transfer image between Android devices, via Socket

The post "File transfer via Socket, between Android devices" show how to send text file between Android devices using Socket. In this example, we are going to send image file of "png" via Socket, with ObjectOutputStream in server side and ObjectInputStream in client side.


The png file is fixed "android-er_sketch_1000.png" at ExternalStorageDirectory in server, and received file in client will be save as "test.png" at ExternalStorageDirectory.

android-er_sketch_1000.png
Here I list the MainActivity of both server and client. For the layout files, refer to the example of "File transfer via Socket, between Android devices".

Server side MainActivity.java
package com.example.androidsocketfiletransferserver;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.Environment;
import android.widget.TextView;
import android.widget.Toast;

/*
 * Permission needed:
 * <uses-permission android:name="android.permission.INTERNET"/>
 * <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 */

public class MainActivity extends ActionBarActivity {

 TextView infoIp, infoPort;

 static final int SocketServerPORT = 8080;
 ServerSocket serverSocket;
 
 ServerSocketThread serverSocketThread;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  infoIp = (TextView) findViewById(R.id.infoip);
  infoPort = (TextView) findViewById(R.id.infoport);

  infoIp.setText(getIpAddress());
  
  serverSocketThread = new ServerSocketThread();
  serverSocketThread.start();
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  
  if (serverSocket != null) {
   try {
    serverSocket.close();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }

 private String getIpAddress() {
  String ip = "";
  try {
   Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
     .getNetworkInterfaces();
   while (enumNetworkInterfaces.hasMoreElements()) {
    NetworkInterface networkInterface = enumNetworkInterfaces
      .nextElement();
    Enumeration<InetAddress> enumInetAddress = networkInterface
      .getInetAddresses();
    while (enumInetAddress.hasMoreElements()) {
     InetAddress inetAddress = enumInetAddress.nextElement();

     if (inetAddress.isSiteLocalAddress()) {
      ip += "SiteLocalAddress: "
        + inetAddress.getHostAddress() + "\n";
     }

    }

   }

  } catch (SocketException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   ip += "Something Wrong! " + e.toString() + "\n";
  }

  return ip;
 }
 
 public class ServerSocketThread extends Thread {

  @Override
  public void run() {
   Socket socket = null;
   
   try {
    serverSocket = new ServerSocket(SocketServerPORT);
    MainActivity.this.runOnUiThread(new Runnable() {

     @Override
     public void run() {
      infoPort.setText("I'm waiting here: " 
       + serverSocket.getLocalPort());
     }});
    
    while (true) {
     socket = serverSocket.accept();
     FileTxThread fileTxThread = new FileTxThread(socket);
     fileTxThread.start();
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } finally {
    if (socket != null) {
     try {
      socket.close();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   }
  }

 }
 
 public class FileTxThread extends Thread {
  Socket socket;
  
  FileTxThread(Socket socket){
   this.socket= socket;
  }

  @Override
  public void run() {
   File file = new File(
     Environment.getExternalStorageDirectory(), 
     "android-er_sketch_1000.png");
   
   byte[] bytes = new byte[(int) file.length()];
   BufferedInputStream bis;
   try {
    bis = new BufferedInputStream(new FileInputStream(file));
    bis.read(bytes, 0, bytes.length);
    
    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 
    oos.writeObject(bytes);
    oos.flush();
    
    socket.close();
    
    final String sentMsg = "File sent to: " + socket.getInetAddress();
    MainActivity.this.runOnUiThread(new Runnable() {

     @Override
     public void run() {
      Toast.makeText(MainActivity.this, 
        sentMsg, 
        Toast.LENGTH_LONG).show();
     }});
    
   } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } finally {
    try {
     socket.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   
  }
 }
}

download filesDownload the files in Server side.


Client side MainActivity.java
package com.example.androidsocketfiletransferclient;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import android.support.v7.app.ActionBarActivity;
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;
import android.os.Bundle;
import android.os.Environment;

/*
 * Permission needed:
 * <uses-permission android:name="android.permission.INTERNET"/>
 * <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 */

public class MainActivity extends ActionBarActivity {

 EditText editTextAddress;
 Button buttonConnect;
 TextView textPort;

 static final int SocketServerPORT = 8080;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  editTextAddress = (EditText) findViewById(R.id.address);
  textPort = (TextView) findViewById(R.id.port);
  textPort.setText("port: " + SocketServerPORT);
  buttonConnect = (Button) findViewById(R.id.connect);
  
  buttonConnect.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    ClientRxThread clientRxThread = 
     new ClientRxThread(
      editTextAddress.getText().toString(), 
      SocketServerPORT);
    
    clientRxThread.start();
   }});
 }

 private class ClientRxThread extends Thread {
  String dstAddress;
  int dstPort;

  ClientRxThread(String address, int port) {
   dstAddress = address;
   dstPort = port;
  }

  @Override
  public void run() {
   Socket socket = null;
   
   try {
    socket = new Socket(dstAddress, dstPort);
    
    File file = new File(
      Environment.getExternalStorageDirectory(), 
      "test.png");

    ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
    byte[] bytes;
    FileOutputStream fos = null;
    try {
     bytes = (byte[])ois.readObject();
     fos = new FileOutputStream(file);
     fos.write(bytes);
    } catch (ClassNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    } finally {
     if(fos!=null){
      fos.close();
     }
     
    }

       socket.close();
       
       MainActivity.this.runOnUiThread(new Runnable() {

     @Override
     public void run() {
      Toast.makeText(MainActivity.this, 
        "Finished", 
        Toast.LENGTH_LONG).show();
     }});
    
   } catch (IOException e) {

    e.printStackTrace();
    
    final String eMsg = "Something wrong: " + e.getMessage();
    MainActivity.this.runOnUiThread(new Runnable() {

     @Override
     public void run() {
      Toast.makeText(MainActivity.this, 
        eMsg, 
        Toast.LENGTH_LONG).show();
     }});
    
   } finally {
    if(socket != null){
     try {
      socket.close();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   }
  }
 }

}

download filesDownload the files in client side.


More example of Android Network programming
- Bi-directional communication between Client and Server, using ServerSocket, Socket, DataInputStream and DataOutputStream

7 comments:

Anonymous said...

hey, 1.but what if we want to send any image from our android smartphone.?

2.does it works using Internet pack or using IP Address?

Unknown said...

hello

i want to ask a question
when sending an image, how to choose the image at server side
because your video didn't show the choosing step
and I always get the same error msg "Something wrong: null" at client side
I think it's because I havn't choose any image yet

thx

Erik said...

The png file is fixed "android-er_sketch_1000.png" at ExternalStorageDirectory in server, and received file in client will be save as "test.png" at ExternalStorageDirectory.

Unknown said...

Hello,

I'm trying to make app which will share PDF files over local network. Client will try to download PDF through browser. When i try send single file with this tutorial browser show some file content (bytes) and then page reload with "The connection was reset" error.
So my question is if there is possibility to receive file from Java ServerSocket by browser (and browser only) without using client? I would be glad if u help me solve this.
Additionally I would like to list PDFs files as index.html which will run first but that's the other problem.

Unknown said...

yes, Great tutorial.
I did similar to your code except I add a reciving object of BufferReader to read the text coming from the server.
Now, the image was sent successfully to the server But the responce from server not recived ...
i goooooogled and search many days i dont know why.

this is my code, I just copy the class thread ..

private class ClientRxThread extends Thread {

@Override
public void run()
{
// time start here
Log.e("MESSAGE", "Start time");
long startTime = System.nanoTime();
try{
//Connect to socket
Log.e("MESSAGE", "HERE socket object");
socket = new Socket(HOST, PORT);
Log.e("MESSAGE", "class thread and socket done");

ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] imageBytes = baos.toByteArray();
//client_str = baos.toString();
client_str = Base64.encodeToString(imageBytes, Base64.DEFAULT);
Log.e("MESSAGE", "HERE write the pmp as string to var finished");

OutputStream out = socket.getOutputStream();
DataOutputStream dos = null;

try{
dos = new DataOutputStream(out);
dos.writeBytes(client_str);
//receive ACK from (server)
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.e("MESSAGE", "Recieve the ACK from server");
recievedMsg = in.readLine();
Log.e("MESSAGE", "the Ack Recieved successfully");

//Time end here
Log.e("MESSAGE", "End time");
long endTime = System.nanoTime();
long difference = endTime-startTime;
Log.e("MESSAGE", String.valueOf(difference));
String d = "\n The time consumed is: " + String.valueOf(difference/(float) 1000000) + " milliseconds";//in milli seconds
recievedMsg += d;

//Update TextView set TextView Value = ACK from server and the consumed time
Message msg = null;
msg = textview_handler_thread.obtainMessage();
msg.obj = recievedMsg;//+ d;
textview_handler_thread.sendMessage(msg);


}
catch(Exception e)
{e.printStackTrace();}
finally{
if(dos!=null){
dos.flush();
dos.close();
}
}
socket.close();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(MainActivity.this, "Finished",Toast.LENGTH_LONG).show();
}});
}
catch(IOException e){ e.printStackTrace();

final String eMsg = "Something wrong: " + e.getMessage();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(MainActivity.this,
eMsg,
Toast.LENGTH_LONG).show();
}});
}
finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

please let me no your notes about the recieving parts in my code..

Anonymous said...

Heya..I get Something Wrong:null while running this application and i gave proper path to FileTxThread as File file = new File(
Environment.getExternalStorageDirectory(),
"images.jpg"); but its not working for me..please give solve this problem.I stuck on it @Android-er

Unknown said...

I have a doubt. Apart from sending image, I also want to send the image name and show it on another side. I was trying to do it using new socket variable but the application was crashing out.

How would I do that ?
Please Help.