问题
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