Skip to content

Monitoring upload status

Alex Gotev edited this page Apr 5, 2020 · 41 revisions

This is an old documentation, referring to 3.x version, which is not developed anymore. Use it at your own risk. It's suggested to migrate to 4.x. New docs: https://github.com/gotev/android-upload-service/wiki/Monitor-Uploads

To listen for the status of the upload tasks, you have the following choices:

Broadcast receiver inside Service or Activity

Create a new subclass of UploadServiceBroadcastReceiver inside a Service or Activity. For detailed instructions on how to to register and unregister the broadcast receiver, refer to the register and unregister method javadocs.

private UploadServiceBroadcastReceiver broadcastReceiver = new UploadServiceBroadcastReceiver() {
    @Override
    public void onProgress(Context context, UploadInfo uploadInfo) {
        // your implementation
    }

    @Override
    public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse, Exception exception) {
        // your implementation
    }

    @Override
    public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
        // your implementation
    }

    @Override
    public void onCancelled(Context context, UploadInfo uploadInfo) {
        // your implementation
    }
};

If you override shouldAcceptEventFrom method (available in 3.3+), you can filter out events based on your custom business logic. If you return true, the event will be accepted and processed, otherwise it will be discarded immediately. This is used in UploadServiceSingleBroadcastReceiver to process only events for a particular upload ID.

Global Broadcast receiver

To listen for upload status globally in your app, create a new class (e.g. MyReceiver) which extends UploadServiceBroadcastReceiver, add your business logic in it and then register it as a broadcast receiver in your manifest (as shown below), with the intent filter com.yourcompany.yourapp.uploadservice.broadcast.status. This way you can listen for events independently from your activities and services. Change com.yourcompany.yourapp with whatever you have set as UploadService.NAMESPACE in the initial setup:

<receiver android:name="MyReceiver" android:exported="false">
  <intent-filter>
      <action android:name="com.yourcompany.yourapp.uploadservice.broadcast.status" />
  </intent-filter>
</receiver>

MyReceiver.java

public class MyReceiver extends UploadServiceBroadcastReceiver {
    @Override
    public void onProgress(Context context, UploadInfo uploadInfo) {
        // your implementation
    }

    @Override
    public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse, Exception exception) {
        // your implementation
    }

    @Override
    public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
        // your implementation
    }

    @Override
    public void onCancelled(Context context, UploadInfo uploadInfo) {
        // your implementation
    }
}

You can also override shouldAcceptEventFrom method to filter incoming events.

Single Upload Broadcast receiver

There are times when you want to monitor only one particular upload task using a broadcast receiver. This can come handy to prevent you from writing some boilerplate code.

For 3.3+:

public class YourActivity extends Activity implements UploadStatusDelegate {

    private static final String TAG = "AndroidUploadService";

    private UploadServiceSingleBroadcastReceiver uploadReceiver;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        uploadReceiver = new UploadServiceSingleBroadcastReceiver(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        uploadReceiver.register(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        uploadReceiver.unregister(this);
    }

    public void uploadMultipart() {
        try {
            String uploadId = UUID.randomUUID().toString();
            uploadReceiver.setUploadID(uploadId);

            new MultipartUploadRequest(this, uploadId, "http://upload.server.com/path")
                    .addFileToUpload("/absolute/path/to/your/file", "your-param-name")
                    .setNotificationConfig(new UploadNotificationConfig())
                    .setMaxRetries(2)
                    .startUpload();

        } catch (Exception exc) {
            Log.e(TAG, exc.getMessage(), exc);
        }
    }

    @Override
    public void onProgress(Context context, UploadInfo uploadInfo) {
        // your implementation
    }

    @Override
    public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse, Exception exception) {
        // your implementation
    }

    @Override
    public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
        // your implementation
    }

    @Override
    public void onCancelled(Context context, UploadInfo uploadInfo) {
        // your implementation
    }
}

For older versions < 3.3, you have to manually add the following class:

public class SingleUploadBroadcastReceiver extends UploadServiceBroadcastReceiver {

    private String mUploadID;
    private UploadStatusDelegate mDelegate;

    public void setUploadID(String uploadID) {
        mUploadID = uploadID;
    }

    public void setDelegate(UploadStatusDelegate delegate) {
        mDelegate = delegate;
    }

    public SingleUploadBroadcastReceiver() {
        super();
    }

    @Override
    public void onProgress(Context context, UploadInfo uploadInfo) {
        if (uploadInfo.getUploadId().equals(mUploadID) && mDelegate != null) {
            mDelegate.onProgress(context, uploadInfo);
        }
    }

