Android image and video upload

Cloudinary provides support for uploading media directly from your mobile application to your Cloudinary account, without going through your servers first. This method allows for faster uploading and a better user experience. It also reduces load on your servers and reduces the complexity of your applications.

You can also take advantage of upload presets for predefining upload parameters. For details on all the available upload parameters, see the Upload Images and Upload Videos documentation and the Upload method of the Upload API Reference.

For security reasons, mobile applications shouldn't contain your Cloudinary account credentials, and so they cannot freely upload resources to your account. You can use a signed upload, but that requires generating an authentication signature on your backend. In most cases, you will probably use unsigned uploads that generally provide all the functionality you need for your mobile application, while restricting upload options that require more security.

MediaManager upload method

The upload request is managed by the MediaManager's upload method, which accepts the file to upload as its only parameter. The file can be specified as either: the path to the local file, a byte array, a Resource ID, or a URI.

The upload request is then dispatched to a background queue via the MediaManager's dispatch method, optionally with a set of fully customizable rules and limits letting you choose when each upload request should actually run and how. Requests are automatically rescheduled to be retried later if a recoverable error is encountered (e.g. network disconnections, timeouts). The upload results are dispatched asynchronously and global callbacks can be defined, as well as specific callbacks per request.

The following simple example uploads an image called imageFile.jpg using the default settings:

String requestId = MediaManager.get().upload("imageFile.jpg").dispatch();

Signed upload

Signed uploads require you to generate an authentication signature on your backend, and as such, Android signed upload with backend support should be implemented in conjunction with one of Cloudinary's backend frameworks (Java, .NET, etc). The various backend frameworks implement helpers to be used in conjunction with Android, as well as automatically generate the authentication signature for the upload.

For an example of client side upload with signature generation on the backend, see the signed upload Android sample project.

Unsigned upload

Unsigned upload is an option for performing upload without the need to generate a signature on your backend. Unsigned upload options are controlled by an upload preset: to use this feature, you first need to enable unsigned uploading for your Cloudinary account from the Upload Settings page.

An upload preset is used to define which upload options will be applied to images that are uploaded unsigned with that preset specified. You can edit the preset at any point in time (or create additional upload presets), to define the parameters that will be used for all images that are uploaded unsigned from your mobile application.

The following simple example uploads an image called imageFile.jpg using an upload preset called sample_preset:

String requestId = MediaManager.get().upload("imageFile.jpg")
   .unsigned("sample_preset")
   .dispatch();

The method returns a requestId that can be used to identify the upload request.

Upload options

Use the MediaManager's option method to add an upload parameter to the upload request. The method accepts 2 parameters: the first specifies the name of the upload parameter and the second its value. For example, to upload an image called samplepic.jpg and set thepublic_id option to sample1:

String requestId = MediaManager.get().upload("samplepic.jpg")
   .unsigned("sample_preset")
   .option("public_id", "sample1")
   .dispatch();

If you want to include more than one upload parameter in the request you can either chain another option method for each parameter, or use the MediaManager's options method to pass a Map of all parameters. Note that if you use the options method it must come before any other method passing upload parameters.

For example, to upload an image called dog.jpg, set the public_id to MyDog, and add the tag animal:

String requestId = MediaManager.get().upload("dog.jpg")
   .unsigned("preset1")
   .option("public_id", "MyDog")
   .option("tags", "animal")
   .dispatch();

Which is equivalent to:

Map<String, Object> options = new HashMap<>();
options.put("public_id", "MyDog");
options.put("tags", "animal");
String requestId = MediaManager.get().upload(imageFile)
   .options(options)
   .unsigned("preset1")
   .dispatch();

Note: For security reasons, only this restricted set of upload options can be specified directly when performing unsigned upload calls. All other upload parameters can only be specified within the upload preset.

Callbacks

You can track upload progress by getting callbacks on the the following events: onStart, onProgress, onSuccess, onError, and onReschedule. The upload results are dispatched asynchronously, with 2 options for adding callback functionality:

  1. Implement the UploadCallBack interface for specific callbacks per request.
  2. Extend the ListenerService for global callbacks, even when your app has been shut down, or is running in the background.

Implement the UploadCallBack interface

Create a class that implements the UploadCallBack interface, and add functionality by overriding specific callback events with your own code. Use the MediaManager's callback method to add the name of an instance of your class to the upload request. The callback is specific to the current upload request only. The following example includes some example code for the onProgress event:

