Developing applications for mobile consumption requires facing, and overcoming, some difficult challenges. Apps need to limit their RAM, CPU and battery usage while still performing the required tasks in a reasonable time frame. If too many background tasks are running, the mobile device can become sluggish, with the battery running out very quickly. Coordination with other apps is crucial to keep the device responsive and make the battery last longer.
Networks on mobile devices are also often unstable. Especially in some areas, disconnections are frequent and there are many switches between different network nodes, as well as slow network performance with a high percentage of packet loss. Apps need to be able to handle all the network issues, and if necessary, network activity needs to fail smoothly and resume when the network is available again, automatically if possible.
To support higher resolution mobile devices, the app backend needs to serve high-quality images and videos. Those resources take longer to download, and also consume more CPU and RAM to decode and then display on screen. On the other hand, for a low-resolution mobile device those are wasted resources, because you only need a low-quality resource. So you need to maintain a lot of different versions for each of your resources and then determine which one is most appropriate to serve to each mobile device.
With all that in mind, Cloudinary's latest version of the Android SDK lets you easily implement background upload functionality in your app to ensure the best user experience. If the user is doing something CPU, RAM or power intensive, the uploads can be paused so that the user experience doesn't suffer, and then continue when conditions are more favorable. And with Cloudinary's Dynamic URL feature, the delivered resource can be generated on the fly, eliminating the need to pre-generate all the various versions of your resources for different mobile devices.
The Cloudinary Android SDK v2.0
The Cloudinary SDK works on the principle that Android knows how to manage its own memory, CPU and power, and so relies on the operating system itself doing the prioritization of those limited hardware resources. All uploads are presented as requests to the operating system, which will schedule the uploads accordingly. The Cloudinary SDK hooks into Android's JobScheduler, which makes sure the mobile device works smoothly when running background uploads. If the mobile device is running an older version of Android that does not support the JobScheduler API, then the Cloudinary SDK transparently falls back to using the scheduling engine inside Google Play services.
All upload requests can be finely-tuned using the new policy mechanism, and the SDK can handle global callbacks, even when your app is down, or is running in the background.
Presenting the Cloudinary MediaManager
The Cloudinary Android SDK v2.0 provides you with the MediaManager
class, with methods for configuring and handling all your media-related operations. Use the upload
method to build your request, which is then dispatched to a background queue via the MediaManager's dispatch
method.
The MediaManager's option
method lets you include any upload parameters for Cloudinary, for example, adding the tag user_uploaded
:
MediaManager.get().upload(imageFile) .option("tags", "user_uploaded") .dispatch();
While you are at it, you might want to specify some upload conditions in your request, such as how many times to retry after a recoverable error (e.g., network issues), to limit the upload to a wifi network, or only when the device is charging. The MediaManager's policy
method lets you do just that, overriding the default values for that particular upload request:
MediaManager.get().upload(filePath) .policy(new UploadPolicy.Builder() .maxRetries(7) .requiresCharging(true) .networkPolicy(UploadPolicy.NetworkType.UNMETERED) .build()) .dispatch();
Callbacks
Since all uploads are ultimately run asynchronously by the system, the MediaManager's callback
method provides an easy way to hook into the upload's progress and provide specific code to run at each stage of the upload.
String requestId = MediaManager.get().upload(filePath) .callback(new UploadCallback() { @Override public void onProgress(String requestId, long bytes, long totalBytes) { Double progress = (double) bytes/totalBytes; // post progress to app UI (e.g. progress bar, notification) } @Override public void onSuccess(String requestId, Map resultData) { } ... }) .dispatch();
This method of implementing callbacks won't suffice if your app is down or is running in the background. In this case, you would want to implement global callbacks for your app by registering a new service class that extends the provided ListenerService
class. All upload request callbacks will be routed to your service, which implements the code to run at each stage of the upload.
public class MyClass extends ListenerService { @Override public void onProgress(String requestId, long bytes, long totalBytes) { Double progress = (double) bytes/totalBytes; // post progress to app UI (e.g. progress bar, notification) } @Override public void onSuccess(String requestId, Map resultData) { } ... }
Not only upload
Once your media assets have been uploaded to Cloudinary, you can take advantage of Cloudinary's Dynamic URL feature to deliver your images and videos to your users. Dynamic URLs include instructions telling Cloudinary how to transform and optimize the asset on-the-fly, and then deliver it through a fast CDN to the end user for optimal user experience. There is no need to pre-generate all the different versions you may need for the various devices running your app.
Besides taking care of all your resource uploads directly to your Cloudinary account, the MediaManager class provides the url
method to generate a URL string for accessing resources uploaded to your Cloudinary account:
MediaManager.get().url().generate("sample.jpg") // returns: https://res.cloudinary.com/demo/image/upload/sample.jpg
You can also call the transformation
method to include any transformation instructions in the generated URL:
MediaManager.get().url().transformation(new Transformation() .gravity("face").radius(75).border("10px_solid_grey").crop("crop").chain() .overlay(new Layer().publicId("couple")).width(170).height(150).radius("max").gravity("faces").border("3px_solid_black").crop("thumb").chain() .flags("layer_apply").gravity("north_east")).generate("woman2.jpg");
Summary
The new version of the Cloudinary SDK for Android is a major release that now makes it simple to include upload functionality in your mobile app, and let your users upload their media directly to your Cloudinary account. The SDK takes advantage of Android's built-in functionality when executing the uploads, to make sure that your users enjoy an uninterrupted experience while using your app. Integrating with Cloudinary to upload, manage, and deliver all your app resources is now easier than ever. Make sure you check out the Android integration documentation, and if you don't already have a Cloudinary account, you can sign up for free.