    @Override
    public void onError(Context context, UploadInfo uploadInfo, Exception exception) {
        if (uploadInfo.getUploadId().equals(mUploadID) && mDelegate != null) {
            mDelegate.onError(context, uploadInfo, exception);
        }
    }

    @Override
    public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
        if (uploadInfo.getUploadId().equals(mUploadID) && mDelegate != null) {
            mDelegate.onCompleted(context, uploadInfo, serverResponse);
        }
    }

    @Override
    public void onCancelled(Context context, UploadInfo uploadInfo) {
        if (uploadInfo.getUploadId().equals(mUploadID) && mDelegate != null) {
            mDelegate.onCancelled(context, uploadInfo);
        }
    }
}

It's used like this:

public class YourActivity extends Activity implements UploadStatusDelegate {

    private static final String TAG = "AndroidUploadService";

    private final SingleUploadBroadcastReceiver uploadReceiver =
            new SingleUploadBroadcastReceiver();

    @Override
    protected void onResume() {
        super.onResume();
        uploadReceiver.register(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        uploadReceiver.unregister(this);
    }

    public void uploadMultipart() {
        try {
            String uploadId = UUID.randomUUID().toString();
            uploadReceiver.setDelegate(this);
            uploadReceiver.setUploadID(uploadId);

            new MultipartUploadRequest(this, uploadId, "http://upload.server.com/path")
                    .addFileToUpload("/absolute/path/to/your/file", "your-param-name")
                    .setNotificationConfig(new UploadNotificationConfig())
                    .setMaxRetries(2)
                    .startUpload();

        } catch (Exception exc) {
            Log.e(TAG, exc.getMessage(), exc);
        }
    }

    @Override
    public void onProgress(Context context, UploadInfo uploadInfo) {
        // your implementation
    }

    @Override
    public void onError(Context context, UploadInfo uploadInfo, Exception exception) {
        // your implementation
    }

    @Override
    public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
        // your implementation
    }

    @Override
    public void onCancelled(Context context, UploadInfo uploadInfo) {
        // your implementation
    }
}

Delegates

Not recommended and not supported in 4.+ versions. Details: https://github.com/gotev/android-upload-service/issues/450

Starting from release 3.0, you can handle upload status events using also delegates. Beware that delegates works only if your activity is always in the foreground and never gets rotated. Once your activity gets destroyed and recreated, the callback is lost forever. This is how you set a delegate for an upload request:

public void uploadMultipart(final Context context) {
    try {
        String uploadId =
          new MultipartUploadRequest(context, "http://upload.server.com/path")
            .addFileToUpload("/absolute/path/to/your/file", "your-param-name")
            .setNotificationConfig(new UploadNotificationConfig())
            .setMaxRetries(2)
            .setDelegate(new UploadStatusDelegate() {
                 @Override
                 public void onProgress(Context context, UploadInfo uploadInfo) {
                     // your code here
                 }

                 @Override
                 public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
                                     Exception exception) {
                    // your code here
                 }

                 @Override
                 public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
                    // your code here
                    // if you have mapped your server response to a POJO, you can easily get it:
                    // YourClass obj = new Gson().fromJson(serverResponse.getBodyAsString(), YourClass.class);

                 }

                 @Override
                 public void onCancelled(Context context, UploadInfo uploadInfo) {
                    // your code here
                 }
            })
            .startUpload();
    } catch (Exception exc) {
        Log.e("AndroidUploadService", exc.getMessage(), exc);
    }
}

When you set the delegate for an UploadRequest, all the events will be pushed to it and will not be broadcasted. So, if you want to handle events using UploadServiceBroadcastReceiver, just do not invoke the setDelegate method. UploadServiceBroadcastReceiver gives you more flexibility (you can generate upload requests in one point of your code and react to events in another service or activity for example), while the delegate is simpler if all you need to do is handle all the events inside the same activity or service which originated the request.

The recommended way to use delegates inside Activities or Services is to implement the UploadStatusDelegate interface in your Activities or Services instead of using the anonymous inner class, to prevent variable out of scope problems.

If you set the delegate inside an activity, pay attention to its lifecycle, e.g. if you create a request with a delegate inside an activity and then you close it, the request will run in the background, but no callback methods will be invoked, because the delegate has been created inside the activity, which no longer exists. Delegates works best when used inside a service or an activity from which the user never goes away during the entire upload process. If this is not your case, I suggest you to use one of the following approaches.