-1

I just started to learn how to create android application and I want to build speed test application. To do that I used this class: Speed Test library

I followed example on github website but problem is that I can't get results to be displayed on my UI. I tried to implement class interface but it resulted with many errors. Does someone knows can it be done? I just want to display results on GUI of my application...

This is code that I am using:

public class SpeedTestTask extends AsyncTask<Void, Void, String> {

        @Override
        protected void onPreExecute() {
            mRunningBar.setVisibility(View.VISIBLE);
        }

        @Override
        protected String doInBackground(Void... params) {

            SpeedTestSocket speedTestSocket = new SpeedTestSocket();
            speedTestSocket.addSpeedTestListener(new ISpeedTestListener() {

                @Override
                public void onDownloadPacketsReceived(int packetSize,
                                                      float transferRateBitPerSeconds,
                                                      float transferRateOctetPerSeconds) {


                    //Log.i(TAG, "download transfer rate  : " + transferRateOctetPerSeconds * 1000 + "MBps");
                    download_result.setText("Download speed  : " + transferRateOctetPerSeconds * 1000 + " MBps");
                }

                @Override
                public void onDownloadError(int errorCode, String message) {
                    Log.i(TAG, "There was error " + errorCode + " Message: " + message);
                }

                @Override
                public void onUploadPacketsReceived(int packetSize,
                                                    float transferRateBitPerSeconds,
                                                    float transferRateOctetPerSeconds) {
                    download_result.setText("Upload speed (upload)  : " + transferRateOctetPerSeconds * 1000 + " MBps");
                }

                @Override
                public void onUploadError(int errorCode, String message) {
                  //  Log.i(TAG, "Upload error " + errorCode + " occured with message : " + message);
                    download_result.setText("Upload error (upload) " + errorCode + " Message: " + message);
                }

                @Override
                public void onDownloadProgress(int percent) {
                }

                @Override
                public void onUploadProgress(int percent) {
                }

            });

           speedTestSocket.startDownload("ipv4.intuxication.testdebit.info", 80,"/fichiers/10Mo.dat");
            speedTestSocket.startUpload("1.testdebit.info",
                    80, "/", 10000000);



            return null;
        }

        @Override
        protected void onPostExecute(String result) {
          //  download_result.setText(result);
            mRunningBar.setVisibility(View.GONE);

        }
    }
jureispro
  • 1,342
  • 5
  • 22
  • 43
  • Check this http://stackoverflow.com/questions/14253421/how-one-interface-can-be-used-for-different-background-android-tasks/14376233#14376233 – Pragnani Mar 21 '16 at 10:28

5 Answers5

2

A quote from the AsyncTask documentation, regarding updating progress indicators:

onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.

I think this will be ideal for your use case.

Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28
1

whatever you have written in doInBackground is executed in a non-UI thread. If you want to update UI elements then you have to do it in onPostExecute which is executed in the UI thread.

EDIT

If you have to update UI elements from any other thread then you can do the following

runOnUiThread(new Runnable() {
     public void run() {
        download_result.setText("Download speed  : " + transferRateOctetPerSeconds * 1000 + " MBps");

     }
});

EDIT 2

I stand corrected. You can also use onProgressUpdate() as some users mentioned here to manipulate UI elements. I think using onProgressUpdate would be the better option than what I have suggested here

Much Overflow
  • 3,142
  • 1
  • 23
  • 40
  • Thanks for fast answer @MuchOverflow. So I just move my code to onPostExecute? – jureispro Mar 21 '16 at 10:26
  • In your case I don't think it is possible too since you have to do network operations. Please check my updated answer – Much Overflow Mar 21 '16 at 10:29
  • 1
    `you have to do it in onPostExecute`<< this is actually not true. You can update the `Views` in `onProgressUpdate(Progress... values)` which is invoked on the main thread – Droidman Mar 21 '16 at 10:36
1

make all your internet request in doInBackground and update your layout ui in the postexcute. All of preExcute, postExcute and onProgress are in the main thread (ui thread) where you can update UI.

Helmi
  • 90
  • 5
0

The publishProgress and onProgressUpdate callbacks are what you are probably looking for. Example with download only:

@Override
public void onDownloadProgress(int percent) {
   SpeedTestTask.this.publishProgress(percent);
}

Override the onProgressUpdate callback of your AsyncTask:

@Override
 protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
        // update your Views here
 }

If you want to publish both the download and the upload progress, you need a way for your onProgressUpdate callback to know which kind of progress is being updated. Since the parameter it takes is an array (Integer... values), you could use a different index for each particular kind of progress. Example:

 @Override
 public void onDownloadProgress(int percent) {
  // using the index 0 for download
  SpeedTestTask.this.publishProgress(percent, -1);
}

Other callback:

 @Override
 public void onUploadProgress(int percent) {
 // using the index 1 for upload
 SpeedTestTask.this.publishProgress(-1, upload);
}

Then:

@Override
protected void onProgressUpdate(Integer... values) {
  super.onProgressUpdate(values);
    if(values[0] != -1)
      // download
    else
      //upload
}

EDIT: since I don't know whether the value -1 can be passed to your callback by the library, I took it as an example. Probably it is safer to use some other constant to indicate that there's no value at the corresponding index.

Droidman
  • 11,485
  • 17
  • 93
  • 141
  • Thank you for your comment @Droidman . I tried your code but I got error on "onDownloadProgress" and on "onUploadProgress" . It says that ASyncTask cannot be applied for array of int (int [] ) – jureispro Mar 21 '16 at 11:06
  • @jureispro my bad, I have updated the code. Note: your `AsyncTask`'s parameterization should now look like `extends AsyncTask`, otherwise it won't work – Droidman Mar 21 '16 at 11:15
  • thank you for all your. I have impemented your code and it is working. I am getting download progoress. Problem is that I want download speed. Can it be done usiing methods onDownloadPacketsReceived and onUploadPacketsReceived – jureispro Mar 21 '16 at 11:26
  • @jureispro I don't know all the aspects of the library you are using and wrote this answer to give you some basic example about how to update `Views` from an `AsyncTask`. Basically you can use this approach for any data you want, In this case I suggest you to define constant flags that will indicate what kind of data you are receiving in the `onProgressUpdate()` callback – Droidman Mar 21 '16 at 12:14
  • @jureispro to elaborate a bit more: your call will then look like `publishProgress(flag, value)` where `flag` is a constant telling you *what* you are getting and the `value` is the *actual value* like percent or anything else – Droidman Mar 21 '16 at 12:18
0

Do not update any UI element in background thread. AsyncTask: onOpreExecute -- > Runs on main thread.doInBackground --> Runs on worker thread. onPostExecute --> Runs on main thread.

Since you are updating

download_result.setText("Upload error (upload) " + errorCode + " Message: " + message);

in doInBackground, your application will crash once u have some exception.

Do it in Main thread.

Isham
  • 424
  • 4
  • 14