code: @SuppressLint("NewApi")
      protected void upload() throws Exception {
  
          Logger.debug(LOG_TAG, "Starting upload task with ID " + params.id);
  
          try {
              getSuccessfullyUploadedFiles().clear();
              uploadedBytes = 0;
              totalBytes = getBodyLength();
  
              if (httpParams.isCustomUserAgentDefined()) {
                  httpParams.addHeader("User-Agent", httpParams.customUserAgent);
              } else {
                  httpParams.addHeader("User-Agent", "AndroidUploadService/" + BuildConfig.VERSION_NAME);
              }
  
              connection = UploadService.HTTP_STACK
                      .createNewConnection(httpParams.method, params.serverUrl)
                      .setHeaders(httpParams.getRequestHeaders())
                      .setTotalBodyBytes(totalBytes, httpParams.usesFixedLengthStreamingMode);
  
              final ServerResponse response = connection.getResponse(this);
              Logger.debug(LOG_TAG, "Server responded with HTTP " + response.getHttpCode()
                              + " to upload with ID: " + params.id);
  
              // Broadcast completion only if the user has not cancelled the operation.
              // It may happen that when the body is not completely written and the client
              // closes the connection, no exception is thrown here, and the server responds
              // with an HTTP status code. Without this, what happened was that completion was
              // broadcasted and then the cancellation. That behaviour was not desirable as the
              // library user couldn't execute code on user cancellation.
              if (shouldContinue) {
                  broadcastCompleted(response);
              }
  
          } finally {
              if (connection != null)
                  connection.close();
          }
      }
docs: Implementation of the upload logic.<br>
  If you want to take advantage of the automations which Android Upload Service provides,
  do not override or change the implementation of this method in your subclasses. If you do,
  you have full control on how the upload is done, so for example you can use your custom
  http stack, but you have to manually setup the request to the server with everything you
  set in your {@link HttpUploadRequest} subclass and to get the response from the server.
  
  @throws Exception if an error occurs