BretzelPretzel
BretzelPretzel

Reputation: 119

Android - basic download progress text

I found a snippet online for showing a download's progress. The error I'm getting is android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. My goal is to have the phone download a file and then when completed, switch to the chaptermenu intent

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.widget.TextView;

public class CheckDownload extends Activity {

/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle SavedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(SavedInstanceState);
    setContentView(R.layout.downloadscreen);
    Thread timer = new Thread() {
        public void run() {
            try {
                // set the download URL, a url that points to a file on the
                // internet
                // this is the file to be downloaded
                URL url = new URL(
                        "http://www.android.com/media/wallpaper/gif/android_logo.gif");

                // create the new connection
                HttpURLConnection urlConnection = (HttpURLConnection) url
                        .openConnection();

                // set up some things on the connection
                urlConnection.setRequestMethod("GET");
                urlConnection.setDoOutput(true);

                // and connect!
                urlConnection.connect();

                // set the path where we want to save the file
                // in this case, going to save it on the root directory of
                // the
                // sd card.
                File SDCardRoot = Environment.getExternalStorageDirectory();
                // create a new file, specifying the path, and the filename
                // which we want to save the file as.
                File file = new File(SDCardRoot, "android_logo.gif");

                // this will be used to write the downloaded data into the
                // file we created
                FileOutputStream fileOutput = new FileOutputStream(file);

                // this will be used in reading the data from the internet
                InputStream inputStream = urlConnection.getInputStream();

                // this is the total size of the file
                int totalSize = urlConnection.getContentLength();
                // variable to store total downloaded bytes
                int downloadedSize = 0;

                // create a buffer...
                byte[] buffer = new byte[1024];
                int bufferLength = 0; // used to store a temporary size of
                                        // the buffer

                // now, read through the input buffer and write the contents
                // to the file
                while ((bufferLength = inputStream.read(buffer)) > 0) {
                    // add the data in the buffer to the file in the file
                    // output stream (the file on the sd card
                    fileOutput.write(buffer, 0, bufferLength);
                    // add up the size so we know how much is downloaded
                    downloadedSize += bufferLength;
                    // this is where you would do something to report the
                    // prgress, like this maybe
                    updateProgress(downloadedSize, totalSize);

                }
                // close the output stream when done
                fileOutput.close();

                // catch some possible errors...
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                Intent chapterMenuIntentObject = new Intent(
                        "com.blah.blah.CHAPTERMENU");
                startActivity(chapterMenuIntentObject);
            }
        }

    };
    timer.start();
}

public void updateProgress(int downloadedSize, int totalSize) {
    int percentage = downloadedSize / totalSize * 100;
    String stringy = "Download Progress: " + percentage + "%";
    TextView textytext = (TextView) findViewById(R.id.downloadscreentextview);
    textytext.setText(stringy);
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    finish();
}

}

Upvotes: 2

Views: 2192

Answers (2)

Billy Pham
Billy Pham

Reputation: 138

One easier way to do this is to use runOnUIThread(Runnable) function. This is a function of Activity class for updating UI. I find using it more convenient than creating handlers/messages for communicating with UI thread. Your code can be changed to (I have not test yet!):

public void updateProgress(int downloadedSize, int totalSize) {
runOnUiThread(new Runnable() {
    public void run() {
        int percentage = downloadedSize / totalSize * 100;
        String stringy = "Download Progress: " + percentage + "%";
    TextView textytext = (TextView) findViewById(R.id.downloadscreentextview);
    textytext.setText(stringy);
}});
}

Let me know if you have any error.

Upvotes: 4

sat
sat

Reputation: 41076

You are trying to update the progress from worker(or background thread) where it doesnot get reference to your views. It has to be done on UI thread.
Try using AsynTask , makes life easier with threads.
http://developer.android.com/reference/android/os/AsyncTask.html

or

if you want to stick with normal threads, Check this code,
http://huuah.com/android-progress-bar-and-thread-updating/
You might have to use messageHandler to send message to progressbar, and then update.

Upvotes: 2

Related Questions