Progress bar implementation with write method of dataoutputstream

南笙酒味 提交于 2021-02-08 09:26:06

问题


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");
          }
        });
}

回答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);



回答2:


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! :)




回答3:


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);


来源:https://stackoverflow.com/questions/17279521/progress-bar-implementation-with-write-method-of-dataoutputstream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!