1

Is it possible to incorporate a horizontal progress bar in the following code? I was thinking os AsyncTask but then I realized, I can't pass an integer value to ProgressUpdate() method inside doInBackground(). Please help!

public void sendFileDOS() throws FileNotFoundException {
    runOnUiThread( new Runnable() {
          @Override
          public void run() {
              registerLog("Sending. . . Please wait. . .");
          }
        });
    final long startTime = System.currentTimeMillis();
    final File myFile= new File(filePath); //sdcard/DCIM.JPG
    byte[] mybytearray = new byte[(int) myFile.length()];
    FileInputStream fis = new FileInputStream(myFile);  
    BufferedInputStream bis = new BufferedInputStream(fis);
    DataInputStream dis = new DataInputStream(bis);
    try {
        dis.readFully(mybytearray, 0, mybytearray.length);
        OutputStream os = socket.getOutputStream();
        //Sending file name and file size to the server  
        DataOutputStream dos = new DataOutputStream(os);     
        dos.writeUTF(myFile.getName());     
        dos.writeLong(mybytearray.length);     
        dos.write(mybytearray, 0, mybytearray.length);     
        dos.flush();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    runOnUiThread( new Runnable() {
          @Override
          public void run() {
              long estimatedTime = (System.currentTimeMillis() - startTime)/1000;
              registerLog("File successfully sent");
              registerLog("File size: "+myFile.length()/1000+" KBytes");
              registerLog("Elapsed time: "+estimatedTime+" sec. (approx)");
              registerLog("Server stopped. Please restart for another session.");
              final Button startServerButton=(Button)findViewById(R.id.button1);
              startServerButton.setText("Restart file server");
          }
        });
}
Vinit Shandilya
  • 1,643
  • 5
  • 24
  • 44

3 Answers3

4

For those facing similar issues, here is the working method for file transfer using Data Output Stream. The main idea was to break file into multiple chunks (i have divided into 100 chunks) and write to DOS in a while loop. Use your loop counter to update progress bar. Make sure to update progress bar in the main UI thread or else the application would crash. Here goes the code:

public void sendFileDOS() throws FileNotFoundException {
    runOnUiThread( new Runnable() {
          @Override
          public void run() {
              registerLog("Sending. . . Please wait. . .");
          }
        });
    final long startTime = System.currentTimeMillis();
    final File myFile= new File(filePath); //sdcard/DCIM.JPG
    byte[] mybytearray = new byte[(int) myFile.length()];
    FileInputStream fis = new FileInputStream(myFile);  
    BufferedInputStream bis = new BufferedInputStream(fis);
    DataInputStream dis = new DataInputStream(bis);
    try {
        dis.readFully(mybytearray, 0, mybytearray.length);
        OutputStream os = socket.getOutputStream();
        //Sending file name and file size to the server  
        DataOutputStream dos = new DataOutputStream(os);     
        dos.writeUTF(myFile.getName());     
        dos.writeLong(mybytearray.length);     
        int i = 0;
        final ProgressBar myProgBar=(ProgressBar)findViewById(R.id.progress_bar);
        while (i<100) {
            dos.write(mybytearray, i*(mybytearray.length/100), mybytearray.length/100);
            final int c=i;
            runOnUiThread( new Runnable() {
                  @Override
                  public void run() {
                      registerLog("Completed: "+c+"%");
                      myProgBar.setProgress(c);
                  }
                });
            i++;
        }    
        dos.flush();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    runOnUiThread( new Runnable() {
          @Override
          public void run() {
              long estimatedTime = (System.currentTimeMillis() - startTime)/1000;
              registerLog("File successfully sent");
              registerLog("File size: "+myFile.length()/1000+" KBytes");
              registerLog("Elapsed time: "+estimatedTime+" sec. (approx)");
              registerLog("Server stopped. Please restart for another session.");
              final Button startServerButton=(Button)findViewById(R.id.button1);
              startServerButton.setText("Restart file server");
          }
        });
}

Cheers! :)

Vinit Shandilya
  • 1,643
  • 5
  • 24
  • 44
  • looks great can I update the value like instead of i++ make it more larger like i += 25 so it will be divided in to 4 chunks? – Mihae Kheel Apr 03 '20 at 16:00
1

You can use AsyncTask that gets a progress bar like that:

public abstract class BaseTask extends AsyncTask<String, Integer, String> 
{   
    private ProgressBar    m_progressBar;

    protected BaseTask(ProgressBar p)
    {
        m_progressBar = p;
    }

    @Override
    protected void onPreExecute()
    {   
        if (m_progressBar != null)
        {
            m_progressBar.setProgress(0);
        }
    }

    @Override
    protected void onPostExecute(String result)
    {   
        if (m_progressBar != null)
            m_progressBar.setVisibility(ProgressBar.GONE);
    }

    public void OnProgress(int prog)
    {
        if (m_progressBar != null)
        {
            m_progressBar.setProgress(prog);
        }
    }
}

To add a progress bar in your xml:

<ProgressBar
 android:id="@+id/progressBar"
 style="?android:attr/progressBarStyleHorizontal"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_margin="10dp" />

To initialize the progress bar in your code:

ProgressBar p = (ProgressBar)findViewById(R.id.progressBar);
p.setVisibility(ProgressBar.VISIBLE);
p.setMax(100);
Kostia
  • 271
  • 1
  • 9
0

I can't pass an integer value to ProgressUpdate() method inside doInBackground()

Yes, you can !

Use publishProgress with the required parameters inside doInBackground to trigger onProgressUpdate:

final class MyTask extends AsyncTask<Void, Integer, Void> {

    private final ProgressBar progress;

    public MyTask(final ProgressBar progress) {
        this.progress = progress;
    }

    @Override
    protected void onPreExecute() {
        progress.setMax(100);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected Void doInBackground(final Void... params) {
        ...
        int progress_val = // What ever you want
        publishProgress(progress_val);  // Here we trigger 'onProgressUpdate' 
                                        // with the updated integer as parameter
        return null;
    }

    @Override
    protected void onProgressUpdate(final Integer... values) {
        progress.incrementProgressBy(values[0]);  // Here we update the bar
    }

    @Override
    protected void onPostExecute(final Void result) {
        parent.finish();
    }
}

EDIT :

Suggestion to write by blocks:

int i = 0;
int offset = 0;
int buflen = mybytearray.length/100;
while (i<100) {
    dos.write(mybytearray, offset, buflen);
    offset += buflen;
    i++;
}
dos.write(mybytearray, offset, mybytearray.length%100);
Gauthier Boaglio
  • 10,054
  • 5
  • 48
  • 85
  • Thanx a lot Golgauth! Sorry for one silly question though: dos.write(mybytearray, 0, mybytearray.length) is writing file at one go. How can I select an intermediate value to increment my progress bar by that value? Can you please modify my code? – Vinit Shandilya Jun 24 '13 at 16:25
  • Write in a loop, by blocks of `mybytearray.length/100`, for example (!This is integer division, so there will be a rest). Then at each iteration, increment... Do not forget to write the rest right after the loop ends (`rest=mybytearray.length%100`). – Gauthier Boaglio Jun 24 '13 at 16:47
  • Let me modify my code and I'll get back to you! Thanks again. :) – Vinit Shandilya Jun 24 '13 at 16:56
  • Hi Golgauth! As suggested by you, I tried to implement it. Please refer to Update section above. Can you please help? I think this is the case of exceeding data off the limits.. – Vinit Shandilya Jun 24 '13 at 17:35
  • I think your offset was wrong... I made a proposition at the end of my answer. If the app crashes, there might be an exception somewhere in your logcat. If this is the case, please show it to me (by editing your question, not my answer ;) – Gauthier Boaglio Jun 24 '13 at 18:13
  • Extremely sorry for that! I'm still new to stackoverflow! Btw, I solved my issue. I removed my "rest" block and the code started working like a charm! I can't understand the reason, but it's working fine (I've tested it and re-tested it). Only one problem remains though! I can't transfer file size more than 65 MB. Any work around? Please find my updated code in edit section. Added a progress bar too! Thanks for your help! :) – Vinit Shandilya Jun 24 '13 at 19:52
  • Glad to hear that! Btw: better create an answer to your own question and remove the 'edit' part of your question, please. This is more clear for anyone who wants to get inspiration from it. Thanks ;) - and I can upvote for sharing... – Gauthier Boaglio Jun 24 '13 at 19:59