String requestId = MediaManager.get().upload(filePath).callback(new UploadCallback() {
  @Override
  public void onStart(String requestId) {
    // your code here
  }
  @Override
  public void onProgress(String requestId, long bytes, long totalBytes) {
            // example code starts here
    Double progress = (double) bytes/totalBytes;
    // post progress to app UI (e.g. progress bar, notification)
            // example code ends here                   
  }
  @Override
  public void onSuccess(String requestId, Map resultData) {
     // your code here
  }
  @Override
  public void onError(String requestId, ErrorInfo error) {
     // your code here
  }
  @Override
  public void onReschedule(String requestId, ErrorInfo error) {
    // your code here
  }})
  .dispatch();

Extend the ListenerService

Extend the ListnerService service, and add functionality by overriding specific callback events with your own code. Callback events for all upload requests will be routed to your service, even when your app has been shut down, or is running in the background.

The following example includes some example code extending the ListnerService :

public class UploadListner extends ListnerService {
  @Override
  public void onStart(String requestId) {
    // your code here
  }
  @Override
  public void onProgress(String requestId, long bytes, long totalBytes) {
           // example code starts here
    Double progress = (double) bytes/totalBytes;
    // post progress to app UI (e.g. progress bar, notification)
            // example code ends here                       
  }
  @Override
  public void onSuccess(String requestId, Map resultData) {
     // your code here
  }
  @Override
  public void onError(String requestId, ErrorInfo error) {
     // your code here
  }
  @Override
  public void onReschedule(String requestId, ErrorInfo error) {
    // your code here
  }
}

Make sure to register your class in the manifest, with both a service tag and a cloudinaryCallbackService meta-data tag, both within the application tag.

For example, if your class is called UploadListner:

<application
  ...
  <service 
    android:name="com.myapp.UploadListner" />
  <meta-data
    android:name="cloudinaryCallbackService"
    android:value="com.myapp.UploadListner" />
  ...
</application>

Upload policy

Use the MediaManager's policy method to configure an upload request to run under specific circumstances. The policy is defined by an object of type UploadPolicy that has the following properties:

Property Type Description
networkPolicy NetworkType Limit the upload to a specific type of network connection
Possible values:
-UploadPolicy.NetworkType.NONE
-UploadPolicy.NetworkType.ANY(default)
-UploadPolicy.NetworkType.UNMETERED
requiresCharging boolean Upload only when the mobile device is currently charging. Default: false
requiresIdle boolean Upload only when the mobile device is currently idle. Default: false
maxRetries int The maximum number of times to retry the upload. Default: 5
backoffCriteria backoffMillis, backoffPolicy The backoff policy to implement before retrying.
    backoffMillis long The time to wait in milliseconds before retrying. Default: 120000 (2 minutes)
    backoffPolicy BackoffPolicy Whether the time between successive upload attempts increases linearly (2, 4, 6, 8, etc) or exponentially (2, 4, 8, 16, etc)
Possible values:
-UploadPolicy.BackoffPolicy.LINEAR
-UploadPolicy.BackoffPolicy.EXPONENTIAL (default)

For example, to request that a specific upload runs only on an unmetered network (e.g. wifi), with a maximum of 7 retries, and waits 5 minutes before retrying with a linear backoff policy:

String requestId = MediaManager.get().upload(imageFile)
   .unsigned("sample_app_preset")
   .policy(new UploadPolicy.Builder()
      .maxRetries(7)
      .backoffCriteria(300000, UploadPolicy.BackoffPolicy.LINEAR)
      .networkPolicy(UploadPolicy.NetworkType.UNMETERED)
      .build())
   .dispatch();

Global policy

To override the default policy for all upload requests, use the setGlobalUploadPolicy method of the MediaManager class. Call the method before using any other methods of the MediaManager class, preferably in Application.onCreate(). The global policy is defined by an object of type GlobalUploadPolicy, which inherits the same properties as the UploadPolicy object described above, with one additional property:

Property Type Description
maxConcurrentRequests int The maximum number of upload requests that can run concurrently. Default: 5

For example, to set the default for upload requests to run only on an unmetered network (e.g. wifi), with no more than 3 upload requests to run concurrently:

MediaManager.get().setGlobalUploadPolicy(
   new GlobalUploadPolicy.Builder()
      .maxConcurrentRequests(3)
      .networkPolicy(UploadPolicy.NetworkType.UNMETERED)
   .